【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事!

简介: 二叉搜索树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。

题目链接


LeetCode 99. 恢复二叉搜索树[1]

题目描述


二叉搜索树中的两个节点被错误地交换。

请在不改变其结构的情况下,恢复这棵树。

示例1

输入
:[1,3,null,null,2]  
1  
/ 
3
\   2
输出:
[3,1,null,null,2]   3  / 1  \   2

示例2

输入:[3,1,4,null,null,2]  3 / \1   4   /  2输出:[2,1,4,null,null,3]  2 / \1   4   /  3

进阶:

image.png

题解


先不考虑空间复杂度,因为二叉搜索树的中序遍历是单调递增的,所以我们只需要求出它的中序遍历。然后两个结点被调换过位置,等价于递增序列中两个数调换了位置。那么我们只需要找出序列中第一个逆序对(前一个数)和最后一个逆序对(后一个数)就行了,然后换回它俩的位置。

但是中序遍历无论使用递归实现还是栈实现,空间复杂度都是树的高度,不是常数。

想一下为什么我们需要用递归或者栈来实现中序遍历?因为从根结点开始进入左子树之后,遍历完了左子树还需要回到根结点,然后再进入右子树继续遍历。但是如果你没有栈,你就没法从左子树回到根结点了,因为左子树中没有结点能指到根结点。

我们需要解决的就是这个问题,这里我们引入 Morris 遍历算法

下图是一个二叉搜索树例子:image.png

我们用递归来做中序遍历,访问结点的顺序是 4212346567 (这个序列就是 Morris 遍历得到的序列)。注意到非叶子结点 246 会被访问两次,第一次是作为根结点进入左子树,第二次是递归返回了,中序遍历到自己了。

那么不用递归或者栈,我们怎么在第二次成功返回根结点呢?注意到叶子结点的左右儿子都是空的,所以可以利用它们来指向根结点。

用结点 4 举个例子。首先访问 4 ,然后遍历它的左子树。左子树的最后一个遍历的结点是 3 ,那么我们就把 3 的右儿子指向根结点 4 。这样遍历完左子树之后,还能通过 3 的右儿子回到根结点 4 ,接着继续遍历右子树。

所以在第一次访问根结点时,首先要找出它左子树中最右边的那个叶子结点,把它的右儿子指向根结点。然后才能放心地递归遍历左子树,不用担心回不去啦。

具体实现的时候还有一些细节,看代码更好理解,我都写在注释里面了。

代码


c++

/** * Definition for a binary tree node. * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */classSolution {
public:
voidrecoverTree(TreeNode*root) {     
TreeNode*x=NULL, *y=NULL, *pre=NULL, *rightmost=NULL;  
while (root) {  
// 如果有左子树,就递归遍历左子树。 if (root->left) {    
rightmost=root->left;   
// 找出左子树的最右边一个叶子结点   while (rightmost->right&&rightmost->right!=root)
                {           
rightmost=rightmost->right;    
                }     
// 如果左子树最右边的叶子结点的右儿子是空的, // 那就说明根结点是第一次访问,那么就把它的右儿子指向根结点。              // 然后递归遍历左子树。if (rightmost->right!=root) {   
rightmost->right=root;  
root=root->left;          
// 否则的话说明根结点是第二次访问了,// 那就说明左子树已经递归完毕了,    // 那么就判断一下是否存在逆序对。  // 记得把左子树最右叶子结点的右儿子改回空指针。// 然后递归遍历右子树了。                    } else {            
if (pre&&pre->val>root->val) {    
if (x==NULL) x=pre;  
y=root;    
                    }           
rightmost->right=NULL;  
pre=root;       
root=root->right;     
                }          
// 如果没有左子树,那就直接遍历右子树,同时判断是否存在逆序对。                 } else {      
if (pre&&pre->val>root->val) {      
if (x==NULL) x=pre;      
y=root;         
                }             
pre=root;     
root=root->right; 
            }     
        }      
swap(x->val, y->val);  
    }
};

参考资料


[1]

LeetCode 99. 恢复二叉搜索树: https://leetcode-cn.com/problems/recover-binary-search-tree/

image.png

作者简介:godweiyang知乎同名华东师范大学计算机系硕士在读,方向自然语言处理与深度学习喜欢与人分享技术与知识,期待与你的进一步交流~


相关文章
|
1天前
|
机器学习/深度学习 算法 安全
基于深度学习的路面裂缝检测算法matlab仿真
本项目基于YOLOv2算法实现高效的路面裂缝检测,使用Matlab 2022a开发。完整程序运行效果无水印,核心代码配有详细中文注释及操作视频。通过深度学习技术,将目标检测转化为回归问题,直接预测裂缝位置和类别,大幅提升检测效率与准确性。适用于实时检测任务,确保道路安全维护。 简介涵盖了算法理论、数据集准备、网络训练及检测过程,采用Darknet-19卷积神经网络结构,结合随机梯度下降算法进行训练。
|
2天前
|
算法 数据可视化 数据安全/隐私保护
一级倒立摆平衡控制系统MATLAB仿真,可显示倒立摆平衡动画,对比极点配置,线性二次型,PID,PI及PD五种算法
本课题基于MATLAB对一级倒立摆控制系统进行升级仿真,增加了PI、PD控制器,并对比了极点配置、线性二次型、PID、PI及PD五种算法的控制效果。通过GUI界面显示倒立摆动画和控制输出曲线,展示了不同控制器在偏转角和小车位移变化上的性能差异。理论部分介绍了倒立摆系统的力学模型,包括小车和杆的动力学方程。核心程序实现了不同控制算法的选择与仿真结果的可视化。
30 15
|
2天前
|
算法
基于SOA海鸥优化算法的三维曲面最高点搜索matlab仿真
本程序基于海鸥优化算法(SOA)进行三维曲面最高点搜索的MATLAB仿真,输出收敛曲线和搜索结果。使用MATLAB2022A版本运行,核心代码实现种群初始化、适应度计算、交叉变异等操作。SOA模拟海鸥觅食行为,通过搜索飞行、跟随飞行和掠食飞行三种策略高效探索解空间,找到全局最优解。
|
3天前
|
算法 数据安全/隐私保护 计算机视觉
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
|
4天前
|
机器学习/深度学习 数据采集 算法
基于GWO灰狼优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目基于MATLAB2022a,展示了时间序列预测算法的运行效果(无水印)。核心程序包含详细中文注释和操作视频。算法采用CNN-GRU-SAM网络,结合灰狼优化(GWO),通过卷积层提取局部特征、GRU处理长期依赖、自注意力机制捕捉全局特征,最终实现复杂非线性时间序列的高效预测。
|
4天前
|
传感器 算法 物联网
基于粒子群算法的网络最优节点部署优化matlab仿真
本项目基于粒子群优化(PSO)算法,实现WSN网络节点的最优部署,以最大化节点覆盖范围。使用MATLAB2022A进行开发与测试,展示了优化后的节点分布及其覆盖范围。核心代码通过定义目标函数和约束条件,利用PSO算法迭代搜索最佳节点位置,并绘制优化结果图。PSO算法灵感源于鸟群觅食行为,适用于连续和离散空间的优化问题,在通信网络、物联网等领域有广泛应用。该算法通过模拟粒子群体智慧,高效逼近最优解,提升网络性能。
|
1月前
|
算法 数据安全/隐私保护 计算机视觉
基于Retinex算法的图像去雾matlab仿真
本项目展示了基于Retinex算法的图像去雾技术。完整程序运行效果无水印,使用Matlab2022a开发。核心代码包含详细中文注释和操作步骤视频。Retinex理论由Edwin Land提出,旨在分离图像的光照和反射分量,增强图像对比度、颜色和细节,尤其在雾天条件下表现优异,有效解决图像去雾问题。
|
1月前
|
算法 数据可视化 安全
基于DWA优化算法的机器人路径规划matlab仿真
本项目基于DWA优化算法实现机器人路径规划的MATLAB仿真,适用于动态环境下的自主导航。使用MATLAB2022A版本运行,展示路径规划和预测结果。核心代码通过散点图和轨迹图可视化路径点及预测路径。DWA算法通过定义速度空间、采样候选动作并评估其优劣(目标方向性、障碍物距离、速度一致性),实时调整机器人运动参数,确保安全避障并接近目标。
147 68
|
1月前
|
算法 决策智能
基于SA模拟退火优化算法的TSP问题求解matlab仿真,并对比ACO蚁群优化算法
本项目基于MATLAB2022A,使用模拟退火(SA)和蚁群优化(ACO)算法求解旅行商问题(TSP),对比两者的仿真时间、收敛曲线及最短路径长度。SA源于金属退火过程,允许暂时接受较差解以跳出局部最优;ACO模仿蚂蚁信息素机制,通过正反馈发现最优路径。结果显示SA全局探索能力强,ACO在路径优化类问题中表现优异。
|
1月前
|
移动开发 算法 计算机视觉
基于分块贝叶斯非局部均值优化(OBNLM)的图像去噪算法matlab仿真
本项目基于分块贝叶斯非局部均值优化(OBNLM)算法实现图像去噪,使用MATLAB2022A进行仿真。通过调整块大小和窗口大小等参数,研究其对去噪效果的影响。OBNLM结合了经典NLM算法与贝叶斯统计理论,利用块匹配和概率模型优化相似块的加权融合,提高去噪效率和保真度。实验展示了不同参数设置下的去噪结果,验证了算法的有效性。

热门文章

最新文章