99. 恢复二叉搜索树

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

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

示例 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 使二叉搜索树有效。

 

class Solution {
    //第一个前置节点,排序二叉树,这里第一个点直接默认最小值
    TreeNode prev=new TreeNode(Integer.MIN_VALUE);
    TreeNode err1=null,err2=null;
    public void recoverTree(TreeNode root) {
      //根据题意知,是两个节点的位置错误了,所以有两种情况
        //1.相邻的两个节点顺序错了,2.不相邻的,不相邻的第一处肯定是前大后小,第二处是前小后大
        helper(root);
        int temp=err1.val;
        err1.val=err2.val;
        err2.val=temp;
    }
    //辅助函数
   //中序遍历对于排序二叉树就是有顺序的
    void helper(TreeNode root){
        if(root==null){
            return;
        }
        helper(root.left);
        //中序遍历代码
        //不满足前小后大,就说明这是一个错误点
        //根据楼主的图可以看出分为两种情况
        //其中第二幅图看出,不相邻的情况下第一处肯定是前大后小,第二处是前小后大,
        // 所以在第一个错误点是pre,第二个错误点是root,
        // 这同时也满足了如果这两个错误点相邻的(第一幅图)情况
        //这也就是为什么要用两个if的原因,而不是把他们写到一个if里
        if(prev.val>root.val&&err1==null) {
            err1=prev;
        }
        if(prev.val>root.val&&err1!=null) {
            err2=root;
        }
        //当前点用完,就更新前置点
        prev=root;
        helper(root.right);
    }
}
package code;

import java.util.Stack;
/*
 * 99. Recover Binary Search Tree
 * 题意:二叉搜索树中两个节点错位了,恢复二叉搜索树,用O(1)空间
 * 难度:Hard
 * 分类:Tree, Depth-first Search
 * 思路:只要记录错乱的节点就可以了,最后交换两个节点的值
 *      先序遍历  在print那个地方加上逻辑代码
 * Tips:
 */
public class lc99 {
    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) {
            val = x;
        }
    }

    TreeNode tn1 = null;
    TreeNode tn2 = null;
    public void recoverTree(TreeNode root) {
        inorder(root);
        int temp = tn1.val;
        tn1.val = tn2.val;
        tn2.val = temp;
    }

    public void inorder(TreeNode root){
        TreeNode pre = null;
        Stack<TreeNode> st = new Stack();
        while(root!=null || !st.isEmpty()){
            while(root!=null){
                st.add(root);
                root = root.left;
            }
            root = st.pop();
            if(pre!=null && pre.val>root.val && tn1==null)
                tn1 = pre;
            if(pre!=null && pre.val>root.val && tn1!=null)   //可能被执行多次  eg  3 2 1  tn2 先被赋值2 后被赋值1
                tn2 = root;
            pre = root;
            root = root.right;
        }
    }
}
原文地址:https://www.cnblogs.com/kpwong/p/14716530.html