[LC] 341. Flatten Nested List Iterator

这一题一种最直接的做法就是先真的做一个完整的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));
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值