题目描述

:::fold-green 相关原题

LeetCode 原题: ✅ 230. 二叉搜索树中第 K 小的元素

力扣保证树非空且 k 合法;本文额外约定空树或非法 k 返回 -1。

:::

给定二叉搜索树 root 和整数 k,返回按升序排列的第 k 个节点值。

空树、k <= 0 或 k 超过节点数时返回 -1。

示例 1:

输入: root = [], k = 1
输出: -1

提示:

  • 树满足严格二叉搜索树性质。
  • k 从 1 开始计数。

题意分析

严格二叉搜索树的中序序列递增,只需数到第 k 个实际访问的节点。用显式栈可以找到答案后立即返回,无需保存完整有序序列。

解法:栈模拟中序遍历

核心思路

[!blue]

二叉搜索树的中序访问顺序就是节点值的升序,因此第 k 小就是第 k 次真正访问的节点。

stack 保存已经沿左链走过、但自身尚未访问的祖先。先不断压入左孩子;左侧走完后弹栈,此时才访问当前节点并递减 k,再转到它的右子树。压栈只是等待,不应扣减排名。

非法的 k <= 0 先返回 -1;遍历条件同时检查当前节点和栈。两者都为空仍未命中,说明节点数不够,不应继续弹空栈。

解题步骤

  1. k<=0 时返回 -1,否则准备空栈。
  2. 沿当前节点的左链不断压栈,直到当前节点为空。
  3. 弹出栈顶并将 k 减一,归零时返回该节点值。
  4. 转向该节点的右子树继续;遍历耗尽仍未归零则返回 -1。

代码实现

class Solution {
    public int kthSmallest(TreeNode root, int k) {
        if (k <= 0) {
            return -1;
        }

        Deque<TreeNode> stack = new ArrayDeque<>();

        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }

            root = stack.pop();

            if (--k == 0) {
                return root.val;
            }

            root = root.right;
        }

        return -1;
    }
}
func kthSmallest(root *TreeNode, k int) int {
    if k <= 0 {
        return -1
    }
    stack := []*TreeNode{}
    for root != nil || len(stack) > 0 {
        for root != nil {
            stack = append(stack, root)
            root = root.Left
        }
        root = stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        k--
        if k == 0 {
            return root.Val
        }
        root = root.Right
    }
    return -1
}

复杂度分析

  • 时间复杂度:最坏 $O(n)$;合法 k 时可提前结束,耗时 $O(h+k)$,其中 $h$ 为树高。
  • 空间复杂度:辅助栈 $O(h)$。

关键点总结

[!green]

用显式栈模拟中序遍历,在节点出栈时递减排名;仅在排名归零时返回,遍历结束仍未找到则返回 -1。

易错点总结

[!yellow]

  • 压栈只是等待访问,只有出栈时才减少 k。
  • 循环条件是当前节点非空或栈非空,不能要求两者同时非空。
  • 节点不足时遍历结束返回 -1,不能继续弹空栈。

相似题目

题目 难度 关联与区别
230. 二叉搜索树中第 K 小的元素 中等 二叉搜索树中序遍历得到升序节点,可复用第 k 次访问的计数;该题保证 k 合法,本题越界或空树时返回 -1。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/362674325744
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!