代码随想录算法训练营第二十一天| 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树

目录

  • 一、LeetCode 669. 修剪二叉搜索树
    • 思路:
    • C++代码
  • 二、LeetCode 108.将有序数组转换为二叉搜索树
    • 思路
    • C++代码
  • 三、LeetCode 538.把二叉搜索树转换为累加树
    • 思路
      • 反中序遍历
      • 变量传参递归(野路子)
  • 总结


一、LeetCode 669. 修剪二叉搜索树

题目链接:LeetCode 669. 修剪二叉搜索树述

文章讲解:代码随想录
视频讲解:你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树

思路:

 题目确定了一个区间[low, high],要求调整二叉搜索树使得所有节点值都在这个范围内;我们首先可以观察一下二叉搜索树的结构,为左子树所有结点小于当前结点,右子树所有结点大于当前结点。因此在遍历到一个结点值在区间之外时(若小于),该结点和该结点的左子树所有结点都不符合条件,可以直接删除,而右子树包含大于该结点的值,有可能含有在区间内的结点,因此进入右子树继续遍历。
在这里插入图片描述
 对于递归函数的设计,仍然按照递归三部曲进行设计;

确定函数传参与返回值:可以直接采用题目给出的函数模板作为递归函数的传参与返回值

TreeNode* trimBST(TreeNode* root, int low, int high)

确定递归边界条件:由于返回值格式为TreeNode*,因此在遍历到空节点时返回空指针NULL.

if(!root) return NULL;

确定递归函数逻辑:按照我们上面分析的内容设计算法,当前结点值满足条件时,左右孩子分别是下一层递归的返回值;若当前结点值小于区间左边界,那么本结点与本结点的左子树全部舍弃,将右孩子传入下一层递归,并将递归的返回值设置为新的结点;节点值大于区间右边界的处理类似。

if(root->val >= low && root->val <= high){root->left = trimBST(root->left, low, high);root->right = trimBST(root->right, low, high);}else{if(root->val < low){root = trimBST(root->right, low, high);}else if(root->val > high){root = trimBST(root->left, low, high);}}

C++代码

完整代码如下:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* trimBST(TreeNode* root, int low, int high) {if(!root) return NULL;if(root->val >= low && root->val <= high){root->left = trimBST(root->left, low, high);root->right = trimBST(root->right, low, high);}else{if(root->val < low){root = trimBST(root->right, low, high);}else if(root->val > high){root = trimBST(root->left, low, high);}}return root;}
};

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

题目链接:LeetCode 108.将有序数组转换为二叉搜索树

文章讲解:代码随想录
视频讲解:构造平衡二叉搜索树!| LeetCode:108.将有序数组转换为二叉搜索树

思路

 题目要求将升序数组转化为平衡二叉搜索树,即树中任意结点的左右子树深度差不大于2;我们可以使用与之前类似的分割数组分别传入下一层的方法,进行递归设计。

 要求构建平衡二叉树,我们可以每次都将数组以中位数为分界点,平分成左右两部分,此时两部分基本长度相同,长度差不超过1,意味着结点的左右子树深度差不超过1,达到了题目要求的平衡要求。

C++代码

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* sortedArrayToBST(vector<int>& nums) {if(nums.empty()) return NULL;auto median = nums.begin() + (nums.end()-nums.begin())/2;TreeNode* root = new TreeNode(*median);if(nums.size() != 1){vector<int> nums_left(nums.begin(), median);vector<int> nums_right(median + 1, nums.end());root->left = sortedArrayToBST(nums_left);root->right = sortedArrayToBST(nums_right);}return root;}
};

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

题目链接:LeetCode 538.把二叉搜索树转换为累加树

文章讲解:代码随想录
视频讲解:普大喜奔!二叉树章节已全部更完啦!| LeetCode:538.把二叉搜索树转换为累加树

思路

反中序遍历

 将二叉搜索树转化为累加树,即把二叉树中所有大于等于该结点值的和,设定为当前结点的新值,那么就需要找二叉树中大于等于当前结点的值,而二叉树的中序遍历的逆序恰好符合从大到小的顺序,因此设置一个反中序递归的函数进行累加赋值即可。
在这里插入图片描述
 设置一个全局变量,记录前一个结点的值,加上本节点的值进行赋值,从而实现累加;可写出如下代码:

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;}
};

变量传参递归(野路子)

 由于笔者初次看到本题时,理解题目有一些偏差,在算法设计上有些过于复杂了,但简化后的代码底层思想与反中序遍历还是相似的。

 笔者首先设置了一个整数参数parVal加入递归传参,类似于反中序遍历中的前一个结点值,记录了比自己结点大的所有结点值之和。笔者对于本题的结点处理,只有当当前结点为左叶子结点时,才加上parVal(否则这一条分支上会重复加上parVal,其余情况都加上自己的孩子结点的返回值;对于结点处理,分出了两个方面的八种情况,即:

  1. 该结点是它的双亲的左/右孩子(2种)
  2. 该结点的孩子结点情况:有两个孩子、只有左孩子、只有右孩子、无孩子结点

 在列出八中情况的结点处理和递归返回值后,经过归纳简化可化简出如下结果:**如果该结点有右孩子,则它的新值是他原本的值加上自己右孩子的下一层递归返回值(相当于返回前一个结点值),否则需要加上parVal(见上面的结点处理规定);如果结点有左孩子,那么递归的返回值是当前结点的左孩子的下一层递归返回值(左子树只返回最左下方的最大值),否则返回当前结点值。**按照这样的规律调整出的代码如下:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int convertBST(TreeNode* root, int parVal){if(!root) return 0;          if(root->right){root->val += convertBST(root->right, parVal); //此时函数返回相当于前一个结点值}else{root->val += parVal;}if(root->left) return convertBST(root->left, root->val);else return root->val;}TreeNode* convertBST(TreeNode* root) {int val = convertBST(root, 0);return root;}
};

 这样的代码让笔者写出来也比较困惑,很奇怪的方法却能正常运行,笔者对于自己这个代码是看做一个反中序遍历的变形版本,使用函数传参和递归返回比较复杂地实现前一个结点值的记录。有大佬看到的话希望在评论区讨论一下。


总结

 二叉树部分一刷结束,通过算法训练营强力巩固了一下数据结构缺少的实操课,熟悉了二叉树的各种基本操作,并且着重练习了递归的设计。


文章图片来源:代码随想录 (https://programmercarl.com/)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

javaweb学习之HTML(一)

推荐学习使用网站 w3school 在线教程 认识HTML HTML&#xff08;HyperText Markup Language&#xff09;是超文本标记语言&#xff0c;它是一个用于创建网页和网页应用程序的标准标记语言。HTML文档由一系列的元素&#xff08;elements&#xff09;组成&#xff0c;这些元素通…

Unity 麦扣 x 勇士传说 全解析 之 怪物基类与野猪(附各模块知识的链接,零基础也包学会的牢弟)(案例难度:★★☆☆☆)

通过一阵子的学习&#xff0c;我是这么认为的&#xff0c;因为该教程是难度两星的教程 &#xff0c;也就是适合学了一阵子基础组件以后的学习者 &#xff08;什么都不会的学习者要是学这套课程会困难重重&#xff0c;如果你什么都不会那么需要学习一星教程&#xff09; 所以该…

SQL-事务与并发问题

在数据库管理系统中&#xff0c;事务是一个重要的概念&#xff0c;它确保了一组数据库操作要么全部成功&#xff0c;要么全部失败&#xff0c;从而维护数据的完整性和一致性。随着多个用户同时访问数据库&#xff0c;事务的并发处理变得尤为重要。 1. 事务的定义 事务是指一组…

AI 代理参考架构

LLM Agent部署框架 围绕 ChatGPT 的讨论&#xff0c;现在已经演变为AI 代理。 图&#xff1a;AI代理平台参考架构 比尔盖茨最近设想&#xff08;CNBC 采访&#xff1a;链接&#xff09;未来我们将拥有一个能够处理和响应自然语言并完成许多不同任务的AI 代理。盖茨以计划旅行…

ETAS工具链自动化实战指南<一>

----自动化不仅是一种技术&#xff0c;更是一种思维方式&#xff0c;它将帮助我们在快节奏的工作环境中保持领先&#xff01; 目录 往期推荐 场景一&#xff1a;SWC 之间 port自动连接 命令示例 参数说明 场景二&#xff1a;SWC与ECU 自动映射 命令示例 参数说明 场景三&…

c#实现数据导出为PDF的方式

PdfSharp vs iTextSharp: C#中PDF导出功能比较 PdfSharp 优点 轻量级&#xff1a;适合简单的PDF生成任务易于学习&#xff1a;API相对简单&#xff0c;学习曲线较缓开源&#xff1a;提供开源版本&#xff0c;可自由使用和修改纯C#实现&#xff1a;不依赖外部库或COM组件支持…

对零基础想转行网络安全同学的一点建议

最近有同学在后台留言&#xff0c;0基础怎么学网络安全&#xff1f;0基础可以转行做网络安全吗&#xff1f;以前也碰到过类似的问题&#xff0c;想了想&#xff0c;今天简单写一下。 我的回答是先了解&#xff0c;再入行。 具体怎么做呢&#xff1f; 首先&#xff0c;你要确…

1.初识redis

文章目录 1.认识redis1.1 mysql和redis 对比1.2分布式系统1.2.1单机架构与分布式架构1.2.2数据库分离(应用服务器和存储服务器分离)与负载均衡1.2.3负载均衡器1.2.4 数据库读写分离1.2.5 数据库服务器引入缓存1.2.6数据库分库分表1.2.7 引入微服务 2.常见概念解释2.1 应用(Appl…

音频导出后为什么效果变差了 FL Studio音频导出设置推荐

FL Studio是一款功能强大的编曲软件&#xff0c;除了可以编曲之外&#xff0c;FL Studio还支持各种音频格式导出。有的小伙伴在使用FL Studio导出音频后&#xff0c;会发现的导出的音频效果不理想&#xff0c;这很大的原因可能是导出设置不对造成的。下面给大家详细讲解&#x…

全面解析Gerapy分布式部署:从环境搭建到定时任务,避开Crawlab的坑

Gerapy分布式部署 搭建远程服务器的环境 装好带docker服务的系统 Docker:容器可生成镜像&#xff0c;也可拉去镜像生成容器 示例&#xff1a;将一个环境打包上传到云端(远程服务器)&#xff0c;其他8个服务器需要这个环境直接向云端拉取镜像生成容器,进而使用该环境,比如有MYS…

代码块分类

局部代码块 public class Test {public static void main(String[] args) {{int a 10;}// 执行到此处时候,变量a已经从内存中消失了。 // System.out.println(a);} } 构造代码块 public class Test {private String name;private int age;{// 构造代码块System.out.…

GEC6818开发板的学习

1、开发板的简介 首先连接 开发板与电脑,需电脑安装串口驱动:例CH340 2、开发板的特性: 像素:800*480Pix分辨率:高,宽两个维度的像素点数目开发板色深为32位一个像素点占4个字节:分别为灰度保留位、RGB三原色各占一位3、为什么要内存映射 虽然LCD设备本质上也可以看作…

R语言:如何安装包“linkET”

自己在R语言中安装包“linkET”时报错不存在叫‘linket’这个名字的程辑包 尝试了install.packages("linkET")和BiocManager::install("linkET")两种安装办法都不行 >install.packages("linkET") WARNING: Rtools is required to build R pa…

【Java】对象与toString()方法

1.前言 了解toString之前&#xff0c;要先明白Object类是什么&#xff0c;Object是所有对象的父类。在Object类当中含有toString()方法&#xff0c;因此所有的对象也都包含有一个toString()方法。 2.toString 2.1 方法调用 toString()方法主要的作用&#xff0c;是对类与对象的…

错误信息“缺少msvcr120.dll”或“找不到msvcr120.dll”应该如何修复?几种方法快速修复

由于这个msvcr120.dll文件与应用程序的运行密切相关&#xff0c;任何与之相关的问题都可能导致应用程序无法正常运行。错误信息如“缺少msvcr120.dll”或“找不到msvcr120.dll”&#xff0c;通常出现在软件安装不正确或系统更新后。接下俩就教大家几种方法快速修复msvcr120.dll…

CentOS 7 安装流程详细教程

目录 前言1. CentOS 7 概述2. 安装环境准备2.1 硬件要求2.2 安装介质准备 3. CentOS 7 安装步骤3.1 引导安装程序3.2 选择语言和键盘布局3.3 配置安装源和软件包3.4 配置分区3.5 设置网络和主机名3.6 设置时间和日期3.7 设置 root 密码和创建用户3.8 开始安装并完成配置 4. 安装…

Cocos Creator2D游戏开发(14)---CocosCreator常用组件详解

Canvas RenderRoot2D 组件所在的节点是 2D 渲染组件数据收集的入口,而 Canvas&#xff08;画布&#xff09; 组件继承自 RenderRoot2D 组件&#xff0c;所以 Canvas 组件也是数据收集入口。所有 2D 渲染元素都必须作为 RenderRoot2D 的子节点才能被渲染。 Canvas还作为屏幕适配…

用基础项目来理解spring的作用

简介 spring官方的解释过于专业化&#xff0c;初学者可能比较难懂&#xff0c;接下来我将通过一个最基础的Java项目来尽可能的展示spring中的作用及spring的底层是如何来实现的。 项目结构 该项目是一个简单的JavaSE项目&#xff0c;没有maven或者tomcat等其他。只在控制台进…

《黑神话悟空》2024官方配置要求一览

黑神话悟空配置要求 1080P 高画质推荐6650xt和4060以上的显卡高画质 全景光追推荐4060 2k 高画质推荐4060ti/7700x以上的显卡 高画质全景光追推荐4070 4K 高画质推荐4070s起步 高画质全景光追推存4080S 一、官方配置要求一览 1、最低配置: 需要 64 位处理器和操作系…

什么是逃逸分析

如何快速判断是否逃逸就看方法内new的对象实体是否能够被外部方法进行调用 什么是逃逸分析 在java虚拟机中&#xff0c;对象是在java堆中分配内存的&#xff0c;这是一个普遍的常识。但是&#xff0c;有一种特殊情况&#xff0c;那就是如果经过逃逸分析&#xff08;escape an…