package tree;
/**
 * 给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
 *
 * 进阶:使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?
 *
 *
 * @author Tang
 */
public class RecoverTree {
    /**
     * 被揪出来的不符合大小顺序的节点
     */
    TreeNode temp;
    /**
     * 节点中val有可能是负数
     */
    int max = Integer.MIN_VALUE;
    /**
     * 大体思路: 按照中序大小遍历
     * 执行jiu()方法,揪出中序遍历(最后一个)比前一个节点值小的节点,赋值给temp
     * 判断temp是不是null,如果是null说明没揪出来 说明顺序已经正常了
     * 执行cha()方法,中序遍历,找到第一个比temp值大的节点,与temp值交换
     *
     *
     * @param root
     */
    public void recoverTree(TreeNode root) {
        if(root == null){
            return;
        }
        while(true){
            jiu(root);
            if(temp == null){
                break;
            }
            cha(root);
        }
    }
    /**
     * 中序遍历 按从小到大排列,不符合的节点揪出来,赋值给temp
     * 判断条件就是从第一个节点开始,比max值大就算符合大小,并赋值给max 用来判断下一个节点
     *
     * @param node 当前节点
     * @return
     */
    public void jiu(TreeNode node){
        if(node == null){
            return;
        }
        jiu(node.left);
        if(node.val < max){
            temp = node;
        }
        max = Math.max(max, node.val);
        jiu(node.right);
    }
    /**
     * 把揪出来的temp交换到理想位置
     * 遇到第一个比temp节点的值大的节点 交换值
     * 交换成功,temp置空,max置Integer.MIN_VALUE
     *
     * @return 本次是否交换成功
     */
    public boolean cha(TreeNode node){
        if(node == null){
            return false;
        }
        if(cha(node.left)){
            return true;
        }
        if(node.val > temp.val){
            int tem = node.val;
            node.val = temp.val;
            temp.val = tem;
            temp = null;
            max = Integer.MIN_VALUE;
            return true;
        }
        return cha(node.right);
    }
    public static void main(String[] args) {
        TreeNode node1 = new TreeNode(5);
        TreeNode node2 = new TreeNode(3);
        TreeNode node3 = new TreeNode(9);
        TreeNode node4 = new TreeNode(-214748648);
        TreeNode node5 = new TreeNode(2);
        TreeNode node6 = new TreeNode(6);
        node1.left = node2;
        node1.right = node3;
        node2.left = node4;
        node2.right = node5;
        new RecoverTree().recoverTree(node1);
    }
}