Day 23 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 总结篇

修剪二叉搜索树

给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。

669.修剪二叉搜索树

669.修剪二叉搜索树1

​ 最直接的想法,遍历树然后找到root->val在[L,R]以外的节点删除,通过递归处理返回根节点;

​ 如果此时简单的给出这种代码:

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

​ 就会忽视掉当前节点不在范围内但是节点左(右)子树可能在范围内的情况;

​ 如下图所示:

​ 也就是在删除节点时,还要对其子树进行判断;至于实现方式可以参考上一题的子树嫁接方法,无须重构二叉树结构;

​ 下面写递归三部曲:

​ 首先确定递归函数参数和返回值:遍历整棵树,做修改,其实不需要返回值也可以完成修剪(其实就是从二叉树中移除节点)的操作;但是有返回值,更方便,可以通过递归函数的返回值来移除节点,不需要额外操作;

​ 其次确定终止条件:修剪的操作并不是在终止条件进行的,所以就是遇到空节点返回就可以了;

​ 最后确定单层递归的逻辑:嫁接子树,此处不再赘述;

​ 递归代码如下:

	TreeNode* traversal(TreeNode* root, int L, int R){
        if(root == NULL)	return NULL;
        if(root->val < L){//节点值小于左边边界值
            TreeNode* tempNode = traversal(root->right, L, R);//此节点右子树中寻找所有大于L的值的节点,继续嵌套递归修剪右子树;
            return tempNode;
        }
        if(root->val > R)	return	traversal(root->left, L, R);//同理,并非直接return子树,而是修剪过后再return
        root->left = traversal(root->left, L, R);//对符合区间条件的根节点左右子树进行操作
        root->right = traversal(root->right, L, R);
        return root;
    }

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

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

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

​ 按题目要求切割数组得到平衡二叉搜索树,则从数组中间作为根节点开始切割;

​ 同时注意循环不变量,因为这里是需要不断对数组进行切割直到子数组的长度为一;

​ 遍历代码如下:

	TreeNode* traversal(vector<int>& nums, int L, int R){//确定函数参数和返回值
        //这里选择左闭右开的切割区间,则子区间停止切割的终止条件即是数组长度等于零的时候
        if(L >= R)	return NULL;
        //单层递归逻辑
        int mid = (R-L)/2+L;//防止int溢出
        TreeNode* root = new TreeNode(nums[mid]);//确定根节点
        root->left = traversal(nums, L, mid);//左闭右开
        root->right = traversal(nums, mid+1, R);
        return root;
    }

把二叉搜索树转化为累加树

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

提醒一下,二叉搜索树满足下列约束条件:

节点的左子树仅包含键 小于 节点键的节点。 节点的右子树仅包含键 大于 节点键的节点。 左右子树也必须是二叉搜索树。

示例 1:

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

  • 输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
  • 输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]

示例 2:

  • 输入:root = [0,null,1]
  • 输出:[1,null,1]

示例 3:

  • 输入:root = [1,0,2]
  • 输出:[3,3,2]

示例 4:

  • 输入:root = [3,2,4,1]
  • 输出:[7,9,4,10]

提示:

  • 树中的节点数介于 0 和 104 之间。
  • 每个节点的值介于 -104 和 104 之间。
  • 树中的所有值互不相同
  • 给定的树为二叉搜索树。

​ 如果给定的是一个有序数组,则[1, 2, 3, 4]的结果就是[10, 9, 7, 4],那二叉树呢?

​ 从二叉搜索树的最大值开始往前递加,无疑就是处理顺序的改变,即右中左的顺序来遍历整个二叉搜索树,即反中序遍历;

​ 则递归代码如下:

	int sum = 0;//记录前一个节点的数值
	void traversal(TreeNode* cur){//确定函数参数和返回值:遍历整棵树且无须对返回值进行处理
        if(!cur)	return;//确定终止条件:为空返回
        //if(cur->right)	sum += cur->right->val;	单层逻辑
        traversal(cur->right);
        cur->val += sum;
        sum = cur->val;//更新sum
        //if(cur->left)	sum += cur->left->val;
        traversal(cur->left);
    }

​ 整体代码如下:

/**
 * 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 {
private:
    int sum = 0;//记录前一个节点的数值
	void traversal(TreeNode* cur){//确定函数参数和返回值:遍历整棵树且无须对返回值进行处理
        if(!cur)	return;//确定终止条件:为空返回
        //if(cur->right)	sum += cur->right->val;	单层逻辑
        traversal(cur->right);
        cur->val += sum;
        sum = cur->val;//更新sum
        //if(cur->left)	sum += cur->left->val;
        traversal(cur->left);
    }
public:
    TreeNode* convertBST(TreeNode* root) {
        sum = 0;
        traversal(root);
        return root;
    }
};

总结

​ 递归和迭代的思想都要熟悉;

递归

​ 首先是熟知递归函数的参数和返回值:

​ 如何利用才能使算法的性能最优化,例如对返回节点类型、传入int替代vector;

​ (见Day 18)

​ 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值;(这种情况就是本文下半部分介绍的113.路径总和ii)

​ 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值; (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)

​ 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回;

​ 其次是关于递归函数的终止条件:

​ 有时候终止条件并不是简单的对处理节点判空即可,需要根据具体情境进行判断;

​ 最后是递归函数的单层遍历逻辑:

​ 二叉树题目的逻辑往往不算很难,大多时候可以理解为对一个遍历顺序特殊的数组进行处理,所以遍历顺序尤为重要;

​ 在构建二叉树的节点的时候,一定是选择从根节点开始(中左右),即前序遍历;

​ 在面对二叉搜索树时,一定是选择中序遍历(左中右),这样才能充分利用二叉搜索树的有序性质;

​ 求普通二叉树的属性的时候,一般采取后序遍历(左右中),因为需要返回中节点进行处理;

迭代

​ 迭代最主要的思想就是用栈来模拟树的逻辑,通过不断的push pop得到理想中的出栈顺序;

​ 一般在涉及到递归不是很好处理返回值的时候使用迭代,层序遍历就是一个典型的例子。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【CSS】SVG图片属性及修改颜色

最近的开发中遇到了SVG不能修改颜色的问题&#xff0c;以前是直接用&#xff0c;没有研究过&#xff0c;现在搞个笔记记录下 SVG的属性&#xff1a; width:设置最终SVG图片的宽度height:设置最终SVG图片的高度viewbox&#xff1a;视区&#xff0c;在svg上截取一块&#xff0c…

【C++学习】C++智能指针:提高代码安全与性能的利器

文章标题 智能指针的提出智能指针概念及使用RAII 智能指针的原理C库多种智能指针详解版本一&#xff1a;std::auto_ptr&#xff08;C98&#xff09;1. std::auto_ptr 使用2. std::auto_ptr 原理3. std::auto_ptr 模拟实现 版本二&#xff1a;unique_ptr (C11)1. unique_ptr 的使…

Unity之PUN实现多人联机射击游戏的优化(Section 3)

目录 &#x1f4a3;一、准备工作 &#x1f4a3;二、生成弹头脚本的编写 &#x1f4a3;三、实现发射和伤害同步 手雷都加了在给狗剩加个火箭筒不过分吧。效果看GIF动图&#xff0c;分别是单机和联机的效果。 添加火箭筒依旧是在原有的基础上更改&#xff0c;我查看火箭筒模型…

基于STC12C5A60S2系列1T 8051单片机的LCD1602显示中文英文数字小数字库字符自定义字符的应用

基于STC12C5A60S2系列1T 8051单片机的LCD1602显示中文英文数字小数字库字符自定义字符的应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍LCD1602字符型液晶显示器介…

策略模式:灵活调整算法的设计精髓

在软件开发中&#xff0c;策略模式是一种行为型设计模式&#xff0c;它允许在运行时选择算法的行为。通过定义一系列算法&#xff0c;并将每个算法封装起来&#xff0c;策略模式使得算法可以互换使用&#xff0c;这使得算法可以独立于使用它们的客户。本文将详细介绍策略模式的…

算法——栈

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享关于栈相关的算法 如果有不足的或者错误的请您指出! 目录 1.删除字符中的所有相邻重复项1.1解析1.2题解 2.比较含退格的字符串2.1解析2.2题解 3.基本计算器II3.1解析3.2题解 4.…

清明美食制作|“心灵护航,增能培力”残疾人职业能力提升培养

为提高残疾人的动手能力&#xff0c;提升个人的自身素质和自主就业创业能力&#xff0c;弘扬中华民族传统文化&#xff0c;临近清明之际&#xff0c;淳安县从益舍社会工作服务中心于浪川乡展开了以“品尝春天味道 制作清明粿 清明美食制作”为主题的清明节活动。 【清明粿制作】…

【C语言__函数__复习篇1】

目录 前言&#xff1a; 一、C语言中函数的概念 二、库函数 2.1 库函数的概念 2.2 怎样自学库函数——以sqrt函数为例 三、自定义函数 3.1 自定义函数的概念 3.2 自定义函数的语法形式 3.3 函数的实参 3.4 函数的形参 3.5 实参与形参的关系 3.6 return语句 3.7 数组传参 …

O2OA开发平台如何查看数据表结构?

在访问后端api地址&#xff0c;页面最下方有列示平台的各个服务&#xff0c;点击进入可查看具体的表内容 后端api地址&#xff1a; http://{hostIP}/x_program_center/jest/list.html 其中&#xff1a;{hostIP}为中心服务器所在域名或者IP地址 如下图&#xff1a;

RA4000CE为汽车动力传动系统提供解决方案

目前汽车电气化的水平越来越高&#xff0c;其中比较显著的一个发展方向就是将发动机管理系统和自动变速器控制系统&#xff0c;集成为动力传动系统的综合控制(PCM)。作为汽车动力的核心部件&#xff0c;通过电子系统的运用&#xff0c;将外部多个传感器和执行环节的数据进行统一…

Go 自定义14位时间类型 yyyyMMddHHmmss

目录 功能 代码 功能 数据库或者接口时间类型&#xff0c;经常会使用14位的时间格式。每次都转换有点麻烦。可以自定义一个时间类型。 自定义类型需要实现json接口中的MarshalJSON与UnmarshalJSON两个函数&#xff0c;这样在做json编码解码时就会自动转为14位的时间格式了。…

基于flutter3.x+window_manager+getx桌面端仿macOS系统

flutter3_macui桌面端仿macOS系统实战项目完结啦&#xff01; 原创研发flutter3.19dart3.3window_managergetx等技术构建桌面版macOS系统。支持自定义毛玻璃虚化背景、Dock菜单多级嵌套自由拖拽排序、可拖拽弹窗等功能。 支持macOS和windows11两种风格。 使用技术 编辑器&…

【c++】优先级队列|反向迭代器(vector|list)

优先级队列的常用函数的使用 #include<iostream> #include<queue> using namespace std;int main() {priority_queue<int>st;st.push(1);st.push(7);st.push(5);st.push(2);st.push(3);st.push(9);while (!st.empty()){cout << st.top() << &qu…

【vue】watch 侦听器

watch&#xff1a;可监听值的变化&#xff0c;旧值和新值 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…

openstack之neutron介绍

核心组件 neutron-server&#xff1a;提供API接口&#xff0c;把对应的api请求传给plugin进&#xff1b; neutron-plugin&#xff1a;管理逻辑网络状态&#xff0c;调用agent&#xff1b; neutron-agent&#xff1a;在provider network上创建网络对象&#xff1b; neutron-…

【Vue】实现仿微信输入@出现选择框

<div style"padding: 10px 10px" class"editor"><el-inputresizetype"textarea":rows"4"clearableplaceholder"请输入您的问题.."v-model"requestParams.prompt"input"handleInput"keydown.na…

C# WinForm —— 项目目录结构

1. WinForm 应用程序项目 Properties&#xff1a;属性文件夹存放了一个自动生成的类文件AssemblyInfo.cs&#xff0c;保存了一些应用程序集的一些信息引用存放了一些为应用程序提供所需的&#xff0c;某些功能的一些程序集&#xff08;dll文件&#xff09;等添加引用&#xff…

Html网页小游戏源代码

Html网页小游戏源代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Jello Jumping Game</title><meta name"viewport" content"widthdevice-width, initial-scale1"&…

【安全】挖矿木马自助清理手册

一、什么是挖矿木马 挖矿木马会占用CPU进行超频运算&#xff0c;从而占用主机大量的CPU资源&#xff0c;严重影响服务器上的其他应用的正常运行。黑客为了得到更多的算力资源&#xff0c;一般都会对全网进行无差别扫描&#xff0c;同时利用SSH爆破和漏洞利用等手段攻击主机。 …

【AR】使用深度API实现虚实遮挡

遮挡效果 本段描述摘自 https://developers.google.cn/ar/develop/depth 遮挡是深度API的应用之一。 遮挡&#xff08;即准确渲染虚拟物体在现实物体后面&#xff09;对于沉浸式 AR 体验至关重要。 参考下图&#xff0c;假设场景中有一个Andy&#xff0c;用户可能需要放置在包含…