【Leecode】Leecode刷题之路第99天之恢复二叉搜索树

news2025/1/6 20:35:32

题目出处

99-恢复二叉搜索树-题目出处

题目描述

在这里插入图片描述
在这里插入图片描述

个人解法

思路:

todo

代码示例:(Java)

todo

复杂度分析

todo

官方解法

99-恢复二叉搜索树-官方解法

方法1:显式中序遍历

思路:

在这里插入图片描述

代码示例:(Java)

@Data
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;
    }
}

public class Solution1 {
    public void recoverTree(TreeNode root) {
        List<Integer> nums = new ArrayList<Integer>();
        inorder(root, nums);
        int[] swapped = findTwoSwapped(nums);
        recover(root, 2, swapped[0], swapped[1]);
    }

    public void inorder(TreeNode root, List<Integer> nums) {
        if (root == null) {
            return;
        }
        inorder(root.left, nums);
        nums.add(root.val);
        inorder(root.right, nums);
    }

    public int[] findTwoSwapped(List<Integer> nums) {
        int n = nums.size();
        int index1 = -1, index2 = -1;
        for (int i = 0; i < n - 1; ++i) {
            if (nums.get(i + 1) < nums.get(i)) {
                index2 = i + 1;
                if (index1 == -1) {
                    index1 = i;
                } else {
                    break;
                }
            }
        }
        int x = nums.get(index1), y = nums.get(index2);
        return new int[]{x, y};
    }

    public void recover(TreeNode root, int count, int x, int y) {
        if (root != null) {
            if (root.val == x || root.val == y) {
                root.val = root.val == x ? y : x;
                if (--count == 0) {
                    return;
                }
            }
            recover(root.right, count, x, y);
            recover(root.left, count, x, y);
        }
    }


}

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉搜索树的节点数。中序遍历需要 O(N) 的时间,判断两个交换节点在最好的情况下是 O(1),在最坏的情况下是 O(N),因此总时间复杂度为 O(N)。
  • 空间复杂度:O(N)。我们需要用 nums 数组存储树的中序遍历列表。

方法2:隐式中序遍历

思路:

在这里插入图片描述
在这里插入图片描述

代码示例:(Java)

public class Solution2 {
    public void recoverTree(TreeNode root) {
        Deque<TreeNode> stack = new ArrayDeque<TreeNode>();
        TreeNode x = null, y = null, pred = null;

        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            if (pred != null && root.val < pred.val) {
                y = root;
                if (x == null) {
                    x = pred;
                } else {
                    break;
                }
            }
            pred = root;
            root = root.right;
        }

        swap(x, y);
    }

    public void swap(TreeNode x, TreeNode y) {
        int tmp = x.val;
        x.val = y.val;
        y.val = tmp;
    }


}

复杂度分析

  • 时间复杂度:最坏情况下(即待交换节点为二叉搜索树最右侧的叶子节点)我们需要遍历整棵树,时间复杂度为 O(N),其中 N 为二叉搜索树的节点个数。
  • 空间复杂度:O(H),其中 H 为二叉搜索树的高度。中序遍历的时候栈的深度取决于二叉搜索树的高度。

方法3:Morris 中序遍历

思路:

在这里插入图片描述
在这里插入图片描述

代码示例:(Java)

public class Solution3 {
    public void recoverTree(TreeNode root) {
        TreeNode x = null, y = null, pred = null, predecessor = null;

        while (root != null) {
            if (root.left != null) {
                // predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
                predecessor = root.left;
                while (predecessor.right != null && predecessor.right != root) {
                    predecessor = predecessor.right;
                }

                // 让 predecessor 的右指针指向 root,继续遍历左子树
                if (predecessor.right == null) {
                    predecessor.right = root;
                    root = root.left;
                }
                // 说明左子树已经访问完了,我们需要断开链接
                else {
                    if (pred != null && root.val < pred.val) {
                        y = root;
                        if (x == null) {
                            x = pred;
                        }
                    }
                    pred = root;

                    predecessor.right = null;
                    root = root.right;
                }
            }
            // 如果没有左孩子,则直接访问右孩子
            else {
                if (pred != null && root.val < pred.val) {
                    y = root;
                    if (x == null) {
                        x = pred;
                    }
                }
                pred = root;
                root = root.right;
            }
        }
        swap(x, y);
    }

    public void swap(TreeNode x, TreeNode y) {
        int tmp = x.val;
        x.val = y.val;
        y.val = tmp;
    }


}

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉搜索树的高度。Morris 遍历中每个节点会被访问两次,因此总时间复杂度为 O(2N)=O(N)。
  • 空间复杂度:O(1)。

考察知识点

1.二叉树的中序遍历

收获

Gitee源码位置

99-恢复二叉搜索树-源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271073.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用AI优化SEO提升关键词排名的有效策略

内容概要 随着数字化时代的到来&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;在各类企业的在线营销战略中占据了越来越重要的位置。而人工智能&#xff08;AI&#xff09;技术的迅速发展为SEO带来了新的机遇和挑战。通过智能化的数据分析和智能内容生成&#xff0c;企…

YOLO分割数据集转化(json转TXT)

一、数据集转化 import json import os from tqdm import tqdm import glob import os.path as ospdef json_to_txt(jsonfilePath, resultDirPath):"""jsonfilePath: labelme标注好的*.json文件所在文件夹resultDirPath: 转换好后的*.txt保存文件夹""…

中建海龙:科技助力福城南产业片区绿色建筑发展

在快速发展的城市化进程中&#xff0c;绿色建筑以其环保、节能、可持续的特点日益受到重视。作为建筑工业化领域的领军企业&#xff0c;中建海龙科技有限公司&#xff08;简称“中建海龙”&#xff09;凭借其卓越的科技实力和创新举措&#xff0c;在推动绿色建筑发展方面做出了…

基于深度学习算法的AI图像视觉检测

基于人工智能和深度学习方法的现代计算机视觉技术在过去10年里取得了显著进展。如今&#xff0c;它被广泛用于图像分类、人脸识别、图像中物体的识别等。那么什么是深度学习&#xff1f;深度学习是如何应用在视觉检测上的呢&#xff1f; 什么是深度学习&#xff1f; 深度学习是…

大数据技术-Hadoop(四)Yarn的介绍与使用

目录 一、Yarn 基本结构 1、Yarn基本结构 2、Yarn的工作机制 二、Yarn常用的命令 三、调度器 1、Capacity Scheduler&#xff08;容量调度器&#xff09; 1.1、特点 1.2、配置 1.2.1、yarn-site.xml 1.2.2、capacity-scheduler.xml 1.3、重启yarn、刷新队列 测试 向hi…

python修改ppt中的文字部分及插入图片

批量修改ppt中的某个模块&#xff0c;或者批量制作奖状等场景会用到&#xff1b; import os import pandas as pd from pptx import Presentation from pptx.util import Inchesfilepath/Users/kangyongqing/Documents/kangyq/202303/分析模版/批量制作/file1时段预警_副本.pp…

数据库新建用户后(Host:%),报错:localhost无法连接

存在问题 在给数据库&#xff08;MySQL、MariaDB等&#xff09;创建了新的用户名&#xff08;eg&#xff1a;maxscale&#xff09;后&#xff0c;无法使用新用户名登录&#xff0c;并报如下错误&#xff1a;ERROR 1045 (28000): Access denied for user maxscalelocalhost (us…

《机器学习》——逻辑回归(下采样)

文章目录 什么是下采样&#xff1f;为什么在逻辑回归中要使用下采样&#xff1f;使用下采样和不使用下采样的区别实例1、实例内容2、实例步骤 什么是下采样&#xff1f; 下采样&#xff08;Down - Sampling&#xff09;是一种数据处理技术&#xff0c;主要用于处理数据集中不同…

ACM算法模板

ACM算法模板 起手式基础算法前缀和与差分二分查找三分查找求极值分治法&#xff1a;归并排序 动态规划基本线性 d p dp dp最长上升子序列I O ( n 2 ) O(n ^ 2) O(n2)最长上升子序列II O ( n l o g n ) O(nlogn) O(nlogn) 贪心二分最长公共子序列 背包背包求组合种类背包求排列…

Scala_【5】函数式编程

第五章 函数式编程函数和方法的区别函数声明函数参数可变参数参数默认值 函数至简原则匿名函数高阶函数函数作为值传递函数作为参数传递函数作为返回值 函数闭包&柯里化函数递归控制抽象惰性函数友情链接 函数式编程 面向对象编程 解决问题时&#xff0c;分解对象&#xff…

CSS 学习之正确看待 CSS 世界里的 margin 合并

一、什么是 margin 合并 块级元素的上外边距(margin-top)与下外边距(margin-bottom)有时会合并为单个外边距&#xff0c;这样的现象称为“margin 合并”。从此定义上&#xff0c;我们可以捕获两点重要的信息。 块级元素&#xff0c;但不包括浮动和绝对定位元素&#xff0c;尽…

Golang的代码质量分析工具

Golang的代码质量分析工具 一、介绍 作为一种高效、简洁、可靠的编程语言&#xff0c;被越来越多的开发者所喜爱和采用。而随着项目规模的增长和团队人员的扩大&#xff0c;代码质量的管理变得尤为重要。为了保障代码的可维护性、健壮性和可扩展性&#xff0c;我们需要借助代码…

鸿蒙元服务 口袋管家(从0到1) ——准备工作

达到的效果图 如何创建元服务&#xff1f; 如下&#xff1a; 鸿蒙如何创建元服务-元服务是什么&#xff1f;和App的关系&#xff1f;&#xff08;保姆级步骤&#xff09;_鸿蒙元服务-CSDN博客 开始创建包 Bill 里面创建两个page页面 分别是 BillAddPage 和 BillIndexPag…

轻量型web组态软件

体验地址&#xff1a;http://www.hcy-soft.com 随着互联网、物联网技术的快速发展&#xff0c;BY组态基于多年研发积累和私有部署实践打磨、以及对业务场景的深入理解&#xff0c;推出了适用于物联网应用场景的轻量型web组态软件。 该产品采用 B/S 架构&#xff0c;提供 web …

Linux C/C++编程-获得套接字地址、主机名称和主机信息

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com…

SweetAlert2 - 漂亮可定制的 JavaScript 弹窗

https://sweetalert2.github.io/ https://github.com/sweetalert2/sweetalert2 安装&#xff1a; npm install sweetalert2封装&#xff1a; import Swal from sweetalert2/dist/sweetalert2.js import sweetalert2/src/sweetalert2.scss/*** * param {string} icon - ico…

Android布局layout的draw简洁clipPath实现圆角矩形布局,Kotlin

Android布局layout的draw简洁clipPath实现圆角矩形布局&#xff0c;Kotlin 通常&#xff0c;如果要把一个相对布局&#xff0c;FrameLayout&#xff0c;或者线性布局等这样的布局变成具有圆角或者圆形的布局&#xff0c;需要增加一个style&#xff0c;给它设置圆角&#xff0c;…

PHP如何删除数组中的特定值?

php 中删除数组特定值的方法有三种&#xff1a;unset()&#xff1a;直接删除指定索引的值&#xff0c;但会保留数组索引结构和未删除元素&#xff0c;适合小数组。array_filter()&#xff1a;根据自定义回调函数筛选数组元素&#xff0c;返回一个新数组&#xff0c;原数组不变&…

啤酒风味塑造的关键因素——麦汁煮沸

在探索啤酒酿造的工艺过程中&#xff0c;我们发现每一个细微的步骤都对最终的口感和风味产生着不可忽视的影响。今天&#xff0c;让我们深入探讨一个关键环节——麦汁煮沸&#xff0c;以及其中至关重要的概念“煮沸强度”。 何谓煮沸强度&#xff1f;它又如何左右麦汁的品质&a…

unity开发之shader 管道介质流动特效

效果 shader graph 如果出现下面的效果&#xff0c;那是因为你模型的问题&#xff0c;建模做贴图的时候没有设置好UV映射&#xff0c;只需重新设置下映射即可