Morris遍历(力扣第99题)

假设有一个树:

a

/ \

b c

/ \ / \

d e f g

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

Morris遍历的优点:

空间复杂度为 O(1)

Morris遍历的规则:

  • 无左子树 :访问 root,root 向右走

  • 有左子树:

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

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

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

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

相关推荐
?abc!8 分钟前
(数组)581. 最短无序连续子数组
数据结构·算法·leetcode
AI人工智能+电脑小能手11 分钟前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务
paopaokaka_luck2 小时前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
2301_32241428042 小时前
springboot农产品交易平台的设计与实现08055-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·spring boot·redis·mysql·tomcat·maven·mybatis
小郎君6583 小时前
MPTT树复选框的半选状态:一棵百万节点树从递归到计数器,再到区间覆盖
算法
酌沧3 小时前
MemT让记忆成为模型内生能力
jvm·人工智能·算法
hold?fish:palm3 小时前
40 二叉树的直径
c++·leetcode
考虑考虑3 小时前
JDK26的JEP 500属性
java·后端·java ee
LMT流氓兔3 小时前
第五单元——第十二课:把脚本整理成项目
java·数据库·python·langchain·1024程序员节
yuniko-n3 小时前
【JUC】四种内存屏障示例
java·1024程序员节