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

leetcode99 恢复二叉搜索树

问题描述:
给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。

示例 1:
输入:root = [1,3,null,null,2]
输出:[3,1,null,null,2]
解释:3 不能是 1 的左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
示例 2:
输入:root = [3,1,4,null,null,2]
输出:[2,1,4,null,null,3]
解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。

提示:
树上节点的数目在范围 [2, 1000] 内
-231 <= Node.val <= 231 - 1

进阶:使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用 O(1) 空间的解决方案吗?

解题思路
二叉搜索树的特点是: 左子树<根结点<右子树。
所以采用中序遍历时,节点的值是升序的。
我们可以找出不符合升序的两个节点,将他们的值交换。
不符合升序的两个节点分别是:
第一次不满足升序的节点的前一个
第二次不满足升序的当前节点。

代码实现

    public static void recoverTree(TreeNode root) {
        if (root == null) {
            return;
        }
        Stack<TreeNode> sta = new Stack<TreeNode>();
        List<TreeNode> result = new ArrayList<TreeNode>();
        TreeNode p = root;
        while (p != null || !sta.isEmpty()) {
            if (p != null) {
                sta.push(p);
                p = p.left;
            } else {
                p = sta.pop();
                result.add(p);
                p = p.right;
            }
        }
        TreeNode preBad = null, lastBad = null;
        int preVal = result.get(0).val;
        for (int i = 1; i < result.size(); i++) {
            if (preBad == null) {
                if (result.get(i).val < preVal) {
                    preBad = result.get(i - 1);
                    lastBad = result.get(i);
                }
            } else {
                if (result.get(i).val < preVal) {
                    lastBad = result.get(i);
                }
            }
            preVal = result.get(i).val;
        }
        swap(preBad, lastBad);

    }

    private static void swap(TreeNode badNodeL, TreeNode badNodeR) {
        int t = badNodeL.val;
        badNodeL.val = badNodeR.val;
        badNodeR.val = t;
    }

对于中序遍历,我们可以省去额外的list空间,遍历时进行对比

class Solution {
    public void recoverTree(TreeNode root) {
      if (root == null) {
            return;
        }
        Stack<TreeNode> sta = new Stack<TreeNode>();
        TreeNode preBad = null, lastBad = null, pre = null;
        int preVal = Integer.MIN_VALUE;
        TreeNode p = root;
        while (p != null || !sta.isEmpty()) {
            if (p != null) {
                sta.push(p);
                p = p.left;
            } else {
                p = sta.pop();
                if (preBad == null) {
                    if (p.val < preVal) {
                        preBad = pre;
                        lastBad = p;
                    }
                } else {
                    if (p.val < preVal) {
                        lastBad = p;
                    }
                }
                pre = p;
                preVal = p.val;
                p = p.right;
            }
        }
        swap(preBad, lastBad);

    }

    private static void swap(TreeNode badNodeL, TreeNode badNodeR) {
        int t = badNodeL.val;
        badNodeL.val = badNodeR.val;
        badNodeR.val = t;
    }

}

http://www.kler.cn/news/335332.html

相关文章:

  • 基于微信小程序的健康管理系统(源码+定制+文档)
  • Python FastApi 实现签名验证
  • 上传本地项目到GitHub远程仓库(极简洁操作版)
  • 【2024版本】Mac/Windows IDEA安装教程
  • QT系统学习篇(2)- Qt跨平台GUI原理机制
  • 【玩转 JS 函数式编程_008】3.1.2 JavaScript 函数式编程筑基之:箭头函数——一种更流行的写法
  • 第十一章 缓存之更新/穿透/雪崩/击穿
  • CSS面试真题 part1
  • Nginx深度解析与实战应用
  • MATLAB与Git集成:实现高效版本控制的实践指南
  • TypeScript:装饰器
  • 前端中常用的几种单位写法及其解释
  • 猴子吃桃-C语言
  • 小程序使用echarts视图层会悬浮在所有视图之上问题原因
  • 原码、反码、补码极简理解
  • 详解JavaScript中把函数作为值
  • ThreeJS通过制作渐变光效贴图方式实现光柱效果
  • 基于SSM的电影院售票系统设计与实现
  • 【Python游戏开发】贪吃蛇游戏demo拓展
  • C# 非泛型集合基础:ArrayList与Hashtable的使用与注意事项