https://leetcode.com/problems/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?
这道题是利用BST的规律,inorder traversal的话会返回一个从小到大的list,这时候逆序的就是被交换的。
如
12345678,交换后 12543678,由于把大数交换到前面,所以第一个逆序的肯定是比它后面的数大的,如果是相邻两个数交换的话,只需要把逆序的数和它后面的数交换就行,如果不是相邻的数的话,第二个逆序肯定是比它前面的数小的,可以看到例子中4,3都比前面的数小,取遇到的最后一个就可以了。
public class Solution {
private TreeNode previous;
private TreeNode abnormal1;
private TreeNode abnormal2;
public void recoverTree(TreeNode root) {
inorder(root);
int tmp = abnormal1.val;
abnormal1.val = abnormal2.val;
abnormal2.val = tmp;
}
public void inorder(TreeNode root){
if(root==null ) return;
inorder(root.left);
if(previous!=null && root.val < previous.val){
if(abnormal1==null){
abnormal1 = previous;
abnormal2 = root;
}
else abnormal2 = root;
}
previous = root;
inorder(root.right);
}
}
这种方法时间复杂度O(n),空间复杂度是递归栈所用的空间O(lgn)
空间复杂度O(1)的解法的解释见这里:http://fisherlei.blogspot.com/2012/12/leetcode-recover-binary-search-tree.html
如何用O(1)空间进行Inorder Tree Traversal:
重点就是一个节点的前一个几点是它左子树的最右节点,于是每次如果有左子树,则找到最右节点,把最右节点的右指针(因为是最右节点,所以一开始肯定为空)指向这个节点,于是当遍历到最右节点时,就可以回到这个节点了。
另外,当发现最右节点的右指针已经指向该节点时,说明左子树已经完全访问过了,于是此时就访问当前节点,然后右子树就可以了。
时间复杂度O(n*lgn),因为此时每个节点都需要去找它左子树的最右节点,which is O(lgn)
public void recoverTree(TreeNode root) {
if(root==null) return;
TreeNode pre = null;
TreeNode ab1 = null;
TreeNode ab2 = null;
TreeNode current = root;
while(current!=null){
if(current.left==null){
if(pre!=null && pre.val>current.val){
if(ab1==null){
ab1 = pre;
}
ab2 = current;
}
pre = current;
current = current.right;
}
else{
TreeNode left = current.left;
while(left.right!=null && left.right!=current){
left = left.right;
}
if(left.right==current){
if(pre!=null && pre.val>current.val){
if(ab1==null){
ab1 = pre;
}
ab2 = current;
}
pre = current;
current = current.right;
left.right = null;
}
else{
left.right = current;
current = current.left;
}
}
}
int tmp = ab1.val;
ab1.val = ab2.val;
ab2.val = tmp;
}