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 是树的高度。

示例:
[中等] 173. 二叉搜索树迭代器 - 图1

  1. 输入
  2. ["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
  3. [[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
  4. 输出
  5. [null, 3, 7, true, 9, true, 15, true, 20, false]
  6. 解释
  7. BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
  8. bSTIterator.next(); // 返回 3
  9. bSTIterator.next(); // 返回 7
  10. bSTIterator.hasNext(); // 返回 True
  11. bSTIterator.next(); // 返回 9
  12. bSTIterator.hasNext(); // 返回 True
  13. bSTIterator.next(); // 返回 15
  14. bSTIterator.hasNext(); // 返回 True
  15. bSTIterator.next(); // 返回 20
  16. bSTIterator.hasNext(); // 返回 False

解答 & 代码

解法一:保存中序遍历结果

始化 BSTIterator 时先对二叉搜索树进行中序遍历,并将结果保存在数组 inOrderList 中。设置一个 idx 用来遍历数组即可

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. * int val;
  5. * TreeNode *left;
  6. * TreeNode *right;
  7. * TreeNode() : val(0), left(nullptr), right(nullptr) {}
  8. * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
  9. * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
  10. * };
  11. */
  12. class BSTIterator {
  13. private:
  14. vector<int> inOrderList; // 中序数组
  15. int idx; // 当前访问到的数组下标
  16. // 迭代中序遍历二叉搜索树,将结果保存在 inOrderList
  17. void inOrder(TreeNode* root)
  18. {
  19. stack<TreeNode*> s;
  20. TreeNode* cur = root;
  21. while(cur != nullptr || !s.empty())
  22. {
  23. while(cur != nullptr)
  24. {
  25. s.push(cur);
  26. cur = cur->left;
  27. }
  28. cur = s.top();
  29. s.pop();
  30. inOrderList.push_back(cur->val);
  31. cur = cur->right;
  32. }
  33. }
  34. public:
  35. BSTIterator(TreeNode* root) {
  36. inOrder(root);
  37. idx = 0;
  38. }
  39. int next() {
  40. ++idx;
  41. return inOrderList[idx - 1];
  42. }
  43. bool hasNext() {
  44. return idx < inOrderList.size();
  45. }
  46. };
  47. /**
  48. * Your BSTIterator object will be instantiated and called as such:
  49. * BSTIterator* obj = new BSTIterator(root);
  50. * int param_1 = obj->next();
  51. * bool param_2 = obj->hasNext();
  52. */

复杂度分析:设二叉树节点数为 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% 的用户