这一题一种最直接的做法就是先真的做一个完整的flatten放到一个list里面,然后就很简单的iterate这个list就好。flatten的过程就用递归的dfs做就好了。根据这个思路,就可以得到代码如下:
public class NestedIterator implements Iterator<Integer> {
List<Integer> flattened;
int curIndx;
public NestedIterator(List<NestedInteger> nestedList) {
this.flattened = new ArrayList<Integer>();
this.flatten(nestedList);
this.curIndx = 0;
}
public void flatten(List<NestedInteger> nestedList) {
for (NestedInteger ni : nestedList) {
if (ni.isInteger()) {
this.flattened.add(ni.getInteger());
} else {
flatten(ni.getList());
}
}
}
@Override
public Integer next() {
if (!hasNext()) return null;
Integer result = flattened.get(this.curIndx);
this.curIndx++;
return result;
}
@Override
public boolean hasNext() {
return this.curIndx < this.flattened.size();
}
}
但这样做,其实有失iterator的真谛。一开始其实就已经iterate完全部了。上面这个算法是递归的dfs,递归的一个问题就是在于你没法在一个中间的状态停下来再继续。为了继续使用dfs但是可以有一个暂停和继续的功能。这个dfs需要通过类似循环来实现。也就是要用到stack。之前也有过类似的用stack实现dfs进行iterator的例子:https://blog.csdn.net/chaochen1407/article/details/44151079。其实是大同小异的,都是用Stack做循环实现一个可以一步步进行的dfs。最初的想法就是因为递归里面每一层其实就是一个链表,所以,我弄了两个stack,一个stack放对应递归每一层级的链表,另外一个stack放这个链表走到哪了。如果这个链表对应的某个节点也是一个链表,我就放进stack里作为dfs的下一层,如此类推。放出丑陋的代码如下:
Stack<List<NestedInteger>> listStk = new Stack<>();
Stack<Integer> indexStk = new Stack<>();
public NestedIterator(List<NestedInteger> nestedList) {
listStk.push(nestedList);
indexStk.push(-1);
this.findNextInt();
}
@Override
public Integer next() {
Integer index = indexStk.peek();
List<NestedInteger> curNList = listStk.peek();
Integer result = curNList.get(index).getInteger();
this.findNextInt();
return result;
}
@Override
public boolean hasNext() {
return !listStk.isEmpty();
}
protected void findNextInt() {
if (listStk.isEmpty()) {
return;
}
Integer index = indexStk.peek() + 1;
List<NestedInteger> curNList = listStk.peek();
NestedInteger curNI = null;
while(!listStk.isEmpty() && (curNI == null || !curNI.isInteger())) {
if (index == curNList.size()) {
indexStk.pop();
listStk.pop();
if (!indexStk.isEmpty()) {
index = indexStk.peek();
curNList = listStk.peek();
}
} else {
curNI = curNList.get(index);
if (!curNI.isInteger()) {
index++;
indexStk.pop();
indexStk.push(index);
index = 0;
indexStk.push(index);
curNList = curNI.getList();
listStk.push(curNList);
} else {
indexStk.pop();
indexStk.push(index);
}
}
}
}
这种做法太遵循图论的dfs的结构去做了,而开始丢失这一题本身只需要flatten的含义。所以其实可以相对简单化很多,我们没有真的有必要知道遇到一个链表节点的时候,dfs到底是对应递归的第几层,只需要插入当前的输出队列即可,这样对于这个stack本身,我们也做了flatten的处理。所以简化一下,代码可以是下面这样:
public class NestedIterator implements Iterator<Integer> {
Stack<NestedInteger> nIntStk;
public NestedIterator(List<NestedInteger> nestedList) {
nIntStk = new Stack<>();
for (int i = nestedList.size() - 1; i >= 0; i--) {
nIntStk.push(nestedList.get(i));
}
this.findNextInt();
}
@Override
public Integer next() {
Integer result = nIntStk.pop().getInteger();
this.findNextInt();
return result;
}
@Override
public boolean hasNext() {
return !nIntStk.isEmpty();
}
protected void findNextInt() {
if (nIntStk.isEmpty()) {
return;
}
while (!nIntStk.isEmpty() && !nIntStk.peek().isInteger()) {
List<NestedInteger> nextList = nIntStk.pop().getList();
for (int i = nextList.size() - 1; i >= 0; i--) {
nIntStk.push(nextList.get(i));
}
}
}
}