给你一个嵌套的整数列表 nestedList 。每个元素要么是一个整数,要么是一个列表;该列表的元素也可能是整数或者是其他列表。请你实现一个迭代器将其扁平化,使之能够遍历这个列表中的所有整数。
实现扁平迭代器类 NestedIterator :
NestedIterator(List nestedList) 用嵌套列表 nestedList 初始化迭代器。
int next() 返回嵌套列表的下一个整数。
boolean hasNext() 如果仍然存在待迭代的整数,返回 true ;否则,返回 false 。
你的代码将会用下述伪代码检测:
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/flatten-nested-list-iterator
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
有一种数据结构叫做NestedInteger,这个结构中存的数据可能是一个Integer整数,也有可能是是一个NestedInteger的列表,注意,这个列表里面装的是NestdInteger,也就是说这个列表中的每一个元素可能是个整数,也可能是个列表,这样无限递归嵌套下去
我们到的算法将被输入一个NestedInteger列表,需要做的就是写一个迭代器类,将这个带有嵌套结构的NestedInteger给拍平
public class NestedIterator implements Iterator<Integer> {
public NestedIterator(List<NestedInteger> nestedList) {
}
@Override
public Integer next() {
}
@Override
public boolean hasNext() {
}
}
hasNext()方法,然后调用next方法while iterator.hasNext()
append iterator.next() to the end of res
return res
[[1,1],2,[1,1]],其中存在三个NestedInteger,两个列表类型的NestedInteger和一个整数类型的NestedInteger,算法返回打平的列表[1,1,2,1,1][1,[4,[6]]],算法返回打平的列表[1,4,6]NestedInteger结构实际上是一种支持无限嵌套的数据结构,而且可以同时表示整数和列表两种不同的类型public class NestedInteger {
private Integer val;
private List<NestedInteger> list;
public NestedInteger(Integer val){
this.val = val;
this.list = null;
}
public NestedInteger(List<NestedInteger> list){
this.list = list;
}
//如果其中存储的是一个整数,则返回true,否则返回false
public boolean isInteger(){
return this.val!=null;
}
//如果存储的是整数,则返回这个整数,否则返回null
public Integer getVal(){
return this.val;
}
//如果存储的是列表,则返回这个列表
public List<NestedInteger> getList() {
return list;
}
}
Integer类型,其val字段非空,其他节点都是List类型,其val字段为空,但是list字段非空,存着孩子节点class TreeNode{
int val;
List<TreeNode> children
}
void traverse(TreeNode root){
//根节点该怎么做:把自己的所有子节点都给拿出来,遍历,剩下的抛给递归
for(TreeNode node:root.children){
traverse(node);
}
}
NestedInteger感兴趣,也就是只想要叶子节点,所以traverse函数只要在到达叶子节点的时候把val加入结果列表即可 private Iterator<Integer> it;
public NestedIterator(List<NestedInteger> nestedList) {
//存放将nestedList打平的结果
List<Integer> result = new LinkedList<>();
for(NestedInteger node:nestedList){
this.traverse(node,result);
}
//得到result列表的迭代器
this.it = result.iterator();
}
private void traverse(NestedInteger root,List<Integer> result){
if(root.isInteger()){
result.add(root.getInteger());
return;
}
for(NestedInteger node:root.getList()){
this.traverse(node,result);
}
}
@Override
public Integer next() {
return it.next();
}
@Override
public boolean hasNext() {
return it.hasNext();
}
result列表,也就是内存中,next和hasNext只是在对result做迭代,如果输入的规模非常大,构造函数中的计算就会很慢,而且很占用内存nestedList的第一个元素是列表类型,则不断展开这个元素,直到第一个元素是整数类型,由于调用next()方法之前肯定会调用hasNext,这样就可以保证每次调用next方法的时候列表的第一个元素是整数类型,直接返回并删除第一个元素即可 private LinkedList<NestedInteger> list;
public NestedIterator(List<NestedInteger> nestedList) {
//不直接用nestedList的引用,是因为不能确定它的底层实现
//必须保证是LinkedList,否则addFirst会很低效
list = new LinkedList<>(nestedList);
}
@Override
public Integer next() {
//hasNext()方法保证了第一个元素一定是整数类型
return list.remove(0).getInteger();
}
@Override
public boolean hasNext() {
//循环拆分列表,直到第一个元素是整数类型
while(!list.isEmpty() && !list.get(0).isInteger()){
//当列表第一个元素是列表类型时,进入循环
List<NestedInteger> first = list.remove(0).getList();
//将第一个列表打平并按照顺序添加到开头
for(int i = first.size()-1;i>=0;i--){
list.addFirst(first.get(i));
}
}
return !list.isEmpty();
}