LeetCode 230. 二叉搜索树中第 K 小的元素

发布于 2023-10-05 10:22:06 字数 3228 浏览 32 评论 0

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。

说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。

示例 1:

输入: root = [3,1,4,null,2], k = 1

 3
/ \
1 4
\
2

输出: 1
示例 2:

输入: root = [5,3,6,2,4,null,null,1], k = 3

      5
/ \
3 6
/ \
2 4
/
1

输出: 3
进阶:
如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化 kthSmallest 函数?

前置知识

  • 中序遍历

公司

  • 阿里
  • 腾讯
  • 百度
  • 字节

思路

解法一:

由于‘中序遍历一个二叉查找树(BST)的结果是一个有序数组’ ,因此我们只需要在遍历到第 k 个,返回当前元素即可。

解法二:

联想到二叉搜索树的性质,root 大于左子树,小于右子树,如果左子树的节点数目等于 K-1,那么 root 就是结果,否则如果左子树节点数目小于 K-1,那么结果必然在右子树,否则就在左子树。 因此在搜索的时候同时返回节点数目,跟 K 做对比,就能得出结果了。

关键点解析

  • 中序遍历

代码

解法一:

JavaScript Code:

/*
 * @lc app=leetcode id=230 lang=javascript
 *
 * [230] Kth Smallest Element in a BST
 */
/**
 * 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 kthSmallest = function (root, k) {
  const stack = [root];
  let cur = root;
  let i = 0;

  function insertAllLefts(cur) {
    while (cur && cur.left) {
      const l = cur.left;
      stack.push(l);
      cur = l;
    }
  }
  insertAllLefts(cur);

  while ((cur = stack.pop())) {
    i++;
    if (i === k) return cur.val;
    const r = cur.right;

    if (r) {
      stack.push(r);
      insertAllLefts(r);
    }
  }

  return -1;
};

Java Code:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
private int count = 1;
private int res;

public int KthSmallest (TreeNode root, int k) {
    inorder(root, k);
    return res;
}

public void inorder (TreeNode root, int k) {
    if (root == null) return;

    inorder(root.left, k);

    if (count++ == k) {
        res = root.val;
        return;
    }

    inorder(root.right, k);
}

解法二:

JavaScript Code:

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
function nodeCount(node) {
  if (node === null) return 0;

  const l = nodeCount(node.left);
  const r = nodeCount(node.right);

  return 1 + l + r;
}
/**
 * @param {TreeNode} root
 * @param {number} k
 * @return {number}
 */
var kthSmallest = function (root, k) {
  const c = nodeCount(root.left);
  if (c === k - 1) return root.val;
  else if (c < k - 1) return kthSmallest(root.right, k - c - 1);
  return kthSmallest(root.left, k);
};

复杂度分析

  • 时间复杂度:$O(n^2)$,其中 n 为树的节点总数。
  • 空间复杂度:$O(h)$ ,其中 h 为树的高度。

扩展

这道题有一个 follow up:

What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?

建议大家思考一下。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文