leetcode:173. 二叉搜索树迭代器
题目
实现一个二叉搜索树迭代器类 BSTIterator
,表示一个按中序遍历二叉搜索树(BST)的迭代器:
BSTIterator(TreeNode root)
初始化BSTIterator
类的一个对象。BST 的根节点root
会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。boolean hasNext()
如果向指针右侧遍历存在数字,则返回true
;否则返回false
。int next()
将指针向右移动,然后返回指针处的数字。
注意,指针初始化为一个不存在于 BST 中的数字,所以对 next()
的首次调用将返回 BST 中的最小元素。
你可以假设 next()
调用总是有效的,也就是说,当调用 next()
时,BST 的中序遍历中至少存在一个下一个数字。
进阶:
- 你可以设计一个满足下述条件的解决方案吗?
next()
和hasNext()
操作均摊时间复杂度为O(1)
,并使用O(h)
内存。其中h
是树的高度。
示例:
输入
["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
输出
[null, 3, 7, true, 9, true, 15, true, 20, false]
解释
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
bSTIterator.next(); // 返回 3
bSTIterator.next(); // 返回 7
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 9
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 15
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 20
bSTIterator.hasNext(); // 返回 False
解答 & 代码
解法一:保存中序遍历结果
始化 BSTIterator
时先对二叉搜索树进行中序遍历,并将结果保存在数组 inOrderList
中。设置一个 idx
用来遍历数组即可
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class BSTIterator {
private:
vector<int> inOrderList; // 中序数组
int idx; // 当前访问到的数组下标
// 迭代中序遍历二叉搜索树,将结果保存在 inOrderList
void inOrder(TreeNode* root)
{
stack<TreeNode*> s;
TreeNode* cur = root;
while(cur != nullptr || !s.empty())
{
while(cur != nullptr)
{
s.push(cur);
cur = cur->left;
}
cur = s.top();
s.pop();
inOrderList.push_back(cur->val);
cur = cur->right;
}
}
public:
BSTIterator(TreeNode* root) {
inOrder(root);
idx = 0;
}
int next() {
++idx;
return inOrderList[idx - 1];
}
bool hasNext() {
return idx < inOrderList.size();
}
};
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator* obj = new BSTIterator(root);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
复杂度分析:设二叉树节点数为 n,高度为 h
- 时间复杂度:初始化时间复杂度 O(n),后续
next()
和hasNext()
的时间复杂度均为 O(1) - 空间复杂度 O(n):数组
inOrderList
保存中序遍历的全部结果
执行结果:
执行结果:通过
执行用时:28 ms, 在所有 C++ 提交中击败了 45.03% 的用户
内存消耗:23.5 MB, 在所有 C++ 提交中击败了 42.81% 的用户
解法二:迭代
将迭代法中序遍历二叉树分解到 next()
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class BSTIterator {
private:
stack<TreeNode*> s;
TreeNode* cur;
public:
BSTIterator(TreeNode* root) {
cur = root;
}
int next() {
while(cur != nullptr)
{
s.push(cur);
cur = cur->left;
}
cur = s.top();
s.pop();
int val = cur->val;
cur = cur->right;
return val;
}
bool hasNext() {
return cur != nullptr || !s.empty();
}
};
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator* obj = new BSTIterator(root);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
复杂度分析:设二叉树节点数为 n,高度为 h
- 时间复杂度:初始化和调用
hasNext()
的时间复杂度都为 O(1)。n 次调用next()
遍历全部 n 个节点,总的时间复杂度 O(n),每次的均摊时间复杂度 O(1) - 空间复杂度 O(h):栈深度 = 二叉树深度
执行结果:
执行结果:通过
执行用时:44 ms, 在所有 C++ 提交中击败了 6.90% 的用户
内存消耗:23.4 MB, 在所有 C++ 提交中击败了 70.33% 的用户