「这是我参与11月更文挑战的第 29 天,活动详情查看:2021最后一次更文挑战」
题目来源:leetcode 剑指 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 ≤ 二叉搜索树元素个数
题解
提出问题
- 什么是二叉搜索树?
二叉搜索树
- 二叉搜索树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值,若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
中序遍历 分析
- 我们可以根据二叉树的中序遍历来完成此题。
- 中序遍历公式:左->根->右,结合上面所说二叉搜索树的性质
3
/ \
1 4
\
2
- 可以得出:1234从小到大的数组
ans,根据所给的k我们通过ans[ans.length-k]及获取第k大节点
中序遍历 伪代码
- 定义
ans用于存放遍历二叉树时的值 - 定义
in_order方法用于递归中序遍历二叉树 - 首先判断
root是否为null,为null的话直接返回0 - 否则先递归调用当前节点的
left,然后push当前节点的root.val到ans数组中,最后递归调用当前节点的right - 当递归调用完成后,通过
ans[ans.length-k]就可以获取到第k大节点 - 最终就实现二叉搜索树的第k大节点
中序遍历 代码实现
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {number} k
* @return {number}
*/
var kthLargest = function(root, k) {
let ans = []
in_order(root,ans)
return ans[ans.length-k]
};
var in_order = function(root,ans){
if(root == null) return 0
in_order(root.left,ans)
ans.push(root.val)
in_order(root.right,ans)
return
}
比较右子树节点数量与k 分析
- 定义
ans用于存放遍历二叉树时的值 - 定义
getCount方法用于获取二叉搜索树的右节点数量 - 通过
cnt_r右节点数量与k值对比 - 如果
cnt_r右节点数量>= k值就说明第k大节点在右节点当中递归调用kthLargest(root.right,k) - 如果
cnt_r右节点数量== k值就说明第k大节点就说明当前节点root就是第k大节点 - 否则的话就说明第k大节点在左节点当中,那么需要缩小k值
k-cnt_r-1并递归调用kthLargest(root.left,k-cnt_r-1)
比较右子树节点数量与k 代码实现
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {number} k
* @return {number}
*/
var kthLargest = function(root, k) {
let cnt_r = getCount(root.right)
if(k <= cnt_r) return kthLargest(root.right,k)
if(k == cnt_r + 1) return root.val
return kthLargest(root.left,k-cnt_r-1)
};
var getCount = function(root){
if(root == null) return 0
return getCount(root.left) + getCount(root.right) + 1
}