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

相关推荐
请为小H留灯16 小时前
IDEA / PyCharm 如何实现“一个项目一个窗口”?多项目并行开发设置
java·pycharm·intellij-idea·实战项目
khalil102016 小时前
代码随想录算法训练营Day-58 图论08 | 拓扑排序精讲、dijkstra(朴素版)精讲
c++·算法·图论·dijkstra·拓扑排序·prim·最短距离
苦逼的猿宝16 小时前
宠物咖啡馆平台的设计与实现(源码+论文)
java·毕业设计·springboot·计算机毕业设计
吃好睡好便好16 小时前
矩阵的乘法运算
数据结构·人工智能·学习·线性代数·算法·matlab·矩阵
Ricky055317 小时前
RF-DETR:实时检测变换器(transformers)的神经架构搜索(美国2025.12研究)
图像处理·人工智能·算法
程序员buddha17 小时前
Spring Boot框架,类注入成 Bean的方式
java·spring boot·后端
城管不管17 小时前
什么是Prompt?
android·java·数据库·语言模型·llm·prompt
AI大模型17 小时前
被AI抢饭碗的Java程序员,后来都怎样了?
java·后端·ai编程
苦逼的猿宝17 小时前
医院管理系统.(源码+论文)
java·毕业设计·springboot·计算机毕业设计
東雪木17 小时前
JVM 与 Java 内存模型 专属复习笔记
java·jvm·笔记·java面试