题目描述
给定一棵二叉搜索树,请找出其中第K大的节点。(本题是剑指Offer第54题)
示例 1:
输入: root = [3,1,4,null,2], k = 1
3
/ \
1 4
\
2
输出: 4
示例 2:
输入: root = [5,3,6,2,4,null,null,1], k = 3
5
/ \
3 6
/ \
2 4
/
1
输出: 4
限制:
1 ≤ k ≤ 二叉搜索树元素个数。
中序遍历法
本文解题思路的前提是知道二叉搜索树的中序遍历是递增的
。
中序遍历后的树节点是递增的,所以问题就可以转化为找出中序遍历后递增序列的倒数第k个节点
。中序遍历的递归写法为:左子树、根节点、右子树,在二叉搜索树中是一个递增序列,那么它的倒序就是:右子树、根节点、左子树,是一个递减序列。因此我们可以在遍历节点的同时统计遍历的数目,来判断是否是第K个节点。
递归的终止条件:
- root == null,表示越过了叶子节点,直接返回。
- k == 0,分为两种情况:
- k == 0 ,表示已经找到第K大的值,不需要执行后面的递归了,直接返回。
- --k == 0,表示当前结点的值为第K大的值,返回该值,并结束后面的递归。
int result, k;
public int kthLargest(TreeNode root, int k) {
this.k = k;
dfs(root);
return result;
}
public void dfs(TreeNode root) {
if (root == null) return;
dfs(root.right);
if (k == 0) return;
if (--k == 0) {
result = root.val;
return;
}
dfs(root.left);
}
时间复杂度:O(N) 空间复杂度:O(N)
总结
本题的思路在于理解中序遍历和二叉搜索树。算法中有一个优化点值得注意的是k==0在什么地方 return
。个人理解的是:当遍历右子树已经得到第K大的值时,后续的根节点和左子树就不应该在继续执行,所以我在右子树之后加上了(k == 0
)的判断。