问题转换:将需求确认,结合已学知识,进行匹配->改进。列表的扁平化本质就是树的前序遍历,不过不需要父节点而已。树的前序遍历可以递归实现,也可以迭代实现,一题多解,方便理解树的递归结构,前序遍历的多递归本质!才能对里面的知识点融汇贯通,举一反三!
// 扁平化嵌套列表迭代器。
public class NestedIterator implements Iterator<Integer> {
List<Integer> arr = new ArrayList<>();
int idx = 0;
// 层层嵌套,就像是学过的树结构,integer为叶子节点,list为父节点。
// 扁平化的过程就像是前序遍历一样。
public NestedIterator(List<NestedInteger> nestedList) {
// 递归拿元素。
dfs(nestedList);
}
// 树的前序遍历。
private void dfs(List<NestedInteger> nestedList) {
// 多个平行递归,树就是多支子树递归结构。
for (NestedInteger nest : nestedList) {
if (nest.isInteger()) arr.add(nest.getInteger());
else dfs(nest.getList());
}
}
@Override
public boolean hasNext() {
return idx < arr.size();
}
@Override
public Integer next() {
int val = idx < arr.size() ? arr.get(idx) : -1;
if (idx < arr.size()) ++idx;
return val;
}
class NestedInteger {
List<NestedInteger> nestedList;
Integer val;
public NestedInteger(List<NestedInteger> nestedList, Integer val) {
this.nestedList = nestedList;
this.val = val;
}
public boolean isInteger() {
return val != null;
}
public List<NestedInteger> getList() {
return nestedList;
}
public Integer getInteger() {
return val;
}
}
}
// 迭代 + 栈 实现。
class NestedIterator2 implements Iterator<Integer> {
List<Integer> arr = new ArrayList<>();
int idx = 0;
// 层层嵌套,就像是学过的树结构,integer为叶子节点,list为父节点。
// 扁平化的过程就像是前序遍历一样。
public NestedIterator2(List<NestedInteger> nestedList) {
// 根左右
Stack<NestedInteger> sk = new Stack<>();
for (int i = nestedList.size() - 1; i >= 0; i--) sk.push(nestedList.get(i));
NestedInteger root;
while (!sk.isEmpty()) {
root = sk.pop();
if (root.isInteger()) arr.add(root.getInteger());
else {
List<NestedInteger> list = root.getList();
for (int i = list.size() - 1; i >= 0; i--) sk.push(list.get(i));
}
}
}
@Override
public boolean hasNext() {
return idx < arr.size();
}
@Override
public Integer next() {
int val = idx < arr.size() ? arr.get(idx) : -1;
if (idx < arr.size()) ++idx;
return val;
}
class NestedInteger {
List<NestedInteger> nestedList;
Integer val;
public NestedInteger(List<NestedInteger> nestedList, Integer val) {
this.nestedList = nestedList;
this.val = val;
}
public boolean isInteger() {
return val != null;
}
public List<NestedInteger> getList() {
return nestedList;
}
public Integer getInteger() {
return val;
}
}
}
// 迭代 + 栈 + next时访问元素。
class NestedIterator3 implements Iterator<Integer> {
NestedInteger root;
Stack<NestedInteger> sk = new Stack<>();
// 层层嵌套,就像是学过的树结构,integer为叶子节点,list为父节点。
// 扁平化的过程就像是前序遍历一样。
public NestedIterator3(List<NestedInteger> nestedList) {
// 根左右
for (int i = nestedList.size() - 1; i >= 0; i--) sk.push(nestedList.get(i));
}
@Override
public boolean hasNext() {
while (!sk.isEmpty() && !sk.peek().isInteger()) {
root = sk.pop();
List<NestedInteger> list = root.getList();
for (int i = list.size() - 1; i >= 0; i--) sk.push(list.get(i));
}
return !sk.isEmpty();
}
@Override
public Integer next() {
return sk.pop().getInteger();
}
class NestedInteger {
List<NestedInteger> nestedList;
Integer val;
public NestedInteger(List<NestedInteger> nestedList, Integer val) {
this.nestedList = nestedList;
this.val = val;
}
public boolean isInteger() {
return val != null;
}
public List<NestedInteger> getList() {
return nestedList;
}
public Integer getInteger() {
return val;
}
}
}
1)问题转换,确认需求,建模(抽象出来),利用已学知识解决(一般需需要变形,或增加一些细节。),是常见的问题解决方案。当然如果问题转换比较巧妙,则属于脑筋急转弯!
2)树本身就是递归结构,所以树的前序遍历就是多递归,也可以理解为,递归开辟for循环,循环来访问每棵子树。
3)一题多解,深刻理解树的递归结构,前序遍历的本质,才能对考察的知识点融汇贯通,进而举一反三!