题目描述
题目难度: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;
}
}