代码随想录刷题笔记 DAY 23 | 修剪二叉搜索树 No.669 | 将有序数组转换为二叉搜索树 No.108 | 把二叉搜索树转换为累加树 No.538

文章目录

    • Day 23
      • 01. 修剪二叉搜索树(No. 669)
        • 1.1 题目
        • 1.2 笔记
        • 1.3 代码
      • 02. 将有序数组转换为二叉搜索树(No. 108)
        • 2.1 题目
        • 2.2 笔记
        • 2.3 代码
      • 03. 把二叉搜索树转换为累加树(No. 538)
        • 3.1 题目
        • 3.2 笔记
        • 3.3 代码

Day 23

01. 修剪二叉搜索树(No. 669)

题目链接

代码随想录题解

1.1 题目

给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案

所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:root = [1,0,2], low = 1, high = 2
输出:[1,null,2]

示例 2:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3
输出:[3,2,null,1]

提示:

  • 树中节点数在范围 [1, 104]
  • 0 <= Node.val <= 104
  • 树中每个节点的值都是 唯一
  • 题目数据保证输入是一棵有效的二叉搜索树
  • 0 <= low <= high <= 104
1.2 笔记

在解这道题之前,先来看一段代码

public TreeNode traversal(root) {if (root == null) {return null;}root.left = traversal(root.left);root.right = traversal(root.right);return root;
}

这段代码实现了什么呢?

根据递归来分析

  • 递归的出口:root == null
  • 递归的返回值,以及其用途:返回的是当前节点经过处理后的值,将其作为上个节点的左子树或者右子树
  • 对每个节点的操作:分别向左递归,返回左子树,向右递归,返回右子树。

最终可以分析得出,上面的代码就是没有做任何的操作,只是将左子树赋给左子树将右子树赋值给右子树。

❓ 很多朋友看到这里可能怀疑我脑子坏掉了,为什么要举这么无意义的例子呢?

💡 其实换个思路去想,将左子树赋值给左子树,相当于没做任何操作,那如果在递归中进行一些操作,使得这个返回值不是左子树,而是左子树的下的节点,那不就完成了节点的删除吗?

那这道题的思路就清晰了一些,对于不处于规定范围内的节点在递归的过程中去改变返回的值,使得其上个节点得到的是修剪后的子树;但对于处于范围内的节点则负责接收修改的左子树和右子树

那这样递归的框架就能很容易的写出来写出来:

public TreeNode traversal(TreeNode root, int low, int high) {if (root == null) {}if (root.val > high) {} else if (root.val < low) {} else {root.right = traversal(root.right, low, high);root.left = traversal(root.left, low, high);  return root;}}
  1. 先确定了返回值:送分题,root == null,因为对空节点的任何操作都没有意义。
  2. 然后对该节点不处于规定范围和处于规定范围做不同的处理。
  3. 对于处于规定范围的节点直接负责接收值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后来看这个具体的案例,来思考如果节点处于范围外应该去做些什么:回想一下上面提到的,修剪其实就是让本节点的返回值不再是它自己而是它的符合情况的子树

  • 节点 0 是在范围外的,所以它的右子树可能在范围内,所以这里返回的就是它的向右递归搜索的结果,思考到这里就可以了,递归一定不要去特别深入的思考,否则很容易将自己绕进去

  • 这里理顺这个关系就可以:首先要去返回它符合条件子树来达到修剪的目的,而符合条件的子树肯定是出现在该节点的右子树,然后在右子树中去执行相同的逻辑,那调用这个方法最终返回的结果就是符合规范的子树。

  • 比如 0 节点返回的就是 1 2 这个子树

    return traversal(root.right);
    

那对于 root.val > high 的处理情况也很清晰了,要去它 左子树 去得到符合规范的子树。

return traversal(root.left)k

将上面的代码补充完整。

1.3 代码
class Solution {public TreeNode trimBST(TreeNode root, int low, int high) {if (root == null) {return null;}if (root.val > high) {return trimBST(root.left, low, high);} else if (root.val < low) {return trimBST(root.right, low, high);} else {root.right = trimBST(root.right, low, high);root.left = trimBST(root.left, low, high);  return root;}}
}

02. 将有序数组转换为二叉搜索树(No. 108)

题目链接

代码随想录题解

2.1 题目

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:nums = [1,3]
输出:[3,1]
解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums严格递增 顺序排列
2.2 笔记

延续上一道题,其实构造一个二叉树无非也就是这样的思路:

首先将这个节点创造出来,然后分别向两侧去遍历,使得返回值是构造好的子树,并且将这个子树置于其左子树和右子树即可。

先来写一个基础的结构

public TreeNode traversal(int[] nums, int startIndex, int endIndex) {if () {// 终止条件}TreeNode node = new TreeNode(); // 构造新节点的条件node.right = traversal(); // 右递归的条件传输node.left = traversal(); // 左递归的条件传输return node;
}

💡 这里涉及到了逻辑切割数组,可以查看一下我这篇博客的第三道题目

  • 代码随想录刷题笔记 DAY 18 | 找树左下角的值 No.513 | 路经总和 No.112 | 从中序与后序遍历序列构造二叉树 No.106
  • 其实理解起来也很容易,就是传入数组的起始和终止位置来约束来达到和分割数组相同的效果。

接下来就是依照题目去一点点解决这些问题了:

👉 构造节点的条件

  • 这里才开始做和这道题目有关的事情,首先题目交给的就已经是排序好的数组,只需要保证左右子树平衡即可,也就是考虑怎样分割数组的问题。

    • 平衡就需要保证左子树和右子树的节点数量尽量相同,那 分割点起始就是数组中间点

    • 将代码补充出来:

      int mid = (startIndex + endIndex) / 2;
      Treenode node = new TreeNode(nums[mid]);
      

👉 左右递归的条件传输

  • 那分析到这里其实做有递归的条件也很容易写出来了,就是从 startIndexmid - 1 作为其左子树, mid + 1endIndex 作为其右子树。

    • 将代码补充出来

      node.left = traversal(nums, startIndex, mid - 1);
      node.right = traversal(nums, mid + 1, endIndex);
      

👉 递归的终点

  • 当是实际的切割数组的时候,终止条件其实很容易写出,就是 nums == null 的时候,但是对于这种逻辑切割就要考虑一下了。

  • 答案是 startIndex > endIndex 而不是 startIndex == endIndex,因为在过程中如果出现表示的数组为空,逻辑的起始和终止就会出现这种情况,可以当作结论记忆。

    • 将代码补充出来

      if (startIndex > endIndex) {return null;
      }
      
2.3 代码
class Solution {public TreeNode sortedArrayToBST(int[] nums) {return traversal(nums, 0, (nums.length - 1));}public TreeNode traversal(int[] nums, int startIndex, int endIndex) {if (startIndex > endIndex) {return null;}int mid = (startIndex + endIndex) / 2;TreeNode node = new TreeNode(nums[mid]);node.left = traversal(nums, startIndex, mid - 1);node.right = traversal(nums, mid + 1, endIndex);return node;}
}

03. 把二叉搜索树转换为累加树(No. 538)

题目链接

代码随想录题解

3.1 题目

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

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

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

**注意:**本题和 1038: https://leetcode-cn.com/problems/binary-search-tree-to-greater-sum-tree/ 相同

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:[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]

提示:

  • 树中的节点数介于 0104 之间。
  • 每个节点的值介于 -104104 之间。
  • 树中的所有值 互不相同
  • 给定的树为二叉搜索树。
3.2 笔记

题目中给出的是二叉搜索树,来观察上面的 示例 1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

累加树的特征为:每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

二叉搜索树的最右边的节点是整个树中最大的节点,也就是说大于等于它的节点就是它本身,而再往上推到上图中的节点 7 作为次大的节点,这个节点的值就是它本身加上比他大的值也就是 8,按照这个规律很容易就能得出其他的节点的值,节点 6 的值就是 6 + 7 + 8 ,而节点 5 的值就是 5 + 6 + 7 + 8

所以这道题的思路就很明确了:以 右、中、左 的顺序去遍历二叉树,在这途中给节点加上路径中的节点和即可。

最后只需要解决如何按照 右、中、左 的顺序去遍历二叉树就可以了,这其实就是一种另类的中序遍历:

traversal(node.left);
System.out.println(node.val);
traversal(node.right);

这样的遍历顺序是 左、中、右,那修改一下

traversal(node.right);
System.out.println(node.val);
traversal(node.left);

这样就能得到符合上面遍历顺序的值。

只要将输出语句改为对节点的操作就能达到倒序的操作树(将搜索树看作升序数组)。

定义一个全局变量为 0,随着遍历逐步累加为 8 15 21 26 然后将其赋值给该节点即可。

  • globalNum += node.val;
    node.val = globalNum;
    
3.3 代码
class Solution {int globalNum = 0;public TreeNode convertBST(TreeNode root) {traversal(root);return root;}public void traversal(TreeNode node) {if (node == null) {return;}traversal(node.right);globalNum += node.val;node.val = globalNum;traversal(node.left);}
}

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

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

相关文章

Vue - 快速入门(一)

阅读文章可以收获&#xff1a; 1. 明白什么是vue 2. 如何创建一个vue实例 3. vue中的插值表达式如何使用 4. 如何安装vue的开发者工具 Vue 概念 什么是vue&#xff1f; Vue 是一个用于 构建用户界面 的 渐进式 框架 框架优点&#xff1a;大大提升开发效率 (70%↑) 缺点…

第80讲订单管理功能实现

后端 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace"com.java1234.mapper.OrderM…

深入学习Pandas:数据连接、合并、加入、添加、重构函数的全面指南【第72篇—python:数据连接】

深入学习Pandas&#xff1a;数据连接、合并、加入、添加、重构函数的全面指南 Pandas是Python中最强大且广泛使用的数据处理库之一&#xff0c;提供了丰富的函数和工具&#xff0c;以便更轻松地处理和分析数据。在本文中&#xff0c;我们将深入探讨Pandas中一系列数据连接、合…

React18原理: 再聊Fiber架构下的时间分片

时间分片 react的任务可以被打断&#xff0c;其实就是基于时间分片的人眼最高能识别的帧数不超过30帧&#xff0c;电影的帧数差不多是在24浏览器的帧率一般来说是60帧&#xff0c;也就是每秒60个画面, 平均一个画面大概是16.5毫秒左右浏览器正常的工作流程是运算渲染&#xff…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之QRCode组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之QRCode组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、QRCode组件 用于显示单个二维码的组件。 子组件 无。 接口 QRCode(value: st…

python-分享篇-GUI界面开发-PyQt5-对QListWidget列表进行数据绑定

代码 # -*- coding: utf-8 -*-# Form implementation generated from reading ui file bindlist.ui # # Created by: PyQt5 UI code generator 5.11.3 # # WARNING! All changes made in this file will be lost! 对QListWidget列表进行数据绑定from PyQt5 import QtCore, QtG…

Elasticsearch:混合搜索是 GenAI 应用的未来

在这个竞争激烈的人工智能时代&#xff0c;自动化和数据为王。 从庞大的存储库中有效地自动化搜索和检索信息的过程的能力变得至关重要。 随着技术的进步&#xff0c;信息检索方法也在不断进步&#xff0c;从而导致了各种搜索机制的发展。 随着生成式人工智能模型成为吸引力的中…

华为云ModelBox实战:体感小游戏应用实操

目录 一、VsCode插件注册ModelBox设备二、Windows SDK安装1.安装Git for Windows2.下载ModelBox SDK3.相关插件安装 三、体感小游戏应用开发1.技能模板使用2.AI应用示例3.体感小游戏体验 参与华为云活动【HCSD】ModelBox实战营邀请活动&#xff0c;呼朋唤友学AIoT&#xff0c;完…

flask+python企业产品订单管理系统938re

在设计中采用“自下而上”的思想&#xff0c;在创新型产品提前购模块实现了个人中心、个体管理、发布企业管理、投资企业管理、项目分类管理、产品项目管理、个体投资管理、企业投资管理、个体订单管理、企业订单管理、系统管理等的功能性进行操作。最终&#xff0c;对基本系统…

Java学习-常用API(二)

Math类及其常用API&#xff1a; 演示&#xff1a; StringBuilder的认识及其常用方法&#xff1a; StringBuilder支持链式编程 StringBuilder sbnew StringBuilder&#xff08;&#xff09;&#xff1b;sb.append&#xff08;12&#xff09;.append.&#xff08;“itHeima”&am…

synchronized关键字以及底层实现

目录 基本使用 底层实现 synchronized锁升级 对象的内存结构 ⅰ. 对象头 1. ① 运行时元数据 (Mark Word) (占64位) a. 哈希值 (HashCode) b. GC分代年龄 c. 锁状态标记 2. ② 类型指针: (Klass Point) (占 32位) ⅱ. 实例数据 ⅲ. 对齐填充 Moniter重量级锁 轻量…

[ai笔记3] ai春晚观后感-谈谈ai与艺术

欢迎来到文思源想的ai空间&#xff0c;这是技术老兵重学ai以及成长思考的第3篇分享&#xff01; 今天我们不聊技术&#xff0c;只聊感受&#xff01; 1 关于ai春晚 期待许久的ai春晚&#xff0c;但是等初一晚上观看的时候&#xff0c;或多或少还是有些失望。 首先是观看人数…

前端工程化面试题 | 06.精选前端工程化高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【二叉树】构建销毁二叉树

目录 创建二叉树 整体思路 代码实现 图示理解​ 销毁二叉树 判断二叉树是否是完全二叉树&层序 整体思路 代码实现 图是理解 二叉树的性质 题目 创建二叉树 整体思路 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树遇到#就回退&#xff0c;返回…

浅谈路由器交换结构

一、路由器技术概述 路由器&#xff08;Router&#xff09;是连接两个或多个网络的硬件设备&#xff0c;在网络间起网关的作用&#xff0c;是读取每一个数据包中的地址然后决定如何传送的专用智能性的网络设备。它能够理解不同的协议&#xff0c;例如某个局域网使用的以太网协议…

文章页的上下篇功能是否有必要?boke112百科取消上下篇功能

也不知道是从什么时候开始&#xff0c;我们很多站长的博客网站文章页都会在文末添加上“上一篇”和“下一篇”功能&#xff0c;目的是进行站内SEO优化和方便用户阅读上下篇文章。 boke112百科不管是以前使用的Three主题还是现在使用的YIA主题&#xff0c;刚开始的文章页都是有…

学习Android的第十天

目录 Android CheckBox 复选框 获得选中的 CheckBox 的值 自定义点击效果 改变文字与选择框的相对位置 修改文字与选择框的距离 Android ToggleButton 开关按钮 改变 ToggleButton 的状态和文本 Android Switch 开关 改变 Switch 的状态和文本 Android CheckBox 复选框…

腾讯云4核8G服务器可以用来干嘛?怎么收费?

腾讯云4核8G服务器适合做什么&#xff1f;搭建网站博客、企业官网、小程序、小游戏后端服务器、电商应用、云盘和图床等均可以&#xff0c;腾讯云4核8G服务器可以选择轻量应用服务器4核8G12M或云服务器CVM&#xff0c;轻量服务器和标准型CVM服务器性能是差不多的&#xff0c;轻…

sheng的学习笔记-docker部署springboot

部署文章目录&#xff1a;目录 docker部署&#xff0c;原理&#xff0c;命令&#xff0c;可以参考&#xff1a;docker原理图&#xff0c;部署&#xff0c;命令 目录 将springboot部署到docker中 遇到过的问题&#xff1a; pom配置 操作步骤 生成jar 构建镜像 查看镜像d…

CTFshow-WEB入门-信息搜集

web1&#xff08;查看注释1&#xff09; wp 右键查看源代码即可找到flag web2&#xff08;查看注释2&#xff09; wp 【CtrlU】快捷键查看源代码即可找到flag web3&#xff08;抓包与重发包&#xff09; wp 抓包后重新发包&#xff0c;在响应包中找到flag web4&#xff08;robo…