题目描述
给定一个嵌套的整型列表。设计一个迭代器,使其能够遍历这个整型列表中的所有整数。
列表中的项或者为一个整数,或者是另一个列表。
样例
示例1
输入: [[1,1],2,[1,1]]
输出: [1,1,2,1,1]
解释: 通过重复调用next 直到hasNext 返回false,next返回的元素的顺序应该是: [1,1,2,1,1]。
示例2
输入: [1,[4,[6]]]
输出: [1,4,6]
解释: 通过重复调用next直到hasNext 返回false,next返回的元素的顺序应该是: [1,4,6]。
算法1
(DFS存储压平后的链表) $O(n)$
访问迭代器的过程可以用递归来描述,当我们访问一个NestedInteger
迭代器时,如果它包含的不是一个整数,即isInteger
是false
,那么我们对于getList
里的每一个NestedInteger
迭代器再进行递归的访问,直到遇到一个整数为止,然后将它加入全局数组中。这样在构造函数初始化这个类的时候我们就已经将整个列表压平了。
时间复杂度
若整数的个数为n
,那么压平这个列表的时间为$O(n)$,同时空间复杂度也为$O(n)$。
C++ 代码
/**
* // 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 {
public:
vector<int> nums;
int cnt = 0;
NestedIterator(vector<NestedInteger> &nestedList) {
dfs(nestedList);
}
void dfs(vector<NestedInteger> &nestedList) {
for (auto list : nestedList) {
if (list.isInteger()) nums.push_back(list.getInteger());
else dfs(list.getList());
}
}
int next() {
return nums[cnt ++ ];
}
bool hasNext() {
return cnt < nums.size();
}
};
/**
* Your NestedIterator object will be instantiated and called as such:
* NestedIterator i(nestedList);
* while (i.hasNext()) cout << i.next();
*/
算法2
(用栈来模拟递归) $O(n)$
这种做法的思路与 LeetCode 173. Binary Search Tree Iterator 类似,当调用hasNext
时我们将栈顶元素变为下一个要访问的整数,初始化时将迭代器倒序压入栈中,这样可以保证栈顶的迭代器为输入数组的第一个迭代器。
时间复杂度
时间复杂度与上面的算法相同,不过空间复杂度会降低。考虑[1,[1,[1,[1,...,]]]]
这种情况,那么栈中的迭代器数量最大为2,降低了很多空间。
C++ 代码
/**
* // 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 {
public:
stack<NestedInteger> stk;
NestedIterator(vector<NestedInteger> &nestedList) {
for (int i = nestedList.size() - 1; i >= 0; i -- ) {
stk.push(nestedList[i]);
}
}
int next() {
int res = stk.top().getInteger();
stk.pop();
return res;
}
bool hasNext() {
while(stk.size()) {
auto t = stk.top();
if (t.isInteger()) return true;
stk.pop();
for (int i = t.getList().size() - 1; i >= 0; i -- ) {
stk.push(t.getList()[i]);
}
}
return false;
}
};
/**
* Your NestedIterator object will be instantiated and called as such:
* NestedIterator i(nestedList);
* while (i.hasNext()) cout << i.next();
*/