LeetCode 230. 二叉搜索树中第 K 小的元素
本节目标
用显式栈进行中序遍历,在访问第 K 个节点时立即返回。
这道题利用构造与二叉搜索树中的中序有序性,在找到目标后不再访问剩余节点。
题意与边界
给定 BST 与有效的 k,返回按升序排列后的第 k 小节点值。单节点树且 k = 1 是最小边界;题目保证 k 不会超出节点数。
迭代中序早停
中序遍历顺序是左、根、右,因此访问节点的值严格递增。指针持续沿左链入栈;到空节点后弹出栈顶并访问它,再转向其右子树。每弹出一个节点令 k 减一,减到零时该节点正是答案,可立即返回。
正确性依据
栈始终保存尚未访问、但其左侧已经或正在被处理的祖先。每次弹出的节点是当前未访问节点中最小者;随后转向右子树不会遗漏更小值。故第 k 次弹出对应全树中第 k 小的值,早停不会影响答案。
代码实现
- C++
- Python
C++17
#include <stack>
using namespace std;
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode*> nodes;
TreeNode* cur = root;
while (cur != nullptr || !nodes.empty()) {
while (cur != nullptr) {
nodes.push(cur);
cur = cur->left;
}
cur = nodes.top();
nodes.pop();
k--;
if (k == 0) {
return cur->val;
}
cur = cur->right;
}
return 0;
}
};
Python 3
from typing import Optional
class Solution:
def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
nodes: list[TreeNode] = []
cur = root
while cur is not None or nodes:
while cur is not None:
nodes.append(cur)
cur = cur.left
cur = nodes.pop()
k -= 1
if k == 0:
return cur.val
cur = cur.right
return 0
复杂度分析
最坏访问所有节点,时间复杂度为 O(n);找到目标前实际访问 k 个节点及其左链。显式栈最多保存树高 h 个节点,额外空间为 O(h)。
易错点
- 把前序或后序当成有序访问,BST 只有中序遍历有递增性质。
- 每次弹栈后忘记转向右子树,漏掉右侧节点。
- 找到第
k个节点后继续遍历,增加无用工作。
模式迁移
当需要 BST 的第 K 大元素时,可改用右、根、左的逆中序;若查询频繁且树可修改,则可学习维护子树节点数的增强 BST。