原题描述
LeetCode第341题 扁平化嵌套列表迭代器
难度:中等
给你一个嵌套的整型列表。请你设计一个迭代器,使其能够遍历这个整型列表中的所有整数。
列表中的每一项或者为一个整数,或者是另一个列表。其中列表的元素也可能是整数或是其他列表。
相关类
// 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();
}
我的思路
nestedList即会返回整数,也会返回列表。对于整数,我们可以按照List<integer>
的方式设计迭代器。而对于列表,我的思路是为列表创建创建一个迭代器对象,通过递归调用对象的next()
和hasNext()
方法得到结果。
因此,其中的难点在于hasNext()
方法。首先,我们需要在迭代器中维护一个下标。
- 如果下标超出List的长度,可以直接返回fasle;
- 如果下标所在位置的NestedInteger对象持有一个整数,可以直接返回true;
- 如果以上条件均不满足,则下标所在位置的NestedInteger对象持有一个列表,则需要为其创建一个NestedIterator对象:
3.1. 如果存在一个迭代器对象,说明我们不是第一次停留在该列表上,此时应该调用迭代器对象的hasNext()
方法:
3.1.1如果返回为true,说明下标位置处的列表中有未遍历的元素,可以直接向外返回true;
3.1.2如果返回为false,说明下标位置处的列表已经完全遍历,此时需要移动下标,同时将迭代器对象对象置空,但我们并不知道后续数据的情况,因此我们需要重新调用(也就是递归调用)本地迭代器的hasNext()
方法;
3.2. 如果不存在一个迭代器对象,则创建一个迭代器对象(当然,如果列表本身长度为0,则可以直接跳过),由于我们并不知道列表内部结构,因此需要迭代器对象的hasNext()
方法,并将结果返回。
next()
方法的设计相对简单。
- 如果下标所在位置的NestedInteger对象持有一个整数,可以直接返回该整数;
- 如果下标所在位置的NestedInteger对象持有一个列表,可以调用迭代器的
next()
方法即可。
我的尝试
第一次
public class NestedIterator implements Iterator<Integer> {
private List<NestedInteger> nestedList;
private int index;
private NestedIterator innerIterator;
public NestedIterator(List<NestedInteger> nestedList) {
this.nestedList = nestedList;
this.index = 0;
}
@Override
public Integer next() {
if(this.nestedList.get(this.index).isInteger()){
return this.nestedList.get(this.index++).getInteger();
}
return this.innerIterator.next();
}
@Override
public boolean hasNext() {
if(this.index>=this.nestedList.size()){
return false;
}
if(this.nestedList.get(this.index).isInteger()){
return true;
}
if(this.innerIterator!=null && this.innerIterator.hasNext()){
return true;
}else if (this.innerIterator==null){
List<NestedInteger> innerList = this.nestedList.get(this.index).getList();
if(innerList!=null && innerList.size()>0){
this.innerIterator = new NestedIterator(innerList);
return this.innerIterator.hasNext();
}
}
this.index ++;
this.innerIterator = null;
return this.hasNext();
}
}
提交结果:解答错误
输入:[[],[[]],-4,[[[]]],[[],2,[[]],[[-3],1],[[],-1]]]
输出:[]
预期:[-4,2,-3,1,-1]
分析原因
这个测试样例过于复杂,可以先看一个简单的。
输入:[[[]],1]
输出:[]
预期:[1]
在index=0时,其指向的NestedInteger对象持有一个列表[[]]
,其长度为1。而此时innerIterator为空,我们会为其实例化一个NestedIterator对象,并将列表[[]]
传入,并调用innerIterator的hasNext()
方法。
在innerIterator中,innerIterator.index=0时,其指向的NestedInteger对象持有一个列表[]
,其长度为0,因此innerIterator的hasNext()
方法会返回false,这也导致了上一层的hasNext()
方法返回false,进而造成结果出错。
解决思路
这里的本质是3.2.2处,对当前迭代器对象hasNext()
方法的返回值,应当按照3.1.1与3.1.2的方式处理,而不是直接返回。
因此,正确的思路如下:
- 如果下标超出List的长度,可以直接返回fasle;
- 如果下标所在位置的NestedInteger对象持有一个整数,可以直接返回true;
- 如果以上条件军部满足,则下标所在位置的NestedInteger对象持有一个列表,则需要为其创建一个NestedIterator对象:
3.1. 如果不存在一个迭代器对象,则创建一个迭代器对象(当然,如果列表本身长度为0,则可以直接跳过);
3.2. 调用迭代器对象的hasNext()
方法:
3.1.1如果返回为true,说明下标位置处的列表中有未遍历的元素,可以直接向外返回true;
3.1.2如果返回为false,说明下标位置处的列表已经完全遍历,此时需要移动下标,同时将迭代器对象对象置空,但我们并不知道后续数据的情况,因此我们需要重新调用(也就是递归调用)本地迭代器的hasNext()
方法;
第二次
public class NestedIterator implements Iterator<Integer> {
private List<NestedInteger> nestedList;
private int index;
private NestedIterator innerIterator;
public NestedIterator(List<NestedInteger> nestedList) {
this.nestedList = nestedList;
this.index = 0;
}
@Override
public Integer next() {
if(this.nestedList.get(this.index).isInteger()){
this.index ++;
return this.nestedList.get(this.index-1).getInteger();
}
return this.innerIterator.next();
}
@Override
public boolean hasNext() {
if(this.index>=this.nestedList.size()){
return false;
}
if(this.nestedList.get(this.index).isInteger()){
return true;
}
List<NestedInteger> innerList = this.nestedList.get(this.index).getList();
if(innerList!=null && innerList.size()>0){
if (this.innerIterator==null){
this.innerIterator = new NestedIterator(innerList);
}
if (this.innerIterator.hasNext()){
return true;
}
}
this.index ++;
this.innerIterator = null;
return this.hasNext();
}
}
提交结果:通过