leetcode 剑指 Offer 54. 二叉搜索树的第k大节点 JavaScript版

217 阅读2分钟

「这是我参与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.valans数组中,最后递归调用当前节点的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
}