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

相关推荐
daidaidaiyu2 小时前
一文学习入门 ThingsBoard 开源物联网平台
java·mqtt·spring
状元岐2 小时前
C#反射从入门到精通
java·javascript·算法
亚历克斯神2 小时前
Elasticsearch 全文搜索实战:构建企业级搜索引擎
java·spring·微服务
亚历克斯神2 小时前
Spring Boot 与 Elasticsearch 8.0 集成
java·spring·微服务
_深海凉_3 小时前
LeetCode热题100-除了自身以外数组的乘积
数据结构·算法·leetcode
Kk.08023 小时前
项目《基于Linux下的mybash命令解释器》(一)
前端·javascript·算法
星晨雪海3 小时前
Lombok 注解使用场景终极总结
java·数据库·mysql
SteveSenna4 小时前
Trossen Arm MuJoCo自定义1:改变目标物体
人工智能·学习·算法·机器人
yong99904 小时前
IHAOAVOA:天鹰优化算法与非洲秃鹫优化算法的混合算法(Matlab实现)
开发语言·算法·matlab