二叉搜索树的第K大问题|刷题打卡

349 阅读2分钟

题目描述

给定一棵二叉搜索树,请找出其中第K大的节点。(本题是剑指Offer第54题)

示例 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 ≤ 二叉搜索树元素个数。

中序遍历法

本文解题思路的前提是知道二叉搜索树的中序遍历是递增的

中序遍历后的树节点是递增的,所以问题就可以转化为找出中序遍历后递增序列的倒数第k个节点。中序遍历的递归写法为:左子树、根节点、右子树,在二叉搜索树中是一个递增序列,那么它的倒序就是:右子树、根节点、左子树,是一个递减序列。因此我们可以在遍历节点的同时统计遍历的数目,来判断是否是第K个节点。

递归的终止条件:

  1. root == null,表示越过了叶子节点,直接返回。
  2. k == 0,分为两种情况:
    • k == 0 ,表示已经找到第K大的值,不需要执行后面的递归了,直接返回。
    • --k == 0,表示当前结点的值为第K大的值,返回该值,并结束后面的递归。
    int result, k;

    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return result;
    }

    public void dfs(TreeNode root) {
        if (root == null) return;
        dfs(root.right);
        if (k == 0) return;
        if (--k == 0) {
            result = root.val;
            return;
        }
        dfs(root.left);
    }

时间复杂度:O(N) 空间复杂度:O(N)

总结

本题的思路在于理解中序遍历和二叉搜索树。算法中有一个优化点值得注意的是k==0在什么地方 return。个人理解的是:当遍历右子树已经得到第K大的值时,后续的根节点和左子树就不应该在继续执行,所以我在右子树之后加上了(k == 0)的判断。