LeetCode 算法:二叉搜索树中第K小的元素 c++

news2024/11/23 9:34:44

原题链接🔗:二叉搜索树中第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 <= 104
  • 0 <= Node.val <= 104

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

题解

二叉搜索树

二叉搜索树(Binary Search Tree,简称BST)是一种特殊的二叉树,它具有以下性质:

  1. 有序性:对于树中的每个节点,其左子树上所有节点的值都小于该节点的值,其右子树上所有节点的值都大于或等于该节点的值。

  2. 没有兄弟节点:每个节点最多只有一个左子节点和一个右子节点。

  3. 每个节点存储一个键值:在二叉搜索树中,每个节点通常存储一个键值,该键值用于维护树的有序性。

  4. 树结构:二叉搜索树是树结构,这意味着它是一个没有环的分层数据结构。

  5. 平衡性:理想情况下,二叉搜索树是平衡的,即左右子树的高度差不超过1。平衡的二叉搜索树可以保证操作(如搜索、插入和删除)的时间复杂度为O(log n)。但在最坏的情况下,如果插入的元素是有序的,树将退化成链表,时间复杂度变为O(n)。

二叉搜索树的应用非常广泛,因为它提供了高效的数据存储和检索方式。以下是一些基本操作:

  • 搜索:在BST中搜索一个元素,可以从头节点开始,根据目标值与当前节点值的比较结果,决定是向左子树还是向右子树搜索。这个过程可以递归或迭代进行,直到找到目标值或到达叶子节点。

  • 插入:向BST中插入一个新元素,首先搜索该元素应该插入的位置,然后根据BST的性质将其插入到适当的位置。

  • 删除:从BST中删除一个元素,需要考虑几种情况:删除的节点没有子节点、有一个子节点或有两个子节点。在删除节点后,需要调整树以保持BST的性质。

  • 遍历:BST可以通过前序、中序、后序和层序遍历来访问所有节点。中序遍历特别有用,因为它将按照升序访问所有节点。

二叉搜索树的实现通常涉及到递归和迭代技术,以及对树结构的深入理解。在实际应用中,为了提高性能,可能会使用自平衡的二叉搜索树,如AVL树或红黑树。

中序遍历

二叉树的中序遍历是一种遍历二叉树的方法,其遍历顺序为:先遍历左子树,然后访问根节点,最后遍历右子树。这种遍历方式可以确保在访问任何节点之前,其所有左子节点已经被访问过,同样地,在访问任何节点之后,其所有右子节点也会被访问。

中序遍历对于二叉搜索树(BST)特别有用,因为它会按照节点值的非递减顺序访问所有节点,即中序遍历的结果是一个有序数组。

以下是中序遍历的基本步骤:

  1. 访问左子树:首先,递归地对左子树进行中序遍历。

  2. 访问根节点:然后,访问根节点。在遍历过程中,通常会将根节点的值添加到一个列表中。

  3. 访问右子树:最后,递归地对右子树进行中序遍历。

中序遍历的时间复杂度为O(n),其中n是树中节点的数量,因为它需要访问树中的每个节点。空间复杂度取决于递归调用的深度,最坏情况下是O(n)(当树退化成链表时),最好情况下是O(log
n)(当树是平衡的)。

中序遍历递归法

  1. 解题思路

在LeetCode上,题目“二叉搜索树中第K小的元素”通常要求你找到一个二叉搜索树(BST)中第K小的元素。二叉搜索树的性质是:对于树中的任何节点,其左子树上的所有节点的值都小于该节点的值,其右子树上的所有节点的值都大于该节点的值。

解题思路如下:

  • 理解BST的性质:首先,要利用BST的性质来简化问题。在BST中,中序遍历(左-根-右)会以递增的顺序访问所有节点。

  • 中序遍历:由于题目要求找到第K小的元素,我们可以通过中序遍历BST来实现。在遍历过程中,记录访问的节点数量。

  • 计数与停止:在中序遍历的过程中,当访问到第K个节点时,停止遍历。这个节点就是所求的第K小的元素。

  • 递归或迭代:中序遍历可以通过递归或迭代的方式实现。递归是更直观的方法,但迭代可以避免潜在的递归深度问题。

  • 实现算法:编写代码实现上述逻辑。

  1. c++ demo
#include <iostream>
#include <vector>

// 定义二叉树的节点结构
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
public:
    // 主函数,接收二叉搜索树的根节点和K值,返回第K小的元素
    int kthSmallest(TreeNode* root, int k) {
        std::vector<int> elements;
        inOrderTraversal(root, elements, k);
        return elements[k - 1]; // 由于数组索引从0开始,所以用k-1
    }

private:
    // 中序遍历辅助函数,同时接收一个vector来存储遍历结果
    void inOrderTraversal(TreeNode* node, std::vector<int>& elements, int k) {
        if (!node || elements.size() >= k) {
            return;
        }

        // 遍历左子树
        inOrderTraversal(node->left, elements, k);

        // 访问当前节点
        if (elements.size() < k) {
            elements.push_back(node->val);
        }

        // 遍历右子树
        inOrderTraversal(node->right, elements, k);
    }
};

// 示例使用
int main() {
    // 构建一个示例二叉搜索树
    //       3
    //      / \
    //     1   4
    //      \
    //       2
    TreeNode* root = new TreeNode(3);
    root->left = new TreeNode(1);
    root->right = new TreeNode(4);
    root->left->right = new TreeNode(2);

    Solution solution;
    int k = 3; // 假设我们要找第3小的元素
    std::cout << "The " << k << "st smallest element is: " << solution.kthSmallest(root, k) << std::endl;

    // 清理分配的内存(在实际应用中应该使用智能指针来自动管理内存)
    delete root->left->right;
    delete root->left;
    delete root->right;
    delete root;

    return 0;
}
  • 输出结果:

The 3st smallest element is: 3

  1. 代码仓库地址:kthSmallest

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1876934.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

页面开发感想

页面开发 1、 前端预览 2、一些思路 2.1、首页自定义element-plus的走马灯 :deep(.el-carousel__arrow){border-radius: 0%;height: 10vh; }需要使用:deep(标签)才能修改样式 或者 ::v-deep 标签 2.2、整体设计思路 <template><div class"card" style&…

机器学习第四十五周周报 SAM优化器

文章目录 week45 SAM优化器摘要Abstract1. 题目2. Abstract3. 锐度感知最小化3.1 问题提出3.2 方法提出 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程 5. 结论6.代码复现小结参考文献 week45 SAM优化器 摘要 本周阅读了题为Sharpness-Aware Minimization for Efficien…

! Warning: `flutter` on your path resolves to

目录 项目场景&#xff1a; 问题描述 原因分析&#xff1a; 解决方案&#xff1a; 1. 检查并更新.bash_profile或.zshrc文件 2.添加Flutter路径到环境变量 3. 加载配置文件 4.验证Flutter路径 5.重新启动终端 项目场景&#xff1a; 今天重新安装了AndroidStudio,并配置…

Postman设置请求间自动保存返回参数,方便后续请求调用,减少复制粘贴

postman中常常出现&#xff1a;有两个请求&#xff0c;一个请求首先获取验证码或者token&#xff0c;再由得到的验证码或token编写body发送另一个请求。如何设置两个请求间自动关联相关数据呢&#xff1f; 通过环境存储全局变量 现在有两个请求如下图&#xff0c;生成验证码是…

如何制作鼠标悬浮后伸缩的搜索框

引言 许多博客都在使用的伸缩搜索框制作教程 成品展示&#xff08;颜色自行搭配&#xff09; 初步布局 居中盒子&&初始化样式 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewpo…

进程间通信简介-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板

进程间通信简介 进程间通信简介 进程间进程简称IPC(interprocess communication)&#xff0c;进程间通信就是在不同进程之间传递信息或交换信息 进程间通信的目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;多个进程之间共享同样的…

【Docker】集群容器监控和统计 CAdvisor+lnfluxDB+Granfana的基本用法

集群容器监控和统计组合&#xff1a;CAdvisorlnfluxDBGranfana介绍 CAdvisor&#xff1a;数据收集lnfluxDB&#xff1a;数据存储Granfana&#xff1a;数据展示 ‘三剑客’ 安装 通过使用compose容器编排&#xff0c;进行安装。特定目录下新建文件docker-compose.yml文件&am…

使用Vercel 搭建自己的Dashy导航页

背景 Dashy 是一个开源的自托管导航页面配置服务&#xff0c;它具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。用户可以利用 Dashy 将自己常用的一些网站聚合起来&#xff0c;形成一个个性化的导航页面。 同类的竞品还有Heimdall, Flare 等。 可以通过Docker 等…

uniapp,uni-fab组件拖动属性,替代方案

文章目录 1. 背景2. 替代方案2.1 方案一2.2 方案二参考1. 背景 最近基于uniapp开发一款设备参数调试的APP软件,其中有使用到悬浮按钮,快速开发阶段,为了能尽快上线,直接使用了uni-ui的扩展组件uni-fab,参考【1】,效果如下图: 后期,相应的界面内容增多,由于uni-fab是…

TS_类型

目录 1.类型注解 2.类型检查 3.类型推断 4.类型断言 ①尖括号&#xff08;<>&#xff09;语法 ②as语法 5.数据类型 ①boolean ②number ③string ④undefined 和 null ⑤数组和元组 ⑥枚举 ⑦any 和void ⑧symbol ⑨Function ⑩Object 和 object 6.高…

在晋升受阻或遭受不公待遇申诉时,这样写是不是好一些?

在晋升受阻或遭受不公待遇申诉时&#xff0c;这样写是不是好一些&#xff1f; 在职场中&#xff0c;晋升受阻或遭受不公待遇是员工可能面临的问题之一。面对这样的情况&#xff0c;如何撰写一份有效的申诉材料&#xff0c;以维护自己的合法权益&#xff0c;就显得尤为重要。#李…

mathcup大数据竞赛论文中集成学习(或模型融合)的运用分析

ps: (模型融合和集成学习是两个紧密相关但又有所区别的概念。集成学习是一种更广泛的范式&#xff0c;而模型融合可以被视为集成学习的一种特殊形式或策略。) 1.集成学习原理 图1 如图1所示&#xff0c;集成学习是一种通过结合多个机器学习模型的预测来提高整体性能的策略。其…

【MongoDB】分布式数据库入门级学习

SueWakeup 个人主页&#xff1a;SueWakeup 系列专栏&#xff1a;为祖国的科技进步添砖Java 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f8;友情提供 凯楠&#x1f4f8; - 不夜长安 目录 MongoDB 相关 数据库排行榜单 MongoDB 中文官网 菜鸟…

Linux开发讲课19--- SPI原理

一、概述 SPI&#xff08;Serial Peripheral Interface&#xff09;&#xff0c;是一种高速串行全双工的接口。最早由Motorola首先提出的全双工同步串行外围接口&#xff0c;采用主从模式(Master—Slave)架构&#xff0c;支持一个或多个Slave设备。SPI接口主要应用在EEPROM、F…

Django 自定义标签

1&#xff0c;简单标签 1.1 添加自定义标签函数 Test/app5/templatetags/mytags.py from django import template register template.Library() register.simple_tag() def show_title(value, n):if len(value) > n:return f{value[:n]}...else:return value 1.2 添加视…

fiddler 返回Raw乱码

有时会发现自己发送的请求后&#xff0c;返回结果Raw里面是乱码&#xff0c;可以勾选Decode并重新发送请求就解决了 这个时候将Decode勾选一下 此时就好了

【名企专访】|格行自有格行的骄傲,格行骄傲在哪?格行随身wifi火爆出圈的真实内幕!

最近刷视频在一个随身wifi的帖子下边看到&#xff0c;有个网友这样回复&#xff1a;“随身wifi行业真的该整治了&#xff0c;到处是跑路的&#xff0c;夸大宣传的&#xff0c;本来在线上买就是图个方便&#xff0c;现在搞得不敢买。本来利民的产品&#xff0c;被搞得乌烟瘴气&a…

多线程引发的安全问题

前言&#x1f440;~ 上一章我们介绍了线程的一些基础知识点&#xff0c;例如创建线程、查看线程、中断线程、等待线程等知识点&#xff0c;今天我们讲解多线程下引发的安全问题 线程安全&#xff08;最复杂也最重要&#xff09; 产生线程安全问题的原因 锁&#xff08;重要…

教您设置打开IDM下载浮动条的快捷键 全网最强下载神器idm怎么使用教程 idm浮动条不显示怎么办

很多人都知道Internet Download Manager(以下简称IDM)是一款非常优秀的下载提速软件。它功能强大&#xff0c;几乎能下载网页中的所有数据&#xff08;包括视频、音频、图片等&#xff09;&#xff0c;且适用于现在市面上几乎所有的浏览器&#xff0c;非常受大家欢迎。 在使用I…

高数下速通

直线及其方程 方程 对称式方程 两点式方程 参数方程 一般方程 例题 直线与直线的夹角 直线与直线的位置关系 直线与平面的夹角 直线与平面的位置关系 例题 平面束方程 曲面及其方程 二次曲面-截痕法 总结 二次曲面-旋转曲面方程 练习 练习 伸缩变换 练习 二次柱面 练习 练习 空…