二叉搜索树题目:把二叉搜索树转换为累加树

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 前言
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法三
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:把二叉搜索树转换为累加树

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

难度

4 级

题目描述

要求

给定二叉搜索树的根结点 root \texttt{root} root,将其转换为累加树,原二叉搜索树中的每个结点值都变成原结点值加上比该结点值大的所有结点值总和。

二叉搜索树满足下列约束条件:

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

示例

示例 1:

示例 1

输入: root = [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8] \texttt{root = [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]} root = [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] \texttt{[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]} [30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]

示例 2:

输入: root = [0,null,1] \texttt{root = [0,null,1]} root = [0,null,1]
输出: [1,null,1] \texttt{[1,null,1]} [1,null,1]

数据范围

  • 树中结点数目在范围 [0, 10 4 ] \texttt{[0, 10}^\texttt{4}\texttt{]} [0, 104]
  • -10 4 ≤ Node.val ≤ 10 4 \texttt{-10}^\texttt{4} \le \texttt{Node.val} \le \texttt{10}^\texttt{4} -104Node.val104
  • 树中的所有值各不相同
  • root \texttt{root} root 保证是有效的二叉搜索树

前言

考虑二叉搜索树的中序遍历。常规的中序遍历方法是依次遍历左子树、根结点和右子树,对于左子树和右子树使用同样的方法遍历,此时二叉搜索树的中序遍历序列是单调递增的。将中序遍历的顺序改变,依次遍历右子树、根结点和左子树,则是反向中序遍历,二叉搜索树的反向中序遍历序列是单调递减的。在反向中序遍历的过程中,对于每个结点,比该结点值大的所有结点都在该结点之前被访问。

由于对二叉搜索树反向中序遍历访问结点的顺序为结点值单调递减的顺序,因此可以通过反向中序遍历将二叉搜索树转换为累加树。反向中序遍历的过程中,维护已经访问过的结点值总和,对于访问到的每个结点,将总和加到当前结点值,则当前结点值变为该结点在累加树中对应的结点值,然后将当前结点值作为更新后的结点值总和,继续遍历其余的结点,直到遍历结束时,即可得到累加树。

解法一

思路和算法

由于二叉搜索树的反向中序遍历具有递归的性质,因此可以使用递归的方法实现中序遍历。使用递归实现反向中序遍历的做法是依次访问右子树、根结点和左子树,对于右子树和左子树使用同样的方法访问。

遍历过程中维护已经访问过的结点值总和,对于访问到的每个结点,更新结点值,并更新已经访问过的结点值总和。

代码

class Solution {int prev = 0;public TreeNode convertBST(TreeNode root) {if (root == null) {return root;}convertBST(root.right);root.val += prev;prev = root.val;convertBST(root.left);return root;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。空间复杂度主要是递归调用的栈空间,取决于二叉搜索树的高度,最坏情况下二叉搜索树的高度是 O ( n ) O(n) O(n)

解法二

思路和算法

使用迭代实现反向中序遍历的做法是使用栈存储结点。

遍历过程中维护已经访问过的结点值总和,对于访问到的每个结点,更新结点值,并更新已经访问过的结点值总和。

代码

class Solution {public TreeNode convertBST(TreeNode root) {int prev = 0;Deque<TreeNode> stack = new ArrayDeque<TreeNode>();TreeNode node = root;while (!stack.isEmpty() || node != null) {while (node != null) {stack.push(node);node = node.right;}node = stack.pop();node.val += prev;prev = node.val;node = node.left;}return root;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。空间复杂度主要是栈空间,取决于二叉搜索树的高度,最坏情况下二叉搜索树的高度是 O ( n ) O(n) O(n)

解法三

思路和算法

使用莫里斯遍历实现反向中序遍历时,由于遍历顺序是依次遍历右子树、根结点和左子树,因此和常规的莫里斯中序遍历的方向相反。对于每个结点,判断其右子树是否为空,如果当前结点的右子树不为空,则应该找到当前结点的后继结点,即当前结点的右子树中的最左边的结点,对后继结点执行相应的操作。

遍历过程中维护已经访问过的结点值总和,对于访问到的每个结点,更新结点值,并更新已经访问过的结点值总和。

代码

class Solution {public TreeNode convertBST(TreeNode root) {int prev = 0;TreeNode node = root;while (node != null) {if (node.right == null) {node.val += prev;prev = node.val;node = node.left;} else {TreeNode successor = node.right;while (successor.left != null && successor.left != node) {successor = successor.left;}if (successor.left == null) {successor.left = node;node = node.right;} else {successor.left = null;node.val += prev;prev = node.val;node = node.left;}}}return root;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。使用莫里斯遍历,每个结点最多被访问两次。

  • 空间复杂度: O ( 1 ) O(1) O(1)

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

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

相关文章

【北京迅为】《iTOP-3588开发板网络环境配置手册》第1章 网络基础知识学习

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

vue前端使用get方式获取api接口数据 亲测

// GET请求示例 axios.get(‘http://127.0.0.1:5005/ReadIDCardInfo’) // 将URL替换为真正的API接口地址 .then(response > { if(response.data.code1){ var jsonDataresponse.data.data; console.log(jsonData); // 输出从API接口返回的数据 } }) .catch(error > { con…

windows IIS 申请和配置https(SSL)的工具 win-acme

win-acme 是一个为Windows平台设计的工具&#xff0c;用于从Lets Encrypt自动获取和续期SSL/TLS证书&#xff0c;特别适合用于IIS&#xff08;Internet Information Services&#xff09;服务器。它的使用相对简单&#xff0c;提供了一个用户友好的命令行界面&#xff0c;以及一…

是谁家的小千金跑出来了?

古典的山树绣花设计 精致典雅&#xff0c;上身立体又轻盈 做了粉绿两色&#xff0c;很适合春天的氛围 春天是个适合外出游玩的季节 穿上这件出游真的超美&#xff0c;日常穿也可 超出片很吸睛&#xff01;

推荐一款ssh工具 xshell替代品 electerm

下载地址 electerm&#xff1a; https://electerm.github.io/electerm/ windows版本 产品优势 复制粘贴&#xff0c;可以直接使用ctrlc/v 非常的方便 而且不想xshell 需要账号登陆&#xff0c;有更新弹窗&#xff0c;自身集成了sftp 界面设计更新&#xff0c;比MobaXterm的…

Qt6.8 GRPC功能使用(1)标准GRPC C++ exmple编译环境搭建

MSYS2 环境搭建 1. MSYS2 安装 https://www.msys2.org/#installation 网页中找到Installation&#xff0c; 提供下载&#xff0c; 本次下载版本是 [msys2-x86_64-20240113.exe](https://github.com/msys2/msys2-installer/releases/download/2024-01-13/msys2-x86_64-202401…

批量剪辑利器:轻松调整视频画面尺寸,打造专业级视听体验!

在数字时代&#xff0c;视频已成为我们生活中不可或缺的一部分。无论是制作个人Vlog、企业宣传片&#xff0c;还是进行专业的影视剪辑&#xff0c;调整视频画面的高度和宽度都是至关重要的一步。然而&#xff0c;面对大量视频文件&#xff0c;如何快速、高效地调整画面尺寸呢&a…

码住!2024抖音电商爆品攻略,21个行业68个类目一文集齐

小商家&#xff0c;大生意。 2023年&#xff0c;抖音电商高歌猛进&#xff0c;用直播带货创造增量&#xff0c;以商品卡承接用户资产&#xff0c;跑出2万亿市场&#xff0c;带动万千品牌实现二次增长&#xff0c;无数中小商家随奔腾浪潮涌出&#xff0c;从无名到争先&#xff…

Vue3 isProxy,isReactive,isReadonly 三者解析

1、isProxy 作用&#xff1a;判断当前数据是否为代理数据。 注意&#xff1a;它只对通过 reactive&#xff0c;readonly&#xff0c;shallowReactive&#xff0c;shallowReadonly 这四个方法包裹的数据返回true&#xff0c;对于 ref 以及通过 new Proxy 代理的数据返回都是fal…

力扣2月最后三天的每日一题

力扣2月最后三天的每日一题 前言2867.统计树中的合法路径数目思路确定1e5中的质数统计每个点的连接情况开始对质数点进行处理完整代码 2673.使二叉树所有路径值相等的最小代价思路完整代码 2581.统计可能的树根数目思路建立连通关系将猜测数组变为哈希表&#xff0c;方便查询利…

vue 部署后修改配置文件(接口IP)

近期&#xff0c;有一个项目&#xff0c;运维在部署的时候&#xff0c;接口ip还没有确定&#xff0c;而且ip后面的路径一直有变动&#xff0c;导致我这里一天打包至少四五次才行&#xff0c;很麻烦&#xff0c;然后看了下有没有打包后修改配置文件修改接口ip的方法&#xff0c;…

JavaScript的书写方式

JavaScript的书写方式 目前较为流行的是第二种和第三种&#xff0c;第一种很少见。在第二种和第三种推荐使用第三种&#xff0c;因为在日常开发/工作中&#xff0c;第三种是最为常见的 1.行内式 把JS代码嵌入到html元素内部 示例代码 运行效果 由于JS中字符串常量可以使用单引…