二叉搜索树的第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

二、集合+中序遍历

2.1  思路分析

  1. 根据二叉搜索树的特点,其中序遍历的结果即是有序的,那么只要将这个结果保存的数组或集合中,就能轻易的找到第k大的元素;

2.2  代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<Integer> ls = new ArrayList<>();
    public int kthLargest(TreeNode root, int k) {
        helper(root);
        return  ls.get(ls.size() - k);
    }
    //将二叉搜索树按照中序遍历转到集合
    public void helper(TreeNode root) {
        if(root == null) return;
        helper(root.left);
        ls.add(root.val);
        helper(root.right);
    }
}

2.3  复杂度分析

  • 时间复杂度为O(n);
  • 空间复杂度为O(n);

三、中序遍历逆序

3.1  思路分析

  1. 二叉搜索树的中序遍历是一个升序序列,其逆序是一个降序序列,那么其升序中第k大的数就是降序是第k个数字,比如1 2 3 4 5,其第2大的数位4,其逆序5 4 3 2 1,第2个数字为4;
  2. 首先递归右子树,然后对于当前节点,执行 k = k - 1操作,直到 k == 0,将当前节点值保存到res中,然后递归左子树;
  3. 因为在执行完当前节点的操作后,还需递归左子树,而此时k可能已为0,因此加入递归退出条件 k == 0时,直接退出;

3.2  代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int res,k;
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return res;
    }
    public void dfs(TreeNode root) {
        if(root == null) {
            return;
        }
        if(k == 0) return;
        dfs(root.right);
        if(--k == 0) res = root.val;
        dfs(root.left);
    }
}

3.3  复杂度分析

  • 时间复杂度为O(N),当树退化为链表时,无论k值大小,递归深度都为N,占用O(N)的时间;
  • 空间复杂度为O(N),当树退化为链表时,系统使用O(N)大小的栈空间;

四、学习地址

作者:Krahets

链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/solution/mian-shi-ti-54-er-cha-sou-suo-shu-de-di-k-da-jie-d/

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页