
思路很简单,因为只有两个节点互换了,只需要找到这两个节点,再换回来即可
可是怎么找到这两个节点呢?
方法一
直接中序遍历得到一个数组arr1,然后新建一个数组arr2,copy arr1,将其排序
对比arr1和arr2,很容易就能找到不同的两个节点,互换即可
时间复杂度为o(nlogn)
class Solution {
public void recoverTree(TreeNode root) {
List<Integer> sorted = new ArrayList<>();
inorder(root, sorted);
List<Integer> tmp = new ArrayList<>(sorted);
Collections.sort(tmp);
int[] pair = new int[2];
int count = 0;
for(int i=0; i<sorted.size(); i++){
if(sorted.get(i) != tmp.get(i)){
pair[count++] = sorted.get(i);
}
}
dfs(root, pair);
}
private void inorder(TreeNode root, List<Integer> sorted){
if(root == null)
return;
inorder(root.left, sorted);
sorted.add(root.val);
inorder(root.right, sorted);
}
private void dfs(TreeNode root, int[] tmp){
if(root == null)
return;
if(root.val == tmp[0]){
root.val = tmp[1];
}else if(root.val == tmp[1])
root.val = tmp[0];
dfs(root.left, tmp);
dfs(root.right, tmp);
}
}
方法二
只用一个中序遍历,first记录第一个错误节点,second同理
第一个出错的节点,肯定是他的值比后一个节点的值大
第二个出错的节点,肯定是它的值比前一个节点的值小
按照这个规律,就可以找到这两个出错的节点
class Solution {
TreeNode first = null;
TreeNode second = null;
TreeNode prev = new TreeNode(Integer.MIN_VALUE);
public void recoverTree(TreeNode root) {
inorder(root);
int tmp = first.val;
first.val = second.val;
second.val = tmp;
}
private void inorder(TreeNode root){
if(root == null)
return;
inorder(root.left);
if(first == null && prev.val > root.val){
first = prev;
}
if(first != null && prev.val > root.val){
second = root;
}
prev = root;
inorder(root.right);
}
}