99. Recover Binary Search Tree

Posted apanda009

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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?

这道题是要求恢复一颗有两个元素调换错了的二叉查找树。一开始拿到可能会觉得比较复杂,其实观察出规律了就比较简单。主要还是利用二叉查找树的主要性质,就是中序遍历是有序的性质。那么如果其中有元素被调换了,意味着中序遍历中必然出现违背有序的情况。那么会出现几次呢?有两种情况,如果是中序遍历相邻的两个元素被调换了,很容易想到就只需会出现一次违反情况,只需要把这个两个节点记录下来最后调换值就可以;如果是不相邻的两个元素被调换了,举个例子很容易可以发现,会发生两次逆序的情况,那么这时候需要调换的元素应该是第一次逆序前面的元素,和第二次逆序后面的元素。比如1234567,1和5调换了,会得到5234167,逆序发生在52和41,我们需要把4和1调过来,那么就是52的第一个元素,41的第二个元素调换即可。如果是1和3调换了,会得到3214567,逆序发生在32和21,那么需要调换的是32的第一个元素,21的第二个元素。所以我们要做的就是把逆序的所有元素都依次存在一个ArrayList里面,不管是一次逆序还是两次,只需要把一头一尾的两个元素完成值交换,就好了。


搞清楚了规律就容易实现了,中序遍历寻找逆序情况,调换的第一个元素,永远是第一个逆序的第一个元素,而调换的第二个元素如果只有一次逆序,则是那一次的后一个,如果有两次逆序则是第二次的后一个。算法只需要一次中序遍历,所以时间复杂度是O(n),空间是栈大小O(logn)。

public class Solution {
    
    TreeNode firstElement = null;
    TreeNode secondElement = null;
    // The reason for this initialization is to avoid null pointer exception in the first comparison when prevElement has not been initialized
    TreeNode prevElement = new TreeNode(Integer.MIN_VALUE);
    
    public void recoverTree(TreeNode root) {
        
        // In order traversal to find the two elements
        traverse(root);
        
        // Swap the values of the two nodes
        int temp = firstElement.val;
        firstElement.val = secondElement.val;
        secondElement.val = temp;
    }
    
    private void traverse(TreeNode root) {
        
        if (root == null)
            return;
            
        traverse(root.left);
        
        // Start of "do some business", 
        // If first element has not been found, assign it to prevElement (refer to 6 in the example above)
        if (firstElement == null && prevElement.val >= root.val) {
            firstElement = prevElement;
        }
    
        // If first element is found, assign the second element to the root (refer to 2 in the example above)
        if (firstElement != null && prevElement.val >= root.val) {
            secondElement = root;
        }        
        prevElement = root;

        // End of "do some business"

        traverse(root.right);
}

  画图, 看中序遍历, 找规律, 画图, 回溯

这道题还是考察二叉树遍历,不过应用题目要求套了一个不同的外壳,需要我们利用二叉查找树的性质观察出规律之后才能求解

以上是关于99. Recover Binary Search Tree的主要内容,如果未能解决你的问题,请参考以下文章

99. Recover Binary Search Tree

LeetCode99 Recover Binary Search Tree

99. Recover Binary Search Tree

Leetcode 99. Recover Binary Search Tree

Leetcode 99. Recover Binary Search Tree

LeetCode OJ 99. Recover Binary Search Tree