leetcode -- 99. Recover Binary Search Tree

题目描述

题目难度:Hard

Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.
在这里插入图片描述
在这里插入图片描述
Follow up:

A solution using O(n) space is pretty straight forward.
Could you devise a constant space solution?

AC代码1

对一个BST进行中序遍历,结果是一个递增的序列。如果一个BST两个结点交换了,那么中序遍历的结果中对应结点的值也会交换。如第二个例子中,Input 中树的中序遍历为:1 3 2 4;
Output中树的中序遍历为1 2 3 4,是一个递增序列。对比发现 2 和 3发生了交换。其实就是交换两个数字的位置,使得一个序列成为递增序列。算法步骤如下:

  • 求出原始树的中序遍历序列
  • 求出遍历序列中两个数字,使得交换这两个数字可以使得序列递增有序
  • 交换原始树中两个节点的值
    时间复杂度:O(n)
    空间复杂度:O(n)
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public void recoverTree(TreeNode root) {
        if(root == null) return;
        List<Integer> list = new ArrayList<>();
        inOrder(root, list);
        changeNode(root, list);
    }
    
    private void inOrder(TreeNode root, List<Integer> list){
        if(root == null) return;
        inOrder(root.left, list);
        list.add(root.val);
        inOrder(root.right, list);
    }
    
    private void changeNode(TreeNode root, List<Integer> list){
        List<Integer> copyList = new ArrayList<>(list);
        Collections.sort(copyList);
        int n1 = 0, n2 = 0, k = 0;
        for(int i = 0;i < list.size();i++){
            if(list.get(i) != copyList.get(i)) 
                if(k == 0) {
                    n1 = list.get(i);
                    k++;
                }
            else n2 = list.get(i);
           // 1 2 4 5 3;
        }
        changeNodeCore(root, n1, n2);
    }
    
    private void changeNodeCore(TreeNode root, int n1, int n2){
        if(root == null) return;
        if(root.val == n1) root.val =n2;
        else if(root.val == n2) root.val = n1;
        changeNodeCore(root.left, n1, n2);
        changeNodeCore(root.right, n1, n2);
    }
}

AC代码2

对树进行中序遍历,在遍历过程中如果发现上一个节点的值大于当前节点的值,则说明上一个节点是被交换了的。一共会有两个节点会发生上述的问题,最后交换这两个节点的值。

class Solution {
   private TreeNode first;//第一个位置不对的节点
    private TreeNode second;//第二个位置不对的节点
    private TreeNode last = new TreeNode(Integer.MIN_VALUE);//记录上一个root节点,和这次比较大小

    public void recoverTree(TreeNode root) {
        if(root == null){
            return;
        }
       
        inorder(root); //利用中序遍历找出两个位置不对的节点
        swap(first, second);//交换两个位置不对的节点的值
    }
   
    private void inorder(TreeNode root){
        if(root == null){
            return;
        }
        inorder(root.left);
        if(first == null && last.val > root.val){
            first = last;
        }
        if(first != null && last.val > root.val){
            second = root;
        }
        last = root;//滚动节点法
        inorder(root.right);
    }
   
    private void swap(TreeNode n1, TreeNode n2){
        int temp = n1.val;
        n1.val = n2.val;
        n2.val = temp;
    }
}

猜你喜欢

转载自blog.csdn.net/tkzc_csk/article/details/88639540