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?
题意:一颗二叉排序树,但是有两个元素顺序变了。让恢复这个二叉排序树。
最简单的思路就是,中序遍历这个排序树,将相应元素存到数组中,然后在数组中找到两个被交换的元素。
但是,这道题的要求只能使用O(1)的空间。
所以,就不能使用数组了。但是,我们可以使用类似的方法:即,也是中序遍历这个树,但是,需要将之前的节点存下来。如果之前节点的值大于当前节点的值,那么说明之前的节点有问题,将之前的节点存下来:
接下来,有两种情况:
(1)相邻的两个元素被交换,即问题节点1的下一个节点就是问题节点2。
(2)被交换的不是相邻的元素。
程序如下(需要注意,在该程序中,以上两种情况都能被处理):
public class RecoverBinarySearchTree {
TreeNode firstElement = null;
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.val = secondElement.val;
secondElement.val = temp;
}
private void traverse(TreeNode root) {
if (root == null)
return;
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;
}
// 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;
// End of "do some business"
traverse(root.right);
}
}
其实原本,这道题做到这儿应该就完了,而且leetcode也可以通过,但是,讨论区某些人觉得,以上的解法由于使用到了递归,所有,需要的空间并不是O(1),而是O(lgn),不符合题意,如果需要满足题意,那么就需要使用morris方法遍历。
morris方法是个蛋蛋?!?morris方法,无非是通过时间换空间的一种方法,但是感觉时间复杂度较高,不太适用。关于morris方法,具体可以参加另一篇博客:
http://blog.csdn.net/zuoyexingchennn/article/details/45445891
适用morris方法的程序如下:
public void recoverTree2(TreeNode root) {
List<TreeNode> eNodes = new LinkedList<TreeNode>(); //error nodes
if(root == null) return;
TreeNode current = root;
TreeNode pre;
TreeNode previous = null;
while(current != null){
if(current.left == null){
if(previous!=null && previous.val > current.val){
eNodes.add(previous);
eNodes.add(current);
}
previous = current;
current = current.right;
}else{
pre = current.left;
while(pre.right != null && pre.right.val != current.val){
pre = pre.right;
}
if(pre.right == null){
pre.right = current;
current = current.left;
}else {
if(previous!=null && previous.val > current.val){
eNodes.add(previous);
eNodes.add(current);
}
pre.right = null;
previous = current;
current = current.right;
}
}
}
//this is redundant check
//if(eNodes.size() == 0) return;
if(eNodes.size() == 2){
pre = eNodes.get(0);
current = eNodes.get(1);
}else{ //this case where eNodes.size()==4
pre = eNodes.get(0);
current = eNodes.get(3);
}
int temp = pre.val;
pre.val = current.val;
current.val = temp;
}