Medium

题目描述

实现一个二叉搜索树迭代器类 BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:

  • BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应该初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
  • boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false
  • int next() 将指针向右移动,然后返回指针处的数字。

注意,指针初始化为一个不存在的最小数字,所以对 next() 的第一次调用将返回 BST 中的最小元素。

你可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。

示例 1:

输入
["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

提示:

  • 树中节点的数目在范围 [1, 10^5]
  • 0 <= Node.val <= 10^6
  • 最多调用 10^5hasNextnext 操作

进阶:

你可以设计一个满足下述条件的解决方案吗?next()hasNext() 操作均摊时间复杂度为 O(1) ,并使用 O(h) 内存。其中 h 是树的高度。

解题思路

这道题要求实现一个二叉搜索树的迭代器,需要按中序遍历顺序返回节点值。有两种主要解法:

解法一:预处理法 在构造函数中通过中序遍历将所有节点值存储到数组中,然后用索引进行迭代。这种方法简单直观,但空间复杂度为 O(n)。

解法二:栈模拟法(推荐) 使用栈来模拟中序遍历的递归过程,满足进阶要求。核心思想是:

  1. 初始化时,将根节点到最左节点的路径上的所有节点压入栈中
  2. next() 操作:弹出栈顶元素作为结果,如果该元素有右子树,则将右子树的最左路径压入栈
  3. hasNext() 操作:检查栈是否为空

这种方法的关键在于理解中序遍历的本质:对于每个节点,先访问左子树,再访问根节点,最后访问右子树。栈中始终保存着当前需要访问的节点路径。

时间复杂度:每个节点最多入栈和出栈一次,所以均摊时间复杂度为 O(1)。空间复杂度为 O(h),其中 h 是树的高度。

代码实现

class BSTIterator {
private:
    stack<TreeNode*> stk;
    
    void pushLeft(TreeNode* node) {
        while (node) {
            stk.push(node);
            node = node->left;
        }
    }
    
public:
    BSTIterator(TreeNode* root) {
        pushLeft(root);
    }
    
    int next() {
        TreeNode* node = stk.top();
        stk.pop();
        if (node->right) {
            pushLeft(node->right);
        }
        return node->val;
    }
    
    bool hasNext() {
        return !stk.empty();
    }
};
class BSTIterator:

    def __init__(self, root: Optional[TreeNode]):
        self.stack = []
        self._push_left(root)
    
    def _push_left(self, node):
        while node:
            self.stack.append(node)
            node = node.left

    def next(self) -> int:
        node = self.stack.pop()
        if node.right:
            self._push_left(node.right)
        return node.val

    def hasNext(self) -> bool:
        return len(self.stack) > 0
public class BSTIterator {
    private Stack<TreeNode> stack;
    
    public BSTIterator(TreeNode root) {
        stack = new Stack<TreeNode>();
        PushLeft(root);
    }
    
    private void PushLeft(TreeNode node) {
        while (node != null) {
            stack.Push(node);
            node = node.left;
        }
    }
    
    public int Next() {
        TreeNode node = stack.Pop();
        if (node.right != null) {
            PushLeft(node.right);
        }
        return node.val;
    }
    
    public bool HasNext() {
        return stack.Count > 0;
    }
}
var BSTIterator = function(root) {
    this.stack = [];
    this.pushLeft(root);
};

BSTIterator.prototype.pushLeft = function(node) {
    while (node) {
        this.stack.push(node);
        node = node.left;
    }
};

BSTIterator.prototype.next = function() {
    const node = this.stack.pop();
    if (node.right) {
        this.pushLeft(node.right);
    }
    return node.val;
};

BSTIterator.prototype.hasNext = function() {
    return this.stack.length > 0;
};

复杂度分析

操作时间复杂度空间复杂度
构造函数O(h)O(h)
next()均摊 O(1)O(h)
hasNext()O(1)O(h)

其中 h 是二叉搜索树的高度。每个节点最多入栈和出栈一次,所以 next() 操作的均摊时间复杂度为 O(1)。

相关题目