请在不改变树的结构的情况下恢复这棵树。
备注;
用O(n)的空间解决这个问题的方法太暴力了,你能设计一个常数级空间复杂度的算法么?
输入: [1,3,null,null,2]
1 / 3 \ 2
输出: [3,1,null,null,2]
3 / 1 \ 2
/*
Morris中序遍历二叉树,空间复杂度O(1),耗时比较高。。没过测试,试了几个线下应该可以,
时间复杂度O(n),但是有些时间节点会遍历两次。
*/ import java.util.*;
public class Solution {
public void recoverTree(TreeNode root) {
TreeNode cur = root;
TreeNode mostRight;
TreeNode firstStrange=null;
TreeNode firstStrange_next = new TreeNode(Integer.MIN_VALUE);
TreeNode pre=new TreeNode(Integer.MIN_VALUE);
while (cur!=null) {
if (cur.left!=null) {
mostRight = cur.left;
while(mostRight.right!=null&&mostRight.right!=cur) {
mostRight=mostRight.right;
}
if (mostRight.right==null) {
mostRight.right=cur;
cur = cur.left;
continue;
}
else {
mostRight.right = null;
}
}
if (pre.val>cur.val) {
if (firstStrange==null) {
firstStrange=pre;
firstStrange_next=cur;
}
else {
int term = firstStrange.val;
firstStrange.val = cur.val;
cur.val = term;
return;
}
}
pre = cur;
cur =cur.right;
}
int term = firstStrange.val;
firstStrange.val = firstStrange_next.val;
firstStrange_next.val = term;
return;
}
} /**
//只要用到递归空间复杂度至少是O(书的高度),所以要做到O(1)的空间复杂度,只有Morris中序遍历
public void recoverTree(TreeNode root) { if(root==null) return; TreeNode cur=root,m1=null,m2=null,last=null; while(cur!=null) { TreeNode pre=cur.left; if(pre!=null) { while(pre.right!=null&&pre.right!=cur) pre=pre.right; if(pre.right==null) { pre.right=cur; cur=cur.left; continue; } else pre.right=null; } if(last==null) last=cur; else { if(m1==null&&last.val>cur.val) { m1=last; m2=cur; } else if(m1!=null&&last.val>cur.val) m2=cur; last=cur; } cur=cur.right; } int t=m1.val; m1.val=m2.val; m2.val=t; }
//满足空间复杂度为常数
//思路:设定两个指针用来指向两处错误处和一个pre指针指向中序遍历的前一个结点。
public class Solution {
TreeNode pre,mistake1,mistake2;
public void recoverTree(TreeNode root) {
inTraversal(root);
mistake1.val=mistake2.val^mistake1.val^(mistake2.val=mistake1.val);
}
public void inTraversal(TreeNode root){
if(root==null) return ;
inTraversal(root.left);
if(pre!=null&&pre.val>root.val){
if(mistake1==null){
mistake1=pre;
mistake2=root;
}else mistake2=root;
}
pre=root;
inTraversal(root.right);
}
}
import java.util.*;
public class Solution {
public void recoverTree(TreeNode root) {
List<TreeNode> list = new ArrayList<>();
inorder(root, list);
TreeNode first = null, second = null;
for (int i = 0; i < list.size() - 1; i ++) {
if(list.get(i).val > list.get(i + 1).val) {
first = list.get(i);
break;
}
}
for (int i = list.size() - 1; i > 0; i --) {
if(list.get(i).val < list.get(i - 1).val) {
second = list.get(i);
break;
}
}
first.val = second.val ^ first.val ^ (second.val = first.val);
}
public static void inorder(TreeNode root, List<TreeNode> list) {
if(root != null) {
inorder(root.left, list);
list.add(root);
inorder(root.right, list);
}
}
}
public void recoverTree(TreeNode root) {
TreeNode pre = null;
TreeNode first = null, second = null;
// Morris Traversal
TreeNode temp = null;
while(root!=null){ if(root.left!=null){
// connect threading for root temp = root.left;
while(temp.right!=null && temp.right != root) temp = temp.right;
// the threading already exists if(temp.right!=null){ if(pre!=null && pre.val > root.val){ if(first==null){first = pre;second = root;} else{second = root;}
} pre = root;
temp.right = null; root = root.right;
}else{
// construct the threading
temp.right = root; root = root.left;
}
}else{ if(pre!=null && pre.val > root.val){ if(first==null){first = pre;second = root;} else{second = root;}
} pre = root; root = root.right;
}
}
// swap two node values; if(first!= null && second != null){
int t = first.val;
first.val = second.val;
second.val = t;
}
}
public class Solution {
TreeNode firstElement =
TreeNode firstElement = null;
TreeNode secondElement =
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.
firstElement.val = secondElement.val;
secondElement.
secondElement.val = temp;
}
}
private void traverse(TreeNode root) {
if (root == null)
return;
traverse(root.left);
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;
}
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;
secondElement = root;
}
prevElement = root;
// End of "do some business"
traverse(root.right);
}