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

127 阅读2分钟

剑指 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 ≤ 二叉搜索树元素个数

解题思路:什么是二叉搜索树,就是中序遍历后是从小到大的排序,例如实例1中,中序遍历后就是[1,2,3,4],实例二中[123456],还有一个特点就是根节点的左边小于根节点,右边大于根节点,第k大节点的意思就是找出倒数第k个节点,代码如下 实现方式一:中序遍历

var kthLargest = function(root, k) {
    //保存所有节点数组
    let ans = [];
    //通过递归将所有节点存储在ans中
    let ansAll = _kthLargest(root,ans);
    //返回倒数第k个值
    return ansAll[ansAll.length - k];
};
//递归函数
var _kthLargest = function(root,ans){
    if(!root) return;
    //遍历左子树
    _kthLargest(root.left,ans);
    //先保存左节点然后保存根节点
    ans.push(root.val);
    //遍历右子树
    _kthLargest(root.right,ans);
    return ans;
}

实现方式二:根据k的大小来判断,k如果小于等于右子树节点个数,那么k在右子树上,如果k等于右子树节点加一那么第k大节点就是根节点,如果大于右子树那么就在左子树上找,代码如下:

var kthLargest = function(root, k) {
   //获取右子树节点个数
    let r = getHight(root.right);
    //如果k小于等于r那么需要返回的数在右子树上
    if( k <= r ) return kthLargest(root.right,k);
    //直到k等于r+1那么就找到了需要返回的第k大节点了
    if(k === r + 1) return root.val;
    //此时可以判断第k大节点数在左子树上,通过递归可以找到
    return kthLargest(root.left,k - r -1);
};

var getHight = function(root){
    if(!root) return 0;
    //累计节点个数
    return getHight(root.left) + getHight(root.right) + 1;
}