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

相关推荐
黄敬峰7 分钟前
面试必刷:从JS底层包装类到双指针,彻底搞懂字符串与回文算法
算法
MacroZheng20 分钟前
短短几天,暴涨2.8万Star!又一款编程神器开源!
java·人工智能·后端
SamDeepThinking33 分钟前
函数式编程:用BiFunction消除多类型分支的代码重复
java·后端·面试
地平线开发者10 小时前
J6B vio scenario sample
算法
Flittly18 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了18 小时前
Java 生成二维码解决方案
java·后端
BothSavage1 天前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn1 天前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
人活一口气1 天前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot