当前位置: 首页 > news >正文

【LeetCode热题100道笔记】二叉搜索树中第 K 小的元素

题目描述

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 小的元素(从 1 开始计数)。

示例 1:
在这里插入图片描述
输入:root = [3,1,4,null,2], k = 1
输出:1

示例 2:
在这里插入图片描述
输入:root = [5,3,6,2,4,null,null,1], k = 3
输出:3

提示:

树中的节点数为 n 。
1<=k<=n<=1041 <= k <= n <= 10^41<=k<=n<=104
0<=Node.val<=1040 <= Node.val <= 10^40<=Node.val<=104

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

思考一:中序遍历(利用BST有序特性)

核心是借助BST中序遍历的有序性:中序遍历(左→根→右)会生成严格递增的节点值序列,序列中第k-1个元素(索引从0开始)即为第k小元素。

算法过程

  1. 中序遍历收集节点值
    • 初始化空数组arr,用于存储中序遍历的节点值;
    • 递归执行中序遍历:先遍历左子树(确保更小的元素先入数组),再将当前节点值加入arr,最后遍历右子树;
    • 若节点为空,直接返回(递归终止条件)。
  2. 提取第k小元素
    • 遍历完成后,arr已按递增排序,返回arr[k-1](第k个元素,索引为k-1)。

时空复杂度

  • 时间复杂度:O(n),n为二叉树节点总数。
    原因:中序遍历需遍历所有节点(最坏情况需收集全部节点值才能找到第k小),总操作次数与节点数线性相关。
  • 空间复杂度:O(n)。
    原因:数组arr需存储所有节点值(最坏情况),递归调用栈需O(h)(h为树高),总空间由数组主导,为O(n)。

代码

/*** Definition for a binary tree node.* function TreeNode(val, left, right) {*     this.val = (val===undefined ? 0 : val)*     this.left = (left===undefined ? null : left)*     this.right = (right===undefined ? null : right)* }*/
/*** @param {TreeNode} root* @param {number} k* @return {number}*/
var kthSmallest = function(root, k) {const arr = [];inOrder(root, arr);return arr[k-1];
};function inOrder(node, arr) {if (!node) return;inOrder(node.left, arr);arr.push(node.val);inOrder(node.right, arr);
}

思考二:最大堆(动态维护最小的k个元素)

核心是用容量为k的最大堆动态筛选“当前遍历到的最小k个元素”:堆顶始终是这k个元素中的最大值,遍历完成后堆顶即为第k小元素(因比堆顶小的元素有k-1个,堆顶自然是第k小)。
注:JavaScript无内置堆,需实现简易最大堆(按值大小排序,堆顶为最大值)。

算法过程

  1. 实现最大堆
    • 堆初始化时固定容量为k,超过容量时自动弹出堆顶(最大值);
    • 提供push(插入元素并调整堆结构)、front(获取堆顶元素)、size(获取堆元素个数)方法。
  2. 深度优先遍历(DFS)树节点
    • 遍历所有节点,对每个节点值:
      • 若堆中元素不足k个,直接入堆;
      • 若堆已满且当前节点值 < 堆顶(说明当前节点值是更小的元素,需替换堆顶),弹出堆顶后将当前节点值入堆;
  3. 返回结果:遍历完成后,堆顶元素即为第k小元素。

时空复杂度

  • 时间复杂度:O(n log k),n为二叉树节点总数。
    原因:遍历所有节点需O(n),每个节点入堆/出堆操作需O(log k)(堆的调整时间与堆容量k的对数相关),总时间为O(n log k)。
  • 空间复杂度:O(k + h),h为树高。
    原因:堆占用O(k)空间,DFS递归栈占用O(h)空间,总空间由堆主导(k远小于n时比中序遍历更优)。

代码

/*** Definition for a binary tree node.* function TreeNode(val, left, right) {*     this.val = (val===undefined ? 0 : val)*     this.left = (left===undefined ? null : left)*     this.right = (right===undefined ? null : right)* }*/
/*** @param {TreeNode} root* @param {number} k* @return {number}*/
var kthSmallest = function(root, k) {const priorityQueue = new MyMaxPriorityQueue(k);dfs(root, priorityQueue, k);return priorityQueue.front();    
};function dfs(node, queue, k) {if (!node) return;if (queue.size() < k || queue.front() > node.val) {queue.push(node.val);}dfs(node.left, queue, k);dfs(node.right, queue, k);
}class MyMaxPriorityQueue {constructor(capacity = 1000) {this._data = [];this._capacity = capacity;this._size = 0;}front() {return this._data[0];}push(num) {if (this._capacity === this._size) {this.pop();}this._data.push(num);this.swim();this._size++;}pop() {if (this._data.length === 0) return;[this._data[0], this._data[this._data.length-1]] = [this._data[this._data.length-1], this._data[0]];const item = this._data.pop();this.sink();this._size--;return item;}swim(index = this._data.length-1) {while (index > 0) {let pIndex = Math.floor((index-1)/2);if (this._data[index] > this._data[pIndex]) {[this._data[index], this._data[pIndex]] = [this._data[pIndex], this._data[index]];index = pIndex;continue;}break;}}sink(index = 0) {const n = this._data.length;while (true) {let left = 2 * index + 1;let right = left + 1;let biggest = index;if (left < n && this._data[left] > this._data[index]) {biggest = left;}if (right < n && this._data[right] > this._data[biggest]) {biggest = right;}if (biggest !== index) {[this._data[biggest], this._data[index]] = [this._data[index], this._data[biggest]];index = biggest;continue;}break;}}size() {return this._size;}}

文章转载自:

http://lgjaadeD.gwqkk.cn
http://OD4wvSzT.gwqkk.cn
http://QnthqWnA.gwqkk.cn
http://8kWVf9xT.gwqkk.cn
http://gGV5FcL1.gwqkk.cn
http://oM0mFYHR.gwqkk.cn
http://1LlGDDEf.gwqkk.cn
http://JqI4yOFH.gwqkk.cn
http://AILuHAHk.gwqkk.cn
http://B2Qys9Kn.gwqkk.cn
http://IVksjo1J.gwqkk.cn
http://m9nueh1B.gwqkk.cn
http://aidH5shX.gwqkk.cn
http://zoW8wJKk.gwqkk.cn
http://4DDcBgh4.gwqkk.cn
http://5EyOvo6R.gwqkk.cn
http://0wRKlJjS.gwqkk.cn
http://uaF5YCrP.gwqkk.cn
http://25ggYorw.gwqkk.cn
http://lyljacYy.gwqkk.cn
http://hjneQvaG.gwqkk.cn
http://3bhFjVgZ.gwqkk.cn
http://HMuiwXUz.gwqkk.cn
http://4X5o3TWM.gwqkk.cn
http://nWvrni2g.gwqkk.cn
http://xtbM5BKy.gwqkk.cn
http://89dpuMDW.gwqkk.cn
http://05vkmT5m.gwqkk.cn
http://LZFf6rQk.gwqkk.cn
http://12sfA4qp.gwqkk.cn
http://www.dtcms.com/a/370936.html

相关文章:

  • HMI(人机界面)
  • 懒加载的概念
  • panther X2 armbian24 安装宝塔(bt)面板注意事项
  • 少儿配音教育:广州声与色在线科技有限公司打造趣味课程,助力青少年语言能力提升
  • 零基础学习数据采集与监视控制系统SCADA
  • springboot vue sse消息推送,封装系统公共消息推送前后端方法
  • 万字长文详解 MyCat 分表分库:从 0 到 1 构建高可用订单系统
  • Transformer架构(详解)
  • MySQL连接字符串中的安全与性能参数详解
  • Apache Kylin:一款免费开源、高并发、高性能的OLAP引擎
  • Linux 96 shell:expect { }
  • 项目中的一些比较实用的自定义控件
  • 【Canvas与图标】古铜色“HTML”图标
  • 【Postman】对GET请求的参数进行URL编码
  • 【IQA技术专题】 多尺度的transformer网络IQA:MUSIQ
  • 嵌入式学习——ARM 体系架构1
  • Kafka面试精讲 Day 9:零拷贝技术与高性能IO
  • 【65页PPT】智慧数字乡村农业大数据平台解决方案(附下载方式)
  • 服务器线程高占用定位方法
  • 【基础-单选】关于UIAbility的启动模式,下列说法错误的是
  • 【111】基于51单片机停车场车位管理系统【Proteus仿真+Keil程序+报告+原理图】
  • mysql死锁排查与解决
  • 从零开始学AI——14
  • 【CSP-S】数据结构 ST 表详解
  • 积分球的使用——简易版
  • 基于Echarts+HTML5可视化数据大屏展示-图书馆大屏看板
  • 讲解一下冒泡排序
  • 【基础-单选】关于容器组件Row和Column,下面说法错误的是
  • 【佳易王药品进销存软件实测】:操作简单 + 全流程管理,医药台账管理好帮手#软件教程全解析
  • 项目升级--Nginx