1.Description
给你一个嵌套的整型列表。请你设计一个迭代器,使其能够遍历这个整型列表中的所有整数。
列表中的每一项或者为一个整数,或者是另一个列表。其中列表的元素也可能是整数或是其他列表。
2.Example
输入: [[1,1],2,[1,1]]
输出: [1,1,2,1,1]
解释: 通过重复调用 next 直到 hasNext 返回 false,next 返回的元素的顺序应该是: [1,1,2,1,1]。
3.Solution
1.在调用构造函数时就将重叠列表平铺开来
在调用构造函数时就将重叠列表平铺开来,然后在调用next和hasnext时只需要依次增加i的值来遍历已经铺平的list即可。
/**
* // 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 List<Integer> list = new ArrayList<>();
private int i = 0;
public void add(List<NestedInteger> nestedList) {
for(NestedInteger nestedInteger : nestedList) {
if(nestedInteger.isInteger()) {
list.add(nestedInteger.getInteger());
}else {
add(nestedInteger.getList());
}
}
}
public NestedIterator(List<NestedInteger> nestedList) {
add(nestedList);
}
@Override
public Integer next() {
return list.get(i++);
}
@Override
public boolean hasNext() {
return i < list.size();
}
}
/**
* Your NestedIterator object will be instantiated and called as such:
* NestedIterator i = new NestedIterator(nestedList);
* while (i.hasNext()) v[f()] = i.next();
*/
2.构造时不展开,在调用hasnext方法时直接输出重叠列表中的数
把递归方法 转 迭代方法,我们需要用到「栈」。
在递归方法中,我们在遍历时如果遇到一个嵌套的 子list,就立即处理该 子list,直到全部展开;
在迭代方法中,我们不需要全部展开,只需要把 当前list 的所有元素放入 list 中。
由于「栈」的先进后出的特性,我们需要逆序在栈里放入各个元素。
处理流程分为两步:
1.在构造函数中应该初始化,把当前列表的各个元素(不用摊平)逆序放入栈中。
2.在 hasNext() 方法中,访问(不弹出)栈顶元素,判断是否为 int:
如果是 int 那么说明有下一个元素,返回 true;然后 next() 就会被调用,把栈顶的 int 弹出;
如果是 list 需要把当前列表的各个元素(不用摊平)逆序放入栈中。
如果栈为空,那么说明原始的嵌套列表已经访问结束了,返回 false。
算法整体的流程,通过举例说明。假如输入 [1, [2,3]] 。
- 在构造函数中:栈里面放的应该是 stack = [[2, 3], 1]
- 在调用 hasNext() 方法时,访问栈顶元素是 1,为 int,那么直接返回 true;
- 然后调用 next() 方法,弹出栈顶元素 1;
- 再调用 hasNext() 方法时,访问栈顶元素是 [2,3],为 list,那么需要摊平,继续放到栈中。
当前的栈是 stack = [3, 2] - 然后调用 next() 方法,弹出栈顶元素 2;
- 然后调用 next() 方法,弹出栈顶元素 3;
- 再调用 hasNext() 方法时,栈为空,因此返回 false,迭代器运行结束。
这里需要说一下为什么在 hasNext() 方法中摊平 list,而不是在 next() 方法中。比如对于 [[]] 的输入, hasNext() 方法是判断其中是否有 int 元素了,则必须把内层的 list 摊平来看,发现是空的,返回 false。
public class NestedIterator implements Iterator<Integer> {
private Deque<NestedInteger> deque;
public NestedIterator(List<NestedInteger> nestedList) {
deque = new ArrayDeque<>();
for(int i = nestedList.size() - 1 ; i >= 0 ; i--){
deque.addLast(nestedList.get(i));
}
}
@Override
public Integer next() {
NestedInteger cur = deque.removeLast();
return cur.getInteger();
}
@Override
public boolean hasNext() {
while(!deque.isEmpty()){
NestedInteger top = deque.peekLast();
if(top.isInteger()){
return true;
}
deque.removeLast();
for(int i = top.getList().size() - 1 ; i >= 0 ; i--){
deque.addLast(top.getList().get(i));
}
}
return false;
}
}