Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?

使用O(n)空间的话可以直接中序遍历来找问题节点。

如果是O(1)空间的话,基本上就只能是原地操作了。

这里介绍一个Morris Inorder Traversal。可以实现:

1. 如果当前节点有左子树,那么找到左子树的最右节点并把它右指针指向当前节点。当前节点转移到其左节点。

2. 如果左子树的最右节点已经指向了当前节点(之前已经遍历过左子树),那么还原最右节点的右指针为null, 输出当前节点,当前节点转移到其右节点。

3. 如果当前节点没有左子树,那么直接输出当前节点并将其转移到右节点。

写成代码如下:

     public void recoverTree(TreeNode root) {
TreeNode cur = root;
while(cur!=null) {
if(cur.left!=null) {
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 {
temp.right=null;
//print
cur=cur.right;
}
}
else {
//print
cur=cur.right
}
}
}
}

结合这道题,只需要在print的地方添加代码即可。

只存在一处错误,遍历时可能出现两种情况:

1. 发现一次原先节点值比当前节点值大,例如:(1, 4, 3, 7, 9)这时只有对调这两个节点值即可。

2. 发现两次原先节点值比当前节点值大,例如: (1, 9, 4, 5, 3, 10)这时需要对调第一次的原先节点值和第二次的当前节点值。

使用两个TreeNode wrong1, wrong2记录这两个错误节点,如果是第一次发现原先节点比当前节点值大的错误,则wrong1置为原先节点,wrong2置为当前节点。如果又发现一次,则只更改wrong2.

注意原先节点pre和当前节点cur的关系,只有cur即将挪向右节点之前才将pre置为cur. (因为cur挪向左节点是第一次遍历左子树,仅仅用来连接,第二次遍历才输出)

完整代码如下:

     public void recoverTree(TreeNode root) {
TreeNode cur = root;
TreeNode pre = null;
TreeNode wrong1 = null;
TreeNode wrong2 = null;
while(cur!=null) {
if(cur.left!=null) {
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 {
temp.right=null;
//print
if(pre!=null && pre.val>cur.val) {
if(wrong1==null)
wrong1=pre;
wrong2 = cur;
}
pre = cur;
cur=cur.right;
}
}
else {
//print
if(pre!=null && pre.val>cur.val) {
if(wrong1==null)
wrong1=pre;
wrong2 = cur;
}
pre = cur;
cur=cur.right;
}
}
int t = wrong1.val;
wrong1.val = wrong2.val;
wrong2.val = t;
}

[Leetcode][JAVA] Recover Binary Search Tree (Morris Inorder Traversal)的更多相关文章

  1. [LeetCode] 99. Recover Binary Search Tree(复原BST) ☆☆☆☆☆

    Recover Binary Search Tree leetcode java https://leetcode.com/problems/recover-binary-search-tree/di ...

  2. 【leetcode】Recover Binary Search Tree

    Recover Binary Search Tree Two elements of a binary search tree (BST) are swapped by mistake. Recove ...

  3. leetcode 99 Recover Binary Search Tree ----- java

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  4. Java for LeetCode 099 Recover Binary Search Tree

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  5. [LeetCode] 99. Recover Binary Search Tree 复原二叉搜索树

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  6. leetcode@ [173] Binary Search Tree Iterator (InOrder traversal)

    https://leetcode.com/problems/binary-search-tree-iterator/ Implement an iterator over a binary searc ...

  7. [leetcode]99. Recover Binary Search Tree恢复二叉搜索树

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  8. LeetCode 1008. Construct Binary Search Tree from Preorder Traversal

    原题链接在这里:https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/ 题目: Retu ...

  9. 第五周 Leetcode 99. Recover Binary Search Tree (HARD)

    Leetcode99 给定一个 二叉搜索树,其中两个节点被交换,写一个程序恢复这颗BST. 只想到了时间复杂度O(n)空间复杂度O(h) h为树高的解法,还没想到空间O(1)的解法. 交换的情况只有两 ...

随机推荐

  1. linux命令(4):mkdir命令

    linux mkdir 命令 用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 1.命令格式: mkdir [选项] 目录... 2.命 ...

  2. js 两数相减

    var SecondPrice = document.getElementById("txtSecondPrice");  //秒杀价            var MarketP ...

  3. Codeforces 586D. Phillip and Trains 搜索

    D. Phillip and Trains time limit per test: 1 second memory limit per test :256 megabytes input: stan ...

  4. java socket 网络编程常见异常

    1.java.net.SocketTimeoutException 这个异常比较常见,socket超时.一般有2个地方会抛出这个,一个是connect的时候,这个超时参数由connect(Socket ...

  5. php框架制做笔记

    在学习完基础之后,最好的提高方式是做一个自己的框架,因为框架会用到各个知识点,在制做过程中,复习,巩固,提高. 在框架中,因为是单入口,整个脚本运行时都存在的变量我们应该设为静态变量,这样它在每个地方 ...

  6. 三维模型2.5D轮廓提取及遮挡部分的剔除

    轮廓提取相对容易,只需在2.5D渲染视角下,导出模型的顶点坐标以及基于视角的消隐后的三角形面,将三角面投影后合并就可得到轮廓,轮廓坐标基于2.5d图的基准坐标换算就得到.提取轮廓的在我另外一篇文章中有 ...

  7. c#输出、输入

    //输出 Console.WriteLine("这是一行文字");  自动回车的. Console.Write("Hello world");  不带回车的. ...

  8. EAA脚本语言0.2

    对上一版的改进.IL生成问题大部分解决了. 运行效果 脚本源码 #using "System"; #using "System.Drawing"; #using ...

  9. DIV+CSS常用的网页布局代码

    单行一列以下是引用片段:body { margin: 0px; padding: 0px; text-align: center; }#content { margin-left:auto; marg ...

  10. 【转】Crontab定时任务配置

    原文出处:http://www.cnblogs.com/kerrycode/p/3238346.html CRONTAB概念/介绍 crontab命令用于设置周期性被执行的指令.该命令从标准输入设备读 ...