个人记录-LeetCode 99. Recover Binary Search Tree

问题:
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?

这个问题场景是:
二叉搜索树中,节点的值存在问题,在不改变树结构的前提下,修复该二叉搜索树。


代码示例:
1、O(n) space的解法
这种解法比较简单,主要的依据是:
正常的二叉搜素树,按照中序遍历后,
节点的值应该是按照从小到大的顺序排列的。

按照这种思路,可以得到如下的解法:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public void recoverTree(TreeNode root) {
        List nodeList = new ArrayList<>();

        //先中序遍历
        inOrder(root, nodeList);

        //得到当前的节点值
        int[] values = new int[nodeList.size()];
        for (int i = 0; i < nodeList.size(); ++i) {
            values[i] = nodeList.get(i).val;
        }

        //重新排序
        Arrays.sort(values);

        //将排序后的值赋给节点
        for (int i = 0; i < nodeList.size(); ++i) {
            nodeList.get(i).val = values[i];
        }
    }

    //中序排序主要就用到了递归
    //先左子树;然后中间节点;再右子树即可
    private void inOrder(TreeNode root, List rst) {
        if (root == null) {
            return;
        }

        inOrder(root.left, rst);

        rst.add(root);

        inOrder(root.right, rst);
    }
}

2、上述方法的改进
实际上在中序遍历时,我们并不需要记录所有节点的信息,
仅保留出现问题的节点即可。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    //prev记录遍历的前一个节点
    //first记录出现问题的第一个节点
    //second记录出现问题的第二个节点
    TreeNode prev, first, second;

    public void recoverTree(TreeNode root) {
        //依然中序遍历节点
        inOrder(root);

        //如果找到出现问题的两个节点,则交换这两个节点的值
        if (first != null && second != null) {
            int tmp = first.val;
            first.val = second.val;
            second.val = tmp;
        }
    }

    private void inOrder(TreeNode root) {
        if (root == null) {
            return;
        }

        inOrder(root.left);


        if (prev != null) {
            //前一个节点的值大于当前节点
            //说明出现问题
            if (prev.val > root.val) {

                //如果第一次遇到这种情况,那么第一个出错的节点就是当前的prev
                if (first == null) {
                    first = prev;
                }

                //第一次时,第二个节点记录为root
                //即假设出错的两个节点“紧挨着”

                //若第二次重新进入该分支
                //则出错的两个节点有“距离”,此时第二出错节点为当前的root
                second = root;
            }
        }

        //prev永远记录前一个节点
        prev = root;

        inOrder(root.right);
    }
}

你可能感兴趣的:(LeetCode,LeetCode练习记录)