

一、题目大意
给定一棵二叉搜索树 BST 的根节点root和整数k,找出树里第 k 小的元素,k 从 1 开始计数。
二叉搜索树性质:左子树所有节点 < 当前节点 < 右子树所有节点。 中序遍历(左→根→右)得到的序列是从小到大升序排列。
二、核心解题思想
利用 BST 的特性:中序遍历结果升序。 不需要遍历完整棵树,每访问一个节点就计数,访问到第 k 个节点直接返回,提前终止。
本方案:手动栈模拟中序遍历,找到目标立刻退出,面试优先推荐。
三、迭代(栈)完整代码(AC 版)
ini
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int kthSmallest(TreeNode root, int k) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(cur != null || !stack.isEmpty()) {
// 一路向左,整条左链全部入栈
while(cur != null) {
stack.push(cur);
cur = cur.left;
}
// 弹出栈顶,访问当前节点(中序:左访问完,访问根)
cur = stack.pop();
k--;
if(k == 0){
return cur.val;
}
// 处理右子树
cur = cur.right;
}
return -1; //语法兜底,题目保证一定有解
}
}
四、实例演示
样例:root = [5,3,6,2,4,null,null,1],k=3 树结构:
markdown
5
/ \
3 6
/ \
2 4
/
1
中序序列:1, 2, 3, 4, 5, 6,第 3 小答案为 3
| 步骤 | cur 当前节点 | stack(栈底→栈顶) | 执行操作 | k 的值 |
|---|---|---|---|---|
| 1 | 5 | \[\] | 内层 while:cur 不为空,压入 5;cur=5.left=3 | 3 |
| 3 | 5 | 压入 3;cur=3.left=2 | 3 | |
| 2 | 5,3 | 压入 2;cur=2.left=1 | 3 | |
| 1 | 5,3,2 | 压入 1;cur=1.left=null | 3 | |
| 2 | null | 5,3,2,1 | 退出内层循环;pop 取出节点 1;k--;k 不等于 0;cur=1.right=null | 2 |
| 3 | null | 5,3,2 | 外层循环,cur=null,pop 取出节点 2;k--;k 不等于 0;cur=2.right=null | 1 |
| 4 | null | 5,3 | 外层循环,cur=null,pop 取出节点 3;k--;k==0,直接返回 3,结束程序 | 0 |
五、复杂度分析
- 时间复杂度:(O(H + k)),H 是树高。最多访问 k 个节点,找到目标就停止,不用遍历整棵树。
- 空间复杂度:(O(H)),栈最多保存树的一条链,H 为树高;平衡二叉树 H=logn,退化成链表 H=n。
六、易错点清单
- ❌ 大小写错误:
Stack.isEmpty()(类名调用),正确是stack.isEmpty()(实例对象调用)。 - ❌ k 从1 开始计数 ,不是数组下标 0 开始,所以访问节点后
k--,判断k==0返回。 - ❌ Java 语法坑:有返回值的方法,所有分支必须有 return,末尾需要兜底 return。
- ❌ 混淆普通二叉树和 BST:本题必须依赖二叉搜索树的性质,普通二叉树不能直接用中序升序。
七、两种方法对比
| 方法 | 优点 | 缺点 |
|---|---|---|
| 递归中序 | 代码简短,写得快 | 找到答案后不会立刻停止,会继续递归,有栈溢出风险 |
| 栈迭代中序 | 找到目标直接退出,可控,面试推荐 | 代码行数稍多,需要手动维护栈 |
八、个人感悟
二叉搜索树的中序遍历升序是 BST 题型最核心的考点。 遇到求 BST 第 k 大 / 第 k 小、验证 BST、BST 转有序数组,优先想到中序遍历。迭代写法手动模拟栈,能更好控制遍历终止时机,面试更占优势。
拓展思路:如果树会频繁增删节点,每次重新遍历效率低,可以在树节点中保存子树节点数量,用二分思路直接定位第 k 小,时间优化到(O(H))。