leetcode 341. 扁平化嵌套列表迭代器

@(labuladong的算法小抄)[回溯]

leetcode 341. 扁平化嵌套列表迭代器

题目描述

在这里插入图片描述

解题思路

参考:labuladong的算法小抄P345

DFS递归

相当于遍历一棵多叉树的所有叶子节点。

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * public interface NestedInteger {
 *
 *     // @return true if this NestedInteger holds a single integer, rather than a nested list.
 *     public boolean isInteger();
 *
 *     // @return the single integer that this NestedInteger holds, if it holds a single integer
 *     // Return null if this NestedInteger holds a nested list
 *     public Integer getInteger();
 *
 *     // @return the nested list that this NestedInteger holds, if it holds a nested list
 *     // Return null if this NestedInteger holds a single integer
 *     public List<NestedInteger> getList();
 * }
 */
public class NestedIterator implements Iterator<Integer> {
    private Iterator<Integer> it;
    public NestedIterator(List<NestedInteger> nestedList) {
        /* 存放将NestedInteger打平的结果 */
        List<Integer> res = new LinkedList<>();
        for (NestedInteger node : nestedList) {
	        /* 以每个节点为根节点遍历 */
            traverse(node, res);
        }
        it = res.iterator();
    }

    @Override
    public Integer next() {
        return it.next();
    }

    @Override
    public boolean hasNext() {
        return it.hasNext();
    }
    /* 遍历以root为根的多叉树,将叶子节点的值加入res列表 */
    private void traverse(NestedInteger root, List<Integer> res) {
        /* base case : 如果root就是叶子节点,则直接加入res */
        if (root.isInteger()) {
            res.add(root.getInteger());
            return;
        }
        for (NestedInteger child : root.getList()) {
            traverse(child, res);
        }

    }
}

/**
 * Your NestedIterator object will be instantiated and called as such:
 * NestedIterator i = new NestedIterator(nestedList);
 * while (i.hasNext()) v[f()] = i.next();
 */

惰性求值

上面的解法是一次性算出所有叶子节点的值,全部装到res列表中,也就是内存中,nexthasNext函数是在对内存中的res列表迭代。

如果输入的规模非常大,构造函数中的初始化就会非常慢,并且非常占用内存

一般来说,迭代器求值应该是“惰性的”,也就是说,如果你要一个结果,我就算一个(或是一小部分)结果出来,而不是一次性把所有结果都算出来。

因此,思路如下:

调用hasNext时,如果nestedList的第一个元素是列表类型,则不断展开这个元素,直到第一个元素是整数类型。

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * public interface NestedInteger {
 *
 *     // @return true if this NestedInteger holds a single integer, rather than a nested list.
 *     public boolean isInteger();
 *
 *     // @return the single integer that this NestedInteger holds, if it holds a single integer
 *     // Return null if this NestedInteger holds a nested list
 *     public Integer getInteger();
 *
 *     // @return the nested list that this NestedInteger holds, if it holds a nested list
 *     // Return null if this NestedInteger holds a single integer
 *     public List<NestedInteger> getList();
 * }
 */
public class NestedIterator implements Iterator<Integer> {
    LinkedList<NestedInteger> list;
    public NestedIterator(List<NestedInteger> nestedList) {
        /* 不直接用nestedList的引用,是因为不能确定它的底层实现 */
        /* 必须保证是LinkedList,否则下面的addFirst会很低效 */
        list = new LinkedList<>(nestedList);
    }

    @Override
    public Integer next() {
        /* hasNext方法保证了第一个元素一定是Integer类型 */
        return list.remove(0).getInteger();
    }

    @Override
    public boolean hasNext() {
        /* 循环拆分列表元素,直到列表第一个元素是整数类型 */
        while (!list.isEmpty() && !list.get(0).isInteger()) {
            /* 当list中第一个元素是列表类型时,进入循环 */
            List<NestedInteger> first = list.remove(0).getList();
            /* 将第一个列表打平,并按顺序添加到开头 */
            for (int i = first.size() - 1; i >= 0; i--) {
                list.addFirst(first.get(i));
            }
        }
        /* 只要列表不空,就说明还有下一个 */
        return !list.isEmpty();
    }

}

/**
 * Your NestedIterator object will be instantiated and called as such:
 * NestedIterator i = new NestedIterator(nestedList);
 * while (i.hasNext()) v[f()] = i.next();
 */
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值