Morris遍历(力扣第99题)

假设有一个树:

a

/ \

b c

/ \ / \

d e f g

涉及到的变量root当前节点 、tmp 当前节点的前驱节点(极右)、prev前一个节点(99题用到 可以存前一个节点来比较val)

Morris遍历的优点:

空间复杂度为 O(1)

Morris遍历的规则:

  • 无左子树 :访问 rootroot 向右走

  • 有左子树

    • tmp(左子树的极右节点)

    • 第一次到:tmp.right 指向 rootroot 向左走

    • 第二次到:tmp.right 恢复为 null,访问 rootroot 向右走

Morris遍历的实现:

a

/ \

b c

/ \ / \

d e f g

当前节点root依次经过a b d b e a c f c g

可以发现a b c(有左子树的节点)都经历了两次,d e f g(无左子树的节点)只经历了1次

前序遍历(a b d e c f g)就是取a b d b e a c f c g第一次经过的a b c和无子树的节点**{有1+无}**

中序遍历(d b e a f c g)就是取a b d b e a c f c g第二次经过的a b c和无子树的节点**{有2+无}**

Morris遍历的过程:

a

/ \

b c

/ \ / \

d e f g

一开始root=a;tmp=e,发现是有1,让tmp.right指向a,root=b;继续发现是有1,让d指向b,root=d,发现是无左子树,让root=root.right,发现是有2,断开d和b的指向关系、root=root.right。root变成了e,又变成了无的情况,让root变成a,再经历有2,断开和更新root.......

prev用于力扣第99题,存前一个节点,方便和当前节点root进行比较。

prev要有空和非空的比较,这样做可以方便一开始prev=d

leetcode99:

99. 恢复二叉搜索树

题目:

给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树

代码:

java 复制代码
class Solution {
        public class TreeNode {
            int val;
            TreeNode left;
            TreeNode right;
            TreeNode() {}
            TreeNode(int val) { this.val = val; }
            TreeNode(int val, TreeNode left, TreeNode right) {
                this.val = val;
                this.left = left;
                this.right = right;
            }
        }
        //Morris遍历 空间复杂度O(1)
        public void recoverTree(TreeNode root) {
            TreeNode x=null;
            TreeNode y=null;
            TreeNode tmp=null;//前驱节点(极右)
            TreeNode prev=null;//记录前一个结点
            while (root!=null){
                //找tmp
                if(root.left!=null){//有左子树
                    tmp=root.left;
                    while (tmp.right!=null&&tmp.right!=root){
                        tmp=tmp.right;
                    }
                    if(tmp.right==null){//有1
                        tmp.right=root;
                        root=root.left;
                    }else{//有2
                        if(prev!=null&&prev.val>root.val){
                            x=root;
                            if(y==null){
                                y=prev;
                            }
                        }//交换
                        prev=root;
                        root=root.right;
                        tmp.right=null;
                    }
                }else{//无左子树
                    if(prev!=null&&prev.val>root.val){
                        x=root;
                        if(y==null){
                            y=prev;
                        }
                    }//交换
                    prev=root;
                    root=root.right;
                }
            }
            if(x!=null && y!=null) {
                int t = x.val;
                x.val = y.val;
                y.val = t;
            }
        }
    }

morris资料查询:

力扣99题:99. 恢复二叉搜索树 - 力扣(LeetCode)

左神讲解:https://www.bilibili.com/video/BV1Yt421K7Yu?t=1861.6

相关推荐
Zevalin爱灰灰2 小时前
现代密码学 第二章——流密码【下】
算法·密码学
MY_TEUCK4 小时前
【Java 后端】SpringBoot 登录认证与会话跟踪实战(JWT + Filter/Interceptor)
java·开发语言·spring boot
飞Link4 小时前
大模型长文本的“救命稻草”:深度解析 TurboQuant 与 KV Cache 压缩技术
算法
今天长肉了吗4 小时前
银行风控项目踩坑实录:指标跑了6小时,风险评分全挂了
java
随读手机4 小时前
多式联运信息交互平台完整方案(2026版)
java·ai·eclipse·云计算·区块链
郝学胜-神的一滴4 小时前
深度学习优化核心:梯度下降与网络训练全解析
数据结构·人工智能·python·深度学习·算法·机器学习
Je1lyfish5 小时前
CMU15-445 (2025 Fall/2026 Spring) Project#3 - QueryExecution
linux·c语言·开发语言·数据结构·数据库·c++·算法
许彰午5 小时前
03-二叉树——从递归遍历到非递归实现
java·算法
nj01285 小时前
Spring 循环依赖详解:三级缓存、早期引用、AOP 代理与懒加载
java·spring·缓存
Brilliantwxx5 小时前
【C++】 vector(代码实现+坑点讲解)
开发语言·c++·笔记·算法