算法刷题day18|二叉树:669. 修剪二叉搜索树、108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树

669. 修剪二叉搜索树

如果结点的值小于 low,那么说明该结点及它的左子树都不符合要求,我们返回对它的右结点进行修剪后的结果;如果结点的值大于 high,那么说明该结点及它的右子树都不符合要求,我们返回对它的左子树进行修剪后的结果;如果结点的值位于区间 [low,high],我们将结点的左结点设为对它的左子树修剪后的结果,右结点设为对它的右子树进行修剪后的结果。

递归法

class Solution {
public:TreeNode* trimBST(TreeNode* root, int low, int high) {if (root == nullptr) return root;if (root->val < low){return trimBST(root->right, low, high);}else if (root->val > high){return trimBST(root->left, low, high);}else {root->left = trimBST(root->left, low, high);root->right = trimBST(root->right, low, high);return root;}}
};

迭代法

class Solution {
public:TreeNode* trimBST(TreeNode* root, int L, int R) {if (!root) return nullptr;// 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭while (root != nullptr && (root->val < L || root->val > R)) {if (root->val < L) root = root->right; // 小于L往右走else root = root->left; // 大于R往左走}TreeNode *cur = root;// 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况while (cur != nullptr) {while (cur->left && cur->left->val < L) {cur->left = cur->left->right;}cur = cur->left;}cur = root;// 此时root已经在[L, R] 范围内,处理右孩子大于R的情况while (cur != nullptr) {while (cur->right && cur->right->val > R) {cur->right = cur->right->left;}cur = cur->right;}return root;}
};

108. 将有序数组转换为二叉搜索树

递归版本一

class Solution {
public:TreeNode* sortedArrayToBST(vector<int>& nums) {if (nums.size() == 0) return nullptr;//把中间的下标作为根节点int rootIndex = nums.size() / 2;TreeNode* root = new TreeNode(nums[rootIndex]);int size = nums.size();//左子树的递归,左闭右开vector<int> left = vector<int>(nums.begin(), nums.begin() + rootIndex);//右子树的递归,左闭右开vector<int> right = vector<int>(nums.begin() + rootIndex + 1, nums.end());root->left = sortedArrayToBST(left);root->right = sortedArrayToBST(right);return root;}
};

递归版本二

class Solution {
private:TreeNode* traversal(vector<int>& nums, int left, int right) {if (left > right) return nullptr;int mid = left + ((right - left) / 2);TreeNode* root = new TreeNode(nums[mid]);root->left = traversal(nums, left, mid - 1);root->right = traversal(nums, mid + 1, right);return root;}
public:TreeNode* sortedArrayToBST(vector<int>& nums) {TreeNode* root = traversal(nums, 0, nums.size() - 1);return root;}
};

迭代法

迭代法可以通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下标,一个队列放右区间下标。

class Solution {
public:TreeNode* sortedArrayToBST(vector<int>& nums) {if (nums.size() == 0) return nullptr;TreeNode* root = new TreeNode(0);   // 初始根节点queue<TreeNode*> nodeQue;           // 放遍历的节点queue<int> leftQue;                 // 保存左区间下标queue<int> rightQue;                // 保存右区间下标nodeQue.push(root);                 // 根节点入队列leftQue.push(0);                    // 0为左区间下标初始位置rightQue.push(nums.size() - 1);     // nums.size() - 1为右区间下标初始位置while (!nodeQue.empty()) {TreeNode* curNode = nodeQue.front();nodeQue.pop();int left = leftQue.front(); leftQue.pop();int right = rightQue.front(); rightQue.pop();int mid = left + ((right - left) / 2);curNode->val = nums[mid];       // 将mid对应的元素给中间节点if (left <= mid - 1) {          // 处理左区间curNode->left = new TreeNode(0);nodeQue.push(curNode->left);leftQue.push(left);rightQue.push(mid - 1);}if (right >= mid + 1) {         // 处理右区间curNode->right = new TreeNode(0);nodeQue.push(curNode->right);leftQue.push(mid + 1);rightQue.push(right);}}return root;}
};

538. 把二叉搜索树转换为累加树

中序遍历+双指针

定义一个栈,中序遍历二叉搜索树,将树节点压入栈,然后定义双指针来更新每个节点的值

class Solution {
public: void inorder(TreeNode* root, stack<TreeNode*> &stk) {if (root == nullptr) return;inorder(root->left, stk);stk.push(root);inorder(root->right, stk);}TreeNode* convertBST(TreeNode* root) {if (root == NULL) return root;stack<TreeNode*> stk;inorder(root, stk);TreeNode* next = stk.top();stk.pop();while (!stk.empty()){TreeNode* cur = stk.top();stk.pop();cur->val += next->val;next = cur;}return root;}
};

注:1.一开始只是想到用栈存储节点的值,导致后续更新节点的值的时候,对节点的操作不对,一直超时。后来看了别人的解法才知道直接存储节点更容易更新节点的值。

2.inorder中的stack要用引用传递,不能用值传递,或者直接将stack定义为全局变量

值传递(x)、地址传递(*x)、引用传递(&x)的区别

值传递:传值其实就是一个操作副本的概念,我们在传递参数时,会将实参的副本复制到形参中。形参在函数内的修改不会影响实参。

#include <iostream>void modifyValue(int x) {x = 20;  // 只是修改了副本,不影响原始数据
}int main() {int a = 10;modifyValue(a);std::cout << "a: " << a << std::endl;  // 输出仍然是10return 0;
}

地址传递:指针可以理解为是指向变量存储位置的一个箭头,通过传递指针,将实参的地址传递给形参。形参在函数内的修改会直接影响实参。

#include <iostream>void modifyValue(int *x) {*x = 20;  // 修改了实参的值
}int main() {int a = 10;modifyValue(&a);std::cout << "a: " << a << std::endl;  // 输出是20return 0;
}

引用传递:引用传递的不是副本,也不是地址,而是指定的那个变量。通过传递引用,将实参的引用传递给形参。形参在函数内的修改会直接影响实参。

#include <iostream>void modifyValue(int &x) {x = 20;  // 修改了实参的值
}int main() {int a = 10;modifyValue(a);std::cout << "a: " << a << std::endl;  // 输出是20return 0;
}

反序中序递归

class Solution {
private:int pre = 0; // 记录前一个节点的数值void traversal(TreeNode* cur) { // 右中左遍历if (cur == NULL) return;traversal(cur->right);cur->val += pre;pre = cur->val;traversal(cur->left);}
public:TreeNode* convertBST(TreeNode* root) {pre = 0;traversal(root);return root;}
};

迭代法

class Solution {
private:int pre; // 记录前一个节点的数值void traversal(TreeNode* root) {stack<TreeNode*> st;TreeNode* cur = root;while (cur != NULL || !st.empty()) {if (cur != NULL) {st.push(cur);cur = cur->right;   // 右} else {cur = st.top();     // 中st.pop();cur->val += pre;pre = cur->val;cur = cur->left;    // 左}}}
public:TreeNode* convertBST(TreeNode* root) {pre = 0;traversal(root);return root;}
};

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

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

相关文章

2023IMO预选题几何第6题

锐角 △ A B C \triangle ABC △ABC 的外接圆为 ω \omega ω, 圆 I I I 与 ω \omega ω 内切于 A A A, 且与 B C BC BC 切于点 D D D. 设直线 A B AB AB, A C AC AC 分别与 I I I 交于点 P P P, Q Q Q, 点 M M M, N N N 在直线 B C BC BC 上, 满足 B B B 是 …

Python+selenium web自动化测试知识点合集2

选择元素 对于百度搜索页面&#xff0c;如果我们想自动化输入“selenium”&#xff0c;怎么做呢&#xff1f; 这就是在网页中&#xff0c;操控界面元素。 web界面自动化&#xff0c;要操控元素&#xff0c;首先需要 选择 界面元素 &#xff0c;或者说 定位 界面元素 就是 先…

基于豆瓣音乐、豆瓣图书、豆瓣电影详情获取、长短评获取【豆瓣全家桶系列】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 豆瓣电影系列基于Python的海量豆瓣电影、数据获取、数据预处理、数据分析、可视化、大屏设计项目&#xff08;含数据库&#xff09;基于多种机器学习的豆瓣电影评分预测与多维度可视化【可…

设计模式-结构型-09-外观模式

文章目录 1、影院管理项目2、外观模式基本介绍4、MyBatis 框架源码分析5、外观模式总结 1、影院管理项目 组建一个家庭影院&#xff1a; DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机&#xff0c;要求完成使用家庭影院的功能&#xff0c;其过程为&#xff1a; 直接用…

Docker安装oracle19c

文章目录 Docker安装oracle19c1. 拉取镜像2. 创建目录并赋权3. 构建容器并启动4. 查看日志5. 登录docker容器里面6. 登录sqlplus 创建PDB用户7. 查看show pdbs7. 切换数据库8. 创建用户9. 授权10. 使用navicat连接11. 参考和感谢 Docker安装oracle19c 1. 拉取镜像 docker pul…

Java集合——Array、ArrayList、LinkedList

1. ArrayList和Array的区别 1. 大小和自动扩容 Array&#xff1a;创建时指定大小&#xff0c;大小固定。若数组被创建&#xff0c;其大小不能更改 ArrayList&#xff1a;动态数组实现&#xff0c;可以动态增长或缩小。在不断添加元素时&#xff0c;ArrayList会自动进行扩容 …

3.4-GRU

1网络结构 1.1与LSTM相比 LSTM里面有三个门&#xff0c;还有一个增加信息的tanh单元&#xff0c;参数量相较于RNN显著增加&#xff1b; 因此GRU在参数上比LSTM要少&#xff1b; 另外&#xff0c;LSTM 将必要信息记录在记忆单元中&#xff0c;并基于记忆单元的信息计算隐藏状…

关键词查找【Knuth-Morris-Pratt (KMP) 算法】

一个视频让你彻底学懂KMP算法_哔哩哔哩_bilibili KMP算法的核心是利用匹配失败后的信息&#xff0c;尽量减少模式串与主串的匹配次数以达到快速匹配的目的。 第一步&#xff1a;计算模式串(子串)和next[j]数组 模式串 前2位字母的next[j]固定是0 和 1 后续字母的nex[j]&…

特斯拉财报看点:FSD拳打华为,Robotaxi 脚踢百度

大数据产业创新服务媒体 ——聚焦数据 改变商业 特斯拉发最新财报了&#xff0c;这不仅是一份财务报告&#xff0c;更是一张未来发展的蓝图。在这份蓝图中&#xff0c;两个关键词格外耀眼——FSD&#xff08;全自动驾驶系统&#xff09;和Robotaxi&#xff08;无人驾驶出租车&…

项目都做完了,领导要求国际化????--JAVA后端篇

springboot项目国际化相信各位小伙伴都会&#xff0c;很简单&#xff0c;但是怎么项目都做完了&#xff0c;领导却要求国际化文件就很头疼了 国际化的SpringBoot代码&#xff1a; 第一步&#xff1a;创建工具类 /*** 获取i18n资源文件** author bims*/ public class Message…

day08:订单状态定时处理、来单提醒和客户催单

文章目录 Spring Task介绍cron表达式入门案例 订单状态定时处理需求分析代码开发扩展 WebSocket介绍入门案例特点 来单提醒需求分析和设计代码实现 客户催单需求分析和设计代码实现 Spring Task 介绍 Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时…

20240725java的Controller、DAO、DO、Mapper、Service层、反射、AOP注解等内容的学习

在Java开发中&#xff0c;‌controller、‌dao、‌do、‌mapper等概念通常与MVC&#xff08;‌Model-View-Controller&#xff09;‌架构和分层设计相关。‌这些概念各自承担着不同的职责&#xff0c;‌共同协作以构建和运行一个应用程序。‌以下是这些概念的解释&#xff1a;‌…

Java 面试相关问题(下)——JVM相关问题GC相关问题

1. 类加载1.1 类的生命周期说一下&#xff1f;1.2 介绍下生命周期中的加载&#xff1f;1.3 介绍下生命周期中的验证&#xff1f;1.4 介绍下生命周期中的准备&#xff1f;1.5 介绍下生命周期中的解析&#xff1f;1.6 介绍下生命周期中的初始化&#xff1f;1.7 介绍下生命周期中的…

剑和沙盒 6 - 线程辱骂 – 使用线程名称进行攻击

强调&#xff1a; 进程注入是攻击者工具包中的重要技术之一。在下面的文章中 解释了如何滥用线程描述 API 来绕过端点保护产品。提出了一种新的注入技术&#xff1a;Thread Name-Calling&#xff0c;并给出了实施保护的相关建议。 介绍 进程注入是攻击者使用的重要技术之一 。…

【LeetCode 随笔】C++入门级,详细解答加注释,持续更新中。。。

文章目录 58.【简单】最后一个单词的长度&#x1f31f; &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&#xff01;&#x1f60a; &#x1f338;愿您在此停留的每一刻&#xff0c;都…

Golang高效合并(拼接)多个gzip压缩文件

有时我们可能会遇到需要把多个 gzip 文件合并成单个 gzip 文件的场景&#xff0c;最简单最容易的方式是把每个gzip文件都先解压&#xff0c;然后合并成一个文件后再次进行压缩&#xff0c;最终得到我们想要的结果&#xff0c;但这种先解压后压缩的方式显然效率不高&#xff0c;…

SPICE | 常见电路SPICE模型总结

Ref. 1. CMOS VLSI Design: A Circuits and Systems Perspective 目录 0 基础 1 反相器 inverter 2 缓存器 buffer 3 NAND 4 NOR 5 传输门 Transmission gate 6 三态反相器 Tristate Inverter 7 选择器 Multiplexers 8 D锁存器 D Latch 9 D触发器 D Flip-Flop 0 基础…

vue3 antdv3 检测Modal的尺寸是否改变,全屏的时候获取Modal的width与height,然后我们就可以动态设置表格高度了。

1、先上个图&#xff0c;我们要实现如下的效果&#xff0c;中间的表格部分要自动随Modal的改变而改变。官方&#xff1a;Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js 2、那我们一定要能够检测到Modal的宽高的改变才行&#xff0c;然后…

java学习--枚举

问题引入&#xff1a; 当需要解决一个季节类的问题&#xff0c;我们使用学到的类与对象&#xff0c;创建一个季节的类然后添加构造器在进行分装就可以实现&#xff0c;但问题也随之而来&#xff0c;这样不仅可以有正常的四季还可以添加其他不存在的四季以及可以更改四季的属性…

Javascript前端面试基础5【每日更10】

let与var的区别 let命令不存在变量提升&#xff0c;如果在let前使用&#xff0c;会导致报错&#xff08;var存在变量提升&#xff09;如果块区中存在let和const命令&#xff0c;就会形成封闭作用域不允许重复声明&#xff0c;因此&#xff0c;不能在函数内部重新声明参数 m…