1、递归
本题实际上是在遍历一棵树,将每个节点上的值加入最后的数组中,并返回数组的指针。我们可以使用深度优先遍历通过递归来遍历整个嵌套数组。我们首先定义dfs函数,对于nestedList中的每一个元素,若为整数则直接加入最终的数组,否则直接递归调用构造函数新建指针进行扁平化处理。在构造函数中,我们只需要深度遍历整棵树,并将指针指向开头即可。对于next,我们只需要返回当前指针的下一个值即可。对于hasNext,我们只需要判断当前指针是否指向末尾即可。
class NestedIterator {
private:
vector<int> num;
vector<int>::iterator it;
public:
void dfs(const vector<NestedInteger> &nestedList) {
for (auto &nestedInteger: nestedList) {
if (nestedInteger.isInteger()) {
num.emplace_back(nestedInteger.getInteger());
} else {
dfs(nestedInteger.getList());
}
}
}
NestedIterator(vector<NestedInteger> &nestedList) {
dfs(nestedList);
it = num.begin();
}
int next() {
return *it++;
}
bool hasNext() {
return it != num.end();
}
};
2、迭代
我们可以利用栈来存储我们访问过的每一个指针,同时为了方便判断我们是否访问到列表末尾,我们使用pair类型同时存储当前访问的指针和当前列表的尾后指针。在构造函数中,我们添加最外侧列表的指针,若该项被弹出则说明列表已经被完全遍历。在next函数中,我们弹出当前栈顶元素对应的整数。对于hasNext函数,若栈为空则返回false;否则我们进行循环,每次都判断当前的栈顶元素是否指向当前列表的末尾,若是则将当前列表对应的栈顶元素弹出栈,否则我们判断当前指针指向的元素是整数还是列表,若为整数则返回true;否则我们将新的列表压入栈中并继续进行循环。
class NestedIterator {
private:
// pair 中存储的是列表的当前遍历位置,以及一个尾后迭代器用于判断是否遍历到了列表末尾
stack<pair<vector<NestedInteger>::iterator, vector<NestedInteger>::iterator>> stk;
public:
NestedIterator(vector<NestedInteger> &nestedList) {
stk.emplace(nestedList.begin(), nestedList.end());
}
int next() {
// 由于保证调用 next 之前会调用 hasNext,直接返回栈顶列表的当前元素,然后迭代器指向下一个元素
return stk.top().first++->getInteger();
}
bool hasNext() {
while (!stk.empty()) {
auto &p = stk.top();
if (p.first == p.second) { // 遍历到当前列表末尾,出栈
stk.pop();
continue;
}
if (p.first->isInteger()) {
return true;
}
// 若当前元素为列表,则将其入栈,且迭代器指向下一个元素
auto &lst = p.first++->getList();
stk.emplace(lst.begin(), lst.end());
}
return false;
}
};