99.recover-binary-search-tree


99. 恢复二叉搜索树

二叉搜索树中的两个节点被错误地交换。

请在不改变其结构的情况下,恢复这棵树。

示例 1:

输入: [1,3,null,null,2]

   1
  /
 3
  \
   2

输出: [3,1,null,null,2]

   3
  /
 1
  \
   2

示例 2:

输入: [3,1,4,null,null,2]

  3
 / \
1   4
   /
  2

输出: [2,1,4,null,null,3]

  2
 / \
1   4
   /
  3

进阶:

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

解法一

先做中序遍历,得到一个排序数组 查找排序数组中的元素,找到被交换的值 遍历树,交换元素

/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    private void inOrder(TreeNode root, List<Integer> nums) {
        if (root == null) return;
        inOrder(root.left, nums);
        nums.add(root.val);
        inOrder(root.right, nums);
    }

    private int[] findTwoSwapped(List<Integer> nums) {

        int x = -1, y = -1;
        for (int i = 0; i < nums.size() - 1; i++) {

            if (nums.get(i+1) < nums.get(i)) {
                y = nums.get(i+1);

                if (x == -1) x = nums.get(i);
                else break;
            }
        }
        return new int[]{x, y};
    }

    private void recover(TreeNode root, int count, int[] swapped) {

        if (root != null) {
            if (root.val == swapped[0] || root.val == swapped[1]) {
                root.val = root.val == swapped[0] ? swapped[1] : swapped[0];
                if (--count == 0) return;
            }
            recover(root.left, count, swapped);
            recover(root.right, count, swapped);
        }
    }

    public void recoverTree(TreeNode root) {

        List<Integer> nums = new ArrayList<>();
        inOrder(root, nums);

        int[] swapped = findTwoSwapped(nums);
        recover(root, 2, swapped);
    }
}

解法二

先写一个 Morris travesal

/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public void recoverTree(TreeNode root) {
        while(root != null) {
            if (root.left != null) {
                TreeNode temp = root.left;
                while(temp.right != null && temp.right != root) temp = temp.right;
                if (temp.right == null) {
                    temp.right = root;
                    root = root.left;
                } else {
                    temp.right = null;
                    // visit root.val
                    root = root.right;
                } 
            } else {
                // visit root.val
                root = root.right;
            }
        }
    }
}

加入逻辑

/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public void recoverTree(TreeNode root) {
        TreeNode first = null, second = null;
        TreeNode prev = new TreeNode(Integer.MIN_VALUE);
        while(root != null) {
            if (root.left != null) {
                TreeNode temp = root.left;
                while(temp.right != null && temp.right != root) temp = temp.right;
                if (temp.right == null) {
                    temp.right = root;
                    root = root.left;
                } else {
                    temp.right = null;
                    // visit root.val
                    if (prev.val > root.val && first == null) {
                        first = prev;
                    }
                    if (prev.val > root.val && first != null) {
                        second = root;
                    }
                    root = root.right;
                } 
            } else {
                // visit root.val
                if (prev.val > root.val && first == null) {
                    first = prev;
                }
                if (prev.val > root.val && first != null) {
                    second = root;
                }
                root = root.right;
            }
        }
        if (first !=null && second != null) {
            int temp = first.val;
            first.val = second.val;
            second.val = temp;
        }
    }
}