当前位置: 首页 > article >正文

力扣 【99. 恢复二叉搜索树】Java题解(二叉树的 Morris 遍历)

题目链接

Morris遍历

递归和迭代遍历,不管是前序中序还是后续,空间复杂度都是O(n)(递归是因为隐式调用栈的开销)。
而Morris遍历可以做到空间复杂度是O(1)。
思路就是节点的前序节点的右指针指向该节点,来保证可以通过前序节点找到后一个节点。
代码如下:
在这里插入图片描述

过程图如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路

通过Morris遍历,我们就可以做到O(1)的空间复杂度中序遍历这个二叉树。
然后在中序遍历的序列找到错误的节点的方法是找到降序的段。
这里借用了一个视频的一张图:我们可以发现如果只有一个降序段,那就交换这两个节点;如果有两个降序段,就交换第一个段的左边节点和第二个段的右边节点即可。
在这里插入图片描述

代码

class Solution {
    TreeNode x,y; //要交换的两个节点
    TreeNode preNode; //前一个节点
    boolean flag = false; //判断是第一次还是第二次降序的标志
    public void recoverTree(TreeNode root) {
        TreeNode cur = root;
        while(cur != null){
            if(cur.left == null){
                check(preNode,cur);
                preNode = cur;
                cur = cur.right;
            }else{
                TreeNode temp = cur.left;
                while(temp.right != null && temp.right != cur){
                    temp = temp.right;
                }
                if(temp.right == null){
                    temp.right = cur;
                    cur = cur.left;
                }else{
                    check(preNode,cur);
                    temp.right = null;
                    preNode = cur;
                    cur = cur.right;
                }
            }
        }
        swap(x,y);
    }
    public void swap(TreeNode x,TreeNode y){
        int t = x.val;
        x.val = y.val;
        y.val = t;
    }
    public void check(TreeNode preNode,TreeNode cur){
        if(preNode != null && preNode.val > cur.val){
            if(!flag){
                x = preNode;
                y = cur;
                flag = true;
            }else{
                y = cur;
            }
        }
    }
}

相关题目:
https://leetcode.cn/problems/find-mode-in-binary-search-tree

参考:
https://mp.weixin.qq.com/s?__biz=MzI5ODA5NTgyMw==&mid=2247483907&idx=1&sn=0244e1276e31e0ee55a42601158e7481&chksm=ecaa47a3dbddceb5c49e67fbbfd8f2d4ddd1f902e83bdc6114068a7165cf937281eebf35e4c4&token=1538071990&lang=zh_CN#rd


http://www.kler.cn/a/523410.html

相关文章:

  • WebSocket 详解:全双工通信的实现与应用
  • 【C++】特殊类设计、单例模式与类型转换
  • ZZNUOJ(C/C++)基础练习1011——1020(详解版)
  • 分布式版本控制系统:Git
  • SpringBoot 中的测试jar包knife4j(实现效果非常简单)
  • 每日 Java 面试题分享【第 14 天】
  • Vue.js 配合 Vue Router 使用 Vuex
  • 【漫话机器学习系列】065.梯度(Gradient)
  • 数组at()方法:负索引的救赎与JavaScript标准化之路
  • jemalloc 5.3.0的tsd模块的源码分析
  • 关于存储磁盘固件版本:打破版本一致性迷思
  • Python 函数魔法书:基础、范例、避坑、测验与项目实战
  • 大模型概述
  • 第一个3D程序!
  • 在虚拟机里运行frida-server以实现对虚拟机目标软件的监测和修改参数(一)(android Google Api 35高版本版)
  • 借DeepSeek-R1东风,开启创业新机遇
  • nosql mysql的区别
  • SQL server 数据库使用整理
  • 实时数据处理与模型推理:利用 Spring AI 实现对数据的推理与分析
  • 29. 【.NET 8 实战--孢子记账--从单体到微服务】--项目发布
  • 如何保证缓存与数据库的数据一致性?
  • 《多线程基础之条件变量》
  • @RestControllerAdvice 的作用
  • 【信息系统项目管理师-选择真题】2010下半年综合知识答案和详解
  • C#面试常考随笔5:简单讲述下反射
  • 腾讯云开发提供免费GPU服务