1.题目
剑指 Offer 54. 二叉搜索树的第k大节点
给定一棵二叉搜索树,请找出其中第k大的节点。
示例 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 ≤ 二叉搜索树元素个数
2.自我思路与实现
递归
对于二叉搜索树,右子树所有的值都大于根节点,左子树所有的值都小于根节点
- 方法功能
对于一个树,返回其第k个最大值 - 方法终止条件
当右子树的个数刚好等于k - 1时,因为右子树所有的值都大于根节点,有k - 1个值大于根节点,故第k个最大值就是根节点,此时返回根节点的值 - 递归函数
树第k大值 = 右子树第k - 1大值
树第k大值 = 左子树第(k - 1 - 右子树的节点数量)大值
此时需要引入一个计算节点数量的函数,同样使用递归
方法功能:计算一棵树的节点数量
终止条件:当节点为空时,该节点的数量为0, 返回0
递归函数:当前树的节点数量 = 左子树节点数量+ 右子树节点数量+ 1
时间: N
空间:N
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int kthLargest(TreeNode root, int k) {
if(num(root.right) == k - 1)
return root.val;
else if(num(root.right) > k - 1)
return kthLargest(root.right, k--);
else
return kthLargest(root.left, k - num(root.right) - 1);
}
int num(TreeNode root)
{
if(root == null)
return 0;
return num(root.left) + num(root.right) + 1;
}
}
3.总结思路与实现
另一种思路
中序遍历倒序
二叉搜索树的中序遍历为递增序列
二叉搜索树的中序遍历倒序为递减序列
因此问题转化为求此二叉搜索树中序遍历倒序的第k个节点
采用成员变量计数器记录倒序遍历次数,当k减为0时返回该节点
- 方法功能:给定一个节点,遇到中序遍历倒序的第k个节点时赋值给成员变量,终止函数
- 终止条件:当节点为空时返回,当计数器为0时返回
- 递归函数,遍历右子树,计数器减一, 遍历左子树
时间n
空间n
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int res;
int count;
public int kthLargest(TreeNode root, int k) {
count = k;
dfs(root);
return res;
}
void dfs(TreeNode root)
{
if(root == null || count == 0)
return;
dfs(root.right);
if(--count == 0)
res = root.val;
dfs(root.left);
}
}
4.相关知识
- 二叉搜索树的中序遍历为递增序列