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

77 阅读2分钟

题目

给定一棵二叉搜索树,请找出其中第 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 ≤ 二叉搜索树元素个数

题解

题目给的是二叉搜索树,简单的思路是通过中序遍历可以得到 root 的升序数组num1, 如: root = [3,1,4,null,2], 中序遍历后: nums1 = [ null, 1, 2, 3,4], 得到升序数组后reverse反转后,二叉搜索树的第k 大 节点即 nums[k-1];

中序遍历的模板

  1. 遍历左节点
  2. 遍历根节点
  3. 遍历右节点
function inorder(root) {
    if (root == null) return;
    inorder(root.left);
    console.log(root.val);
    inorder(root.right);
}

那么可以实现不用一个数组nums1保存中序遍历的结果吗?

答案当然是可以的!

使用中序遍历的倒序可以得到root降序排列nums2, 如root = [3,1,4,null,2], 中序遍历的倒序后: nums2 = [4, 3, 2, 1, null], 观察下nums2发现,如果第 1大节点, 就是中序遍历的倒序的访问的第一个节点。依次类推,在倒序遍历中,每访问一个节点k--, 如果当k == 0,说明当前节点是第K大的节点,

中序遍历的倒序模板

function inorderReverse(root) {
    if (root == null) return;
    inorder(root.right);
    console.log(root.val);
    inorder(root.left);
}

参考代码

/**
 * 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 res;
   
    function inorderReverse(root) {
        if (root == null) return;
        inorderReverse(root.right);
        // 如果k <= 0, 此时不需要再遍历了,说明已经找到了
        if (k <= 0) return;
        if (--k == 0) {
            res = root.val;
        }
        inorderReverse(root.left);
    }
    inorderReverse(root);
    return res;
    
};

原题链接

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