LeetCode OJ - Recover Binary Search Tree
这道题要求空间复杂度为O(1),则只能采用Morris Traversal进行中序遍历!!这个了解了之后,难点在于如何定位到两个被交换了的节点?
我就被困在这里几个小时!!!(允许我为自己的愚蠢表示下悲伤吧!!!)
参考了discuss中前辈的算法,才发现很简单!!!
我们只需要这样来看问题,BST的中序遍历是递增的,如果有一对节点被交换了,那么这个递增序列会在被交换的这对节点前后被打破。这一对节点有两种情况:一种是相邻着的,一种是不相邻的。对于第一种情况,我们只会遇到一次顺序被打破;而对于第二种情况,我们会遇到两次顺序被打破。当我们第一次遇到顺序被打破的时候,是中序遍历过程中上次被输出的节点和当前节点的值不满足小于的关系,而且可以肯定得是被交换的节点之一是上次被输出的节点,如果我们将不再遇到第二次顺序被打破,则说明是情况一,并且被交换的另一个节点是当前节点;如果我们会遇到第二次顺序被打破,同样这次也是中序遍历过程中上次被输出的节点和当前节点的值不满足小于的关系,并且可以肯定的是被交换的另一个节点是当前节点。
通过上述过程可以确定被交换的两个节点,最后再互换这两个节点的值就可以了!!
1 /** 2 * Two elements of a binary search tree (BST) are swapped by mistake. 3 * Recover the tree without changing its structure. 4 * Could you devise a constant space solution? 5 * using Morris Traversal 6 * @param root 7 */ 8 public void recoverTree(TreeNode root){ 9 if(root == null || root.left == null && root.right == null) 10 return ; 11 TreeNode pred1=null ; 12 TreeNode cur1=null ; 13 TreeNode pred2=null ; 14 TreeNode cur2=null ; 15 16 TreeNode cur = root; 17 TreeNode last = null; // the last node that be printed out 18 19 while(cur!=null){ 20 21 if(cur.left!=null){ 22 //find its predecessor 23 TreeNode pre = cur.left; 24 while(pre.right!=null && pre.right != cur){ 25 pre = pre.right; 26 } 27 if(pre.right == null) 28 { 29 pre.right = cur;//make the predecessor's right pointer points to the current node 30 cur = cur.left; 31 }else 32 { 33 pre.right = null;//recover the predecessor's right pointer. 34 last = cur; 35 cur = cur.right;// notice here!!!!!! 36 } 37 38 }else{ 39 last = cur; 40 cur = cur.right; 41 } 42 //it's a very nice method!!!! 43 if(last!=null && cur != null && last.val>cur.val){ 44 if(pred1 == null){ 45 pred1 = last; 46 cur1 = cur; 47 }else 48 { 49 pred2 = last; 50 cur2 = cur; 51 } 52 } 53 } 54 55 int temp ; 56 if(pred1 != null && cur2 !=null){ 57 temp = pred1.val; 58 pred1.val = cur2.val; 59 cur2.val = temp; 60 }else{ 61 temp = pred1.val; 62 pred1.val = cur1.val; 63 cur1.val = temp; 64 } 65 66 }
有问题可以和我联系,bettyting2010#163 dot com