代码随想录二刷 day23 | 二叉树 之 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树

news2024/12/23 20:40:23

二刷day23

      • 669. 修剪二叉搜索树
      • 108.将有序数组转换为二叉搜索树
      • 538.把二叉搜索树转换为累加树

669. 修剪二叉搜索树

题目链接
解题思路:
递归三部曲

  1. 确定递归函数的参数以及返回值

这里我们为什么需要返回值呢?

因为是要遍历整棵树,做修改,其实不需要返回值也可以,我们也可以完成修剪(其实就是从二叉树中移除节点)的操作。

但是有返回值,更方便,可以通过递归函数的返回值来移除节点。

代码如下:

TreeNode* trimBST(TreeNode* root, int low, int high)
  1. 确定终止条件

修剪的操作并不是在终止条件上进行的,所以就是遇到空节点返回就可以了。

if (root == nullptr ) return nullptr;
  1. 确定单层递归的逻辑

如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。

代码如下:

if (root->val < low) {
    TreeNode* right = trimBST(root->right, low, high); // 寻找符合区间[low, high]的节点
    return right;
}

如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。

代码如下:

if (root->val > high) {
    TreeNode* left = trimBST(root->left, low, high); // 寻找符合区间[low, high]的节点
    return left;
}

接下来要将下一层处理完左子树的结果赋给root->left,处理完右子树的结果赋给root->right。

最后返回root节点,代码如下:

root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子
root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子
return root;

此时大家是不是还没发现这多余的节点究竟是如何从二叉树中移除的呢?

在回顾一下上面的代码,针对下图中二叉树的情况:
在这里插入图片描述如下代码相当于把节点0的右孩子(节点2)返回给上一层,

if (root->val < low) {
    TreeNode* right = trimBST(root->right, low, high); // 寻找符合区间[low, high]的节点
    return right;
}

然后如下代码相当于用节点3的左孩子 把下一层返回的 节点0的右孩子(节点2) 接住。

root->left = trimBST(root->left, low, high);

此时节点3的左孩子就变成了节点2,将节点0从二叉树中移除了。

代码如下:

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == nullptr ) return nullptr;
        if (root->val < low) {
            TreeNode* right = trimBST(root->right, low, high); // 寻找符合区间[low, high]的节点
            return right;
        }
        if (root->val > high) {
            TreeNode* left = trimBST(root->left, low, high); // 寻找符合区间[low, high]的节点
            return left;
        }
        root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子
        root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子
        return root;
    }
};


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

题目链接
解题思路: 本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间
递归三部曲:

  1. 确定递归函数返回值及其参数

那么本题要构造二叉树,依然用递归函数的返回值来构造中节点的左右孩子。
再来看参数,首先是传入数组,然后就是左下标left和右下标right,我们在二叉树:构造二叉树登场!中提过,在构造二叉树的时候尽量不要重新定义左右区间数组,而是用下标来操作原数组。

所以代码如下:

// 左闭右闭区间[left, right]
TreeNode* traversal(vector<int>& nums, int left, int right)

这里注意,我这里定义的是左闭右闭区间,在不断分割的过程中,也会坚持左闭右闭的区间,这又涉及到我们讲过的循环不变量。

  1. 确定递归终止条件

这里定义的是左闭右闭的区间,所以当区间 left > right的时候,就是空节点了。

代码如下:

if (left > right) return nullptr;
  1. 确定单层递归的逻辑

首先取数组中间元素的位置,不难写出int mid = (left + right) / 2;,这么写其实有一个问题,就是数值越界,例如left和right都是最大int,这么操作就越界了,在二分法中尤其需要注意!

所以可以这么写:int mid = left + ((right - left) / 2);

但本题leetcode的测试数据并不会越界,所以怎么写都可以。但需要有这个意识!

取了中间位置,就开始以中间位置的元素构造节点,代码:TreeNode* root = new TreeNode(nums[mid]);。

接着划分区间,root的左孩子接住下一层左区间的构造节点,右孩子接住下一层右区间构造的节点。

最后返回root节点,单层递归整体代码如下:

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;

这里int mid = left + ((right - left) / 2);的写法相当于是如果数组长度为偶数,中间位置有两个元素,取靠左边的。

整体代码如下:

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

注意:在调用traversal的时候传入的left和right为什么是0和nums.size() - 1,因为定义的区间为左闭右闭。

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

题目链接
解题思路: 其实这就是一棵树,大家可能看起来有点别扭,换一个角度来看,这就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],是不是感觉这就简单了。 从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了。

  1. 递归函数参数以及返回值

这里很明确了,不需要递归函数的返回值做什么操作了,要遍历整棵树。

同时需要定义一个全局变量pre,用来保存cur节点的前一个节点的数值,定义为int型就可以了。

代码如下:

int pre = 0; // 记录前一个节点的数值
void traversal(TreeNode* cur)
  1. 确定终止条件

遇空就终止。

if (cur == NULL) return;
  1. 确定单层递归的逻辑

注意要右中左来遍历二叉树, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值。

代码如下:

traversal(cur->right);  // 右
cur->val += pre;        // 中
pre = cur->val;
traversal(cur->left);   // 左

整体代码如下:

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

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

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

相关文章

SOLIDWORKS Electrical如何绘制电线

SOLIDWORKS Electrical 是一套计算机辅助工程 (CAE) 设计工具&#xff0c;他可以帮助电气设计工程师减少创新的内在风险&#xff0c;并允许公司减少对物理原型的需求&#xff0c;从而在更短时间内以更低成本将产品推向市场。通过一组强大、直观的电气设计功能&#xff0c;设计人…

互联网大佬们的成功绝非偶然

以下排名不分先后。 一、百度李彦宏 &#xff0c;1987年阳泉市高考状元&#xff0c;考进北大。 互联网三巨头BAT的第一个字母&#xff0c;指的就是百度。创始人李彦宏是出生在普通家庭出生&#xff0c;他小时候的启蒙教育由三个姐姐负责&#xff0c;不过相比学习&#xff0c;更…

详解国产指纹芯片的工作原理以及应用领域

指纹芯片&#xff0c;是指内嵌指纹识别技术的芯片产品&#xff0c;能够片上实现指纹的图像采集、特征提取、特征比对的芯片&#xff0c;开发者可以方便的实现指纹识别的功能&#xff0c;大大降低了指纹识别行业的门槛&#xff0c;对指纹识别的推广具有十分积极的推动作用。 近几…

数据合规之监管关注要点暨风险防范建议

上市申报过程中证券监督部门最关注的三类问题为数据源合规、数据安全及数据使用合规&#xff0c;而这三类问题也是企业运营时最容易产生的问题&#xff0c;它们无疑应是拟上市企业数据合规治理的重中之重&#xff1a; 1、数据源合规之监管关注要点 1、数据信息 就获取的个人数…

RaaS(勒索软件即服务)是什么?这个模型是如何工作的?

Ransomware as a Service是一个英语术语,指的是一种商业模型&#xff0c;其中勒索软件开发者向感兴趣的恶意行为者提供工具&#xff0c;以便他们可以发起勒索软件攻击。使用者通过签约创建恶意软件即服务或加入联盟计划&#xff0c;并分发一系列勒索软件以换取一定比例的利润。…

字符串--字符串处理函数、向函数传递字符串

一、字符串处理函数 字符串处理函数库提供了很多有用的函数用于字符串处理操作&#xff08;如复制字符串和拼接字符串等&#xff09;以及确定字符串的长度。若要使用这些字符串处理函数&#xff0c;必须在程序的开头将头文件<string.h>包含到源头文件。 例题1&#xff1a…

什么是Vue的前端微服务架构(Micro Frontends)?

什么是Vue的前端微服务架构&#xff08;Micro Frontends&#xff09;&#xff1f; 前端微服务架构&#xff08;Micro Frontends&#xff09;是一种新型的前端架构风格&#xff0c;它借鉴了后端微服务架构的思想&#xff0c;将前端应用程序拆分为多个小型、独立的部分&#xff…

系统学习Spring,阿里最新产Spring全家桶进阶笔记真的很全

Spring是我们Java程序员面试和工作都绕不开的重难点。很多粉丝就经常跟我反馈说由Spring衍生出来的一系列框架太多了&#xff0c;根本不知道从何下手&#xff1b;大家学习过程中大都不成体系&#xff0c;但面试的时候都上升到源码级别了&#xff0c;你不光要清楚了解Spring源码…

混沌演练状态下,如何降低应用的MTTR(平均恢复时间) | 京东云技术团队

在企业业务领域&#xff0c;锦礼是针对福利、营销、激励等员工采购场景的一站式解决方案&#xff0c;包含面向员工、会员等弹性激励SAAS平台。由于其直接面向公司全体员工&#xff0c;其服务的高可用尤其重要&#xff0c;本文将介绍锦礼商城大促前夕&#xff0c;通过混沌工程实…

vue3 项目部署,Nginx配置https,重定向,详细流程

文章目录 前情提要应用场景安装使用 实战解析最后 前情提要 一个web项目完成后&#xff0c;我们需要打包部署上线&#xff0c;关于打包的实战在我的vite专栏里已经有过一些实践&#xff0c;今天我们来实践一些部署的过程&#xff0c;当然部署也可以由后端来完成&#xff1b; 应…

去面腾讯了(社招两年面试经验)

之前很多同学嚷嚷有没有社招经验&#xff0c;正好&#xff0c;我有个朋友去腾讯社招面试了。 他的面的是全栈开发岗位&#xff0c;工作两年&#xff0c;后端是Go&#xff0c;前端是 JavaScript Vue。 因为工作也没多久&#xff0c;就两年时间&#xff0c;所以大概率可能还是…

Linux:用户和用户组

Linux系统中可以&#xff1a; 配置多个用户配置多个用户组用户可以加入多个用户组 Linux系统关于权限的管控级别有两个&#xff0c;即&#xff1a; 针对用户的权限控制针对用户组的权限控制 1、用户组管理 创建用户组&#xff0c;语法&#xff1a; groupadd 用户组名 删除用户组…

NLP——Summarization

文章目录 Extractive summarisationSingle-documentcontent selectionTFIDF MethodLog Likelihood Ratio Method对数似然比Sentence Centrality Method 句子中心法 RST Parsing Multi-documentContent selectionMaximum Marginal Relevance 最大边际相关性Information Ordering…

详细介绍ROS中通过shell文件依次启动多个launch文件

本文主要介绍如何在ROS中通过shell文件依次启动多个launch文件&#xff0c;并介绍如何在同一个窗口的不同选项卡中依次启动多个launch文件。 一、先来看一个简单的示例&#xff1a; #!/bin/bashgnome-terminal -- bash -c "roslaunch bringup racecar_gazebo_rviz_znc.la…

Word控件Spire.Doc 【其他】教程(9):从 Word 文档中提取 OLE 对象

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

NestJs 管道(Pipe)

&#x1f384;Hi~ 大家好&#xff0c;我是小鑫同学&#xff0c;资深 IT 从业者&#xff0c;InfoQ 的签约作者&#xff0c;擅长前端开发并在这一领域有多年的经验&#xff0c;致力于分享我在技术方面的见解和心得 &#x1f680;技术&代码分享 我在 94Code 总结技术学习&…

Windows下安装运行Kafka(最底下有遇到的坑与解决方法)

注&#xff1a;安装kafka需要提前安装Zookeeper 一、Zookeeper安装 1. 下载安装包 https://zookeeper.apache.org/releases.html 注意&#xff1a;要下载带bin的安装包 2. 解压并进入ZooKeeper目录&#xff0c;如&#xff1a;D:\onworking\apache-zookeeper-3.7.0-bin&…

ansible剧本模式特殊模块使用

Nginx安装剧本 ansible-playbook test1.yaml //补充参数 -k&#xff08;-ask-pass&#xff09;&#xff1a;用来交互输入ssh密码 -K&#xff08;-ask-become-pass&#xff09;&#xff1a;用来交互输入sudo密码 -u&#xff1a;指定用户 -e:命令行指定变量 --syntax-check…

【服务器数据恢复】HP LeftHand存储raid5不可用的数据恢复案例

HP LeftHand存储简介&#xff1a; HP LeftHand存储支持搭建RAID5、RAID6、RAID10磁盘阵列&#xff0c;支持卷快照&#xff0c;卷动态扩容等。服务端和客户端分别如下&#xff1a; LeftHand存储共有三个级别&#xff1a;物理磁盘、基于多个物理磁盘组成的逻辑磁盘&#xff08;ra…

广东电信突发故障,手机没信号,对讲机的重要性再次凸显

当我们常用的通信网络出现故障时&#xff0c;就会面临全网瘫痪的情况&#xff0c;这个时候无线电通信就显得尤为重要了&#xff01; 在6月8日下午两点左右&#xff0c;有多位广东电信的用户发现&#xff0c;自己的手机突然出现了打不出去电话&#xff0c;及上不了网的情况&…