LeetCode 剑指 Offer II 054. 所有大于等于节点的值之和

给定一个二叉搜索树,请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。

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

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

示例 1:
在这里插入图片描述
输入: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]

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

解法一:反向中序遍历树,每遍历到一个节点,将其加到所有节点和中,然后将该节点值设为当前所有节点和:

/**
 * 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* convertBST(TreeNode* root) {
        if (root == nullptr) {
            return nullptr;
        }

        convertBST(root->right);
        sum += root->val;
        root->val = sum;
        convertBST(root->left);

        return root;
    }
private:
    int sum = 0;
};

如果树有n个节点,则此算法时间复杂度为O(n),空间复杂度平均情况下O(lgn),最差情况下为O(n),主要的空间开销是栈开销,当二叉搜索树退化成链表时,空间复杂度达到最大。

解法二:此解法是解法一的迭代版,用一个stack来模拟函数调用栈:

/**
 * 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* convertBST(TreeNode* root) {
        stack<TreeNode *> s;
        TreeNode *curNode = root;
        while (curNode || !s.empty()) {
            while (curNode) {
                s.push(curNode);
                curNode = curNode->right;
            }

            curNode = s.top();
            s.pop();
            sum += curNode->val;
            curNode->val = sum;

            curNode = curNode->left;
        }

        return root;
    }
private:
    int sum = 0;
};

如果树有n个节点,则此算法时间复杂度为O(n),空间复杂度平均情况下O(lgn),最差情况下为O(n),主要的空间开销是栈开销,当二叉搜索树退化成链表时,空间复杂度达到最大。

解法三:Morris遍历,它的反向中序遍历的规则如下:
1.如果当前节点的右子节点为空,处理当前节点,并遍历当前节点的左子节点;

2.如果当前节点的右子节点不为空,找到当前节点右子树的最左节点(该节点为当前节点中序遍历的前驱节点);

(1)如果最左节点的左指针为空,将最左节点的左指针指向当前节点,遍历当前节点的右子节点;

(2)如果最左节点的左指针不为空,将最左节点的左指针重新置为空(恢复树的原状),处理当前节点,并将当前节点置为其左节点;

3.重复步骤1和步骤2,直到遍历结束。

/**
 * 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* convertBST(TreeNode* root) {
        TreeNode *node = root;
        int sum = 0;

        while (node)
        {
            if (node->right == nullptr)
            {
                sum += node->val;
                node->val = sum;
                node = node->left;
            }
            else
            {
                TreeNode *mostLeftOfRight = getMostLeftOfRight(node);
                if (mostLeftOfRight->left == nullptr)
                {
                    mostLeftOfRight->left = node;
                    node = node->right;
                }
                else if (mostLeftOfRight->left == node)
                {
                    sum += node->val;
                    node->val = sum;
                    mostLeftOfRight->left = nullptr;
                    node = node->left;
                }
            }
        }

        return root;
    }

private:
    TreeNode *getMostLeftOfRight(TreeNode *node)
    {
        TreeNode *mostLeftOfRight = node->right;
        while (mostLeftOfRight->left && mostLeftOfRight->left != node)
        {
            mostLeftOfRight = mostLeftOfRight->left;
        }

        return mostLeftOfRight;
    }
};

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

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

相关文章

【计数DP】牛客小白月赛19

登录—专业IT笔试面试备考平台_牛客网 题意 思路 首先做法一定是计数 dp 然后状态设计&#xff0c;先设 dp[i] 然后看影响决策的因素&#xff1a;两边的火焰情况&#xff0c;那就 dp[i][0/1][0/1]表示 前 i 个&#xff0c;该位有无火焰&#xff0c;该位右边有无火焰的方案数…

Kioptrix-3

靶场下载地址 https://download.vulnhub.com/kioptrix/KVM3.rar 信息收集 # Nmap 7.94 scan initiated Thu Dec 21 21:52:25 2023 as: nmap -sn -oN live.nmap 192.168.1.0/24 Nmap scan report for 192.168.1.1 (192.168.1.1) Host is up (0.00048s latency). MAC Address:…

2024年PMP考试新考纲-PMBOK第七版-项目管理原则真题解析(续2)

很多在备考2024年PMP考试的小伙伴问华研荟&#xff0c;从8月份以后把PMBOK第七版纳入PMP考试范围后&#xff0c;难不难&#xff1f;PMBOK第七版怎么考&#xff1f;尤其是第七版中的十二大项目管理原则读起来很晦涩难懂&#xff0c;这部分怎么考&#xff1f;该如何备考呢&#x…

Linux---基础操作命令

内容导航 类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统…

JavaWeb—html, css, javascript, dom,xml, tomcatservlet

文章目录 快捷键HTML**常用特殊字符替代:****标题****超链接标签****无序列表、有序列表****无序列表**:ul/li 基本语法**有序列表ol/li:****图像标签(img)**** 表格(table)标签****表格标签-跨行跨列表格****form(表单)标签介绍****表单form提交注意事项**div 标签p 标签sp…

Android可折叠设备完全指南:展开未来

Android可折叠设备完全指南&#xff1a;展开未来 探索如何使用Android Jetpack组件折叠和展开设备。 近年来&#xff0c;科技界见证了可折叠设备的革命性趋势。这些设备融合了便携性和功能性的创新特点&#xff0c;使用户能够在不同的形态之间无缝切换。在本博客中&#xff0c…

照片墙案例

整体效果&#xff1a; HTML部分&#xff1a; <body><div class"content"><header><h1>A silent world</h1><span>Image Wall with jQuery and CSS3</span></header><div class"iw_wrapper"><ul…

3D数字化系统建设

以3D可视化、数字化技术为基础&#xff0c;其实&#xff0c;很多传统的系统软件都可以重新做一下。 比如&#xff1a;以下这个使用场景&#xff1a;零售门店陈列&#xff1b; 还有&#xff0c;数字化仓储系统&#xff0c;3D数字化供应链系统&#xff0c;3D数字化的生产系统&a…

.NET中的Swagger使用

目录 前言 一、Swagger是什么&#xff1f; 二、如何Swagger文档说明的信息 1.在AddSwaggerGen方法中写入文档信息 2.运行效果 二、文档UI界面标题、路由设置 1.在中间件UseSwaggerUI方法中配置 三、文档UI界面添加接口注释 1.在 .csproj中配置 2.在AddSwaggerGen方法中配置Incl…

MFC 菜单

目录 MFC菜单 菜单使用 添加菜单资源 将菜单设置到窗口 ON_COMMAND消息处理 命令消息 WM_COMMAND 的处理顺序 设置菜单项状态 右键菜单 MFC菜单 在Win32编程中&#xff0c;使用菜单句柄 HMENU 来标识菜单&#xff0c;在MFC中使用CMenu类对象表示菜单。封装了关于菜单的…

MATLAB - 四元数(quaternion)

系列文章目录 前言 一、简介 四元数是一种四元超复数&#xff0c;用于三维旋转和定向。 四元数的表示形式为 abicjdk&#xff0c;其中 a、b、c 和 d 为实数&#xff0c;i、j 和 k 为基元&#xff0c;满足等式&#xff1a;i2 j2 k2 ijk -1。 四元数集用 H 表示&#xff0c…

vmware安装中标麒麟高级服务器操作系统软件 V7.0操作系统

vmware安装中标麒麟高级服务器操作系统软件 V7.0操作系统 1、下载中标麒麟高级服务器操作系统软件 V7.0镜像2、安装中标麒麟高级服务器操作系统软件 V7.0操作系统 1、下载中标麒麟高级服务器操作系统软件 V7.0镜像 官方提供使用通道 访问官网 链接: https://www.kylinos.cn/ 下…

【Python】基于flaskMVT架构与session实现博客前台登录登出功能

目录 一、MVT说明 1.Model层 2.View层 3.Template层 二、功能说明 三、代码框架展示 四、具体代码实现 models.py 登录界面前端代码 博客界面前端代码&#xff08;profile.html&#xff09; main.py 一、MVT说明 MVT架构是Model-View-Template的缩写&#xff0c;是…

VS(Visual Studio)更改文件编码

vs默认编码是GB2312,更改为UTF-8 工具->自定义

Tomcat与Netty比较

Tomcat介绍Tomcat支持的协议Tomcat的优缺点Netty介绍Netty支持的协议Netty的优点和缺点Tomcat和Netty的区别Tomcat和Netty的应用场Tomcat和Netty来处理大规模并发连接的优化Tomcat与Netty的网络模型的区别Tomcat与Netty架构设计拓展 Tomcat介绍 Tomcat是一个免费的、开放源代码…

nodejs+vue+ElementUi摄影作品图片分享工作室管理系统

第1周 2.21&#xff5e;2.27 查阅资料&#xff0c;学习vscode开发平台和vue框架技术 第2周 2.28&#xff5e;3.6 对软件功能需求进行分析, 软件功能模块划分及软件界面设计 第3周 3.7&#xff5e;3.13 撰写并提交毕业设计开题报告、英文资料翻译 第4周 3.14&#xff5…

深度学习中的池化

1 深度学习池化概述 1.1 什么是池化 池化层是卷积神经网络中常用的一个组件&#xff0c;池化层经常用在卷积层后边&#xff0c;通过池化来降低卷积层输出的特征向量&#xff0c;避免出现过拟合的情况。池化的基本思想就是对不同位置的特征进行聚合统计。池化层主要是模仿人的…

【docker笔记】docker理论及安装

前言 本笔记来源于尚硅谷docker教学视频 视频地址&#xff1a;https://www.bilibili.com/video/BV1gr4y1U7CY/?spm_id_from333.337.search-card.all.click 纯手打笔记&#xff0c;来之不易&#xff0c;感谢支持~ Docker简介 docker为什么会出现 想象一下&#xff1a;一个应用…

Web前端-JavaScript(Dom基础)

文章目录 1.1 DOM 介绍1.1.1 DOM简介1.1.2 DOM树 1.2. 获取元素1.2.1 根据ID获取元素1.2.2 根据标签名获取元素1.2.3 其它方式获取元素1.2.4 获取特殊元素 1.3 事件基础1.3.1 事件概述1.3.2 事件三要素1.3.3 执行事件步骤1.3.4 鼠标事件 1.4 操作元素1.4.1 操作元素内容1.4.2 属…

Java小案例-MusiQ音乐网站

目录 前言 项目功能 技术栈 后端 前端 开发环境 项目展示 前台-首页-展示 前台-首页-代码 前台-歌单-展示 前台-歌单-代码 前台-歌手-展示 前台-歌手-代码 前台-其他页面展示 后台-登录-展示 后台-登录-代码 后台-首页-展示 首台-首页-代码 后台-其他页面-展…