LeetCode 341. 扁平化嵌套列表迭代器
题目描述
给你一个嵌套的整数列表 nestedList 。每个元素要么是一个整数,要么是一个列表;该列表的元素也可能是整数或者是其他列表。请你实现一个迭代器将其扁平化,使之能够遍历这个列表中的所有整数。
实现扁平迭代器类 NestedIterator :
- NestedIterator(List
nestedList) 用嵌套列表 nestedList 初始化迭代器。 - int next() 返回嵌套列表的下一个整数。
- boolean hasNext() 如果仍然存在待迭代的整数,返回 true ;否则,返回 false 。
你的代码将会用下述伪代码检测:
initialize iterator with nestedList
res = []
while iterator.hasNext()
append iterator.next() to the end of res
return res
如果 res 与预期的扁平化列表匹配,那么你的代码将会被判为正确。
示例 1:
输入:nestedList = [[1,1],2,[1,1]]
输出:[1,1,2,1,1]
解释:通过重复调用 next 直到 hasNext 返回 false,next 返回的元素的顺序应该是: [1,1,2,1,1]。
示例 2:
输入:nestedList = [1,[4,[6]]]
输出:[1,4,6]
解释:通过重复调用 next 直到 hasNext 返回 false,next 返回的元素的顺序应该是: [1,4,6]。
提示:
- 1 <= nestedList.length <= 500
- 嵌套列表中的整数值在范围 [-106, 106] 内
解题思路
这道题的基本思想仍然是递归。对于一个列表,是否存在下一个元素,要看当前迭代器位置,如果是一个数字的话,直接可以判断,如果是一个列表如何判断呢?
给这个列表创建一个子迭代器,在这个迭代器里判断就可以了!
参考代码
错误代码
刚开始可能写出这种代码,但是遇到 [1,[2,3]]
这种需要连续推出的嵌套,会报内存错误。主要原因在于,我们的使用方法是 while(it.hasNext()) it.next();
没有正确维护 it 状态。
class NestedIterator {
vector<NestedInteger>::iterator _it;
vector<NestedInteger>::iterator _end;
NestedIterator *_sub;
public:
NestedIterator(vector<NestedInteger> &nestedList) {
_it = nestedList.begin();
_end = nestedList.end();
_sub = nullptr;
}
int next() {
if (_it->isInteger()) {
int val = _it->getInteger();
_it++;
return val;
}
if (_sub == nullptr) {
_sub = new NestedIterator(_it->getList());
}
if (_sub->hasNext()) {
return _sub->next();
} else {
delete _sub;
_sub = nullptr;
_it++;
return next();
}
}
// // 注意到题目中 1 <= nestedList.length,所以不担心列表元素是空的
bool hasNext() {
return _it != _end;
}
};
正确代码
注意到我们的 it 始终放在下一次访问的元素位置上,访问子序列时也应该维护这一性质,即:hasNext 来判断是否存在下一个合法元素,next 一定是直接拿到合法元素。
而且,题目中欺骗了我们,题目说 1 <= nestedList.length <= 500
然而测试样例却给了一个 [[]]
,他难道是认为 nestedList 中的 nestedList 不算 nestedList 吗 ……
几个测试样例,分别用于测试不同的边界情况:
[1,2,3]
[[1,2],3]
[1,[2,3]]
[[]]
[[[[]]]
/*
* @lc app=leetcode.cn id=341 lang=cpp
*
* [341] 扁平化嵌套列表迭代器
*/
// @lc code=start
/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* class NestedInteger {
* public:
* // Return true if this NestedInteger holds a single integer, rather than a nested list.
* bool isInteger() const;
*
* // Return the single integer that this NestedInteger holds, if it holds a single integer
* // The result is undefined if this NestedInteger holds a nested list
* int getInteger() const;
*
* // Return the nested list that this NestedInteger holds, if it holds a nested list
* // The result is undefined if this NestedInteger holds a single integer
* const vector<NestedInteger> &getList() const;
* };
*/
class NestedIterator {
vector<NestedInteger>::iterator _it;
vector<NestedInteger>::iterator _end;
NestedIterator *_sub;
public:
NestedIterator(vector<NestedInteger> &nestedList) {
_it = nestedList.begin();
_end = nestedList.end();
_sub = nullptr;
}
int next() {
if (_it->isInteger()) {
int val = _it->getInteger();
_it++;
return val;
}
return _sub->next();
}
bool hasNext() {
while (_it != _end) {
if (_it->isInteger()) {
return true;
}
if (_sub == nullptr) {
_sub = new NestedIterator(_it->getList());
}
if (_sub->hasNext()) {
return true;
} else {
printf("%p====
", _it);
delete _sub;
printf("%p====
", _it);
_sub = nullptr;
_it++;
}
}
return false;
} // AC
};
/**
* Your NestedIterator object will be instantiated and called as such:
* NestedIterator i(nestedList);
* while (i.hasNext()) cout << i.next();
*/
// @lc code=end