Two elements of a binary search tree (BST) are swapped by mistake.html
Recover the tree without changing its structure.java
Note:node
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?git
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.github
Hide Tags Tree Depth-first Searchapp
採用遞歸+全局變量完成:ide
空間複雜度是O(logn)spa
REF: http://huntfor.iteye.com/blog/2077665
這一篇講得蠻清楚:
http://yucoding.blogspot.com/2013/03/leetcode-question-75-recover-binary.html
code
具體的思路,仍是經過中序遍歷,只不過,不須要存儲每一個節點,只須要存一個前驅便可。htm
例如1,4,3,2,5,6
1.當咱們讀到4的時候,發現是正序的,不作處理
2.可是遇到3時,發現逆序,將4存爲第一個錯誤節點,3存爲第二個錯誤節點
3.繼續日後,發現3,2又是逆序了,那麼將第2個錯誤節點更新爲2
若是是這樣的序列:1,4,3,5,6同上,獲得逆序的兩個節點爲4和3。
========================================
這裏咱們補充一下,爲何要替換第二個節點而不是第一個節點:
e.g. The correct BST is below:
The inorder traversal is : 1 3 4 6 7 8 10 13 14
Find the place which the order is wrong.
Wrong order: 1 3 8 6 7 4 10 13 14
FIND: 8 6
Then we find: 7 4
8, 6 是錯誤的序列, 可是,7,4也是錯誤的序列。
由於8,6前面的序列是正確的,因此8,6必定是後面的序列交換來的。
然後面的是比較大的數字,也就是說8必定是被交換過來的。而7,4
中也應該是小的數字4是前面交換過來的。
用反證法來證實:
假設:6是後面交換過來的
推論: 那麼8比6還大,那麼8應該也是後面交換來的,
這樣起碼有3個錯誤的數字了
而題目是2個錯誤的數字,得證,只應該是8是交換過來的。
結論就是:咱們須要交換的是:8, 4.
1 public class RecoverTree { 2 TreeNode pre = null; 3 TreeNode first = null; 4 TreeNode second = null; 5 6 7 public void recoverTree(TreeNode root) { 8 inOrder(root); 9 10 // swap the value of first and second node. 11 int tmp = first.val; 12 first.val = second.val; 13 second.val = tmp; 14 } 15 16 public void inOrder(TreeNode root) { 17 if (root == null) { 18 return; 19 } 20 21 // inorder traverse. 22 inOrder(root.left); 23 24 /* 25 Find the place which the order is wrong. 26 For example: 1 3 4 6 7 8 10 13 14 27 Wrong order: 1 3 8 6 7 4 10 13 14 28 FIND: ___ 29 Then we find: ___ 30 8, 6 是錯誤的序列, 可是,7,4也是錯誤的序列。 31 由於8,6前面的序列是正確的,因此8,6必定是後面的序列交換來的。 32 然後面的是比較大的數字,也就是說8必定是被交換過來的。而7,4 33 中也應該是小的數字4是前面交換過來的。 34 35 用反證法來證實: 36 假設:6是後面交換過來的 37 推論: 那麼8比6還大,那麼8應該也是後面交換來的, 38 這樣起碼有3個錯誤的數字了 39 而題目是2個錯誤的數字,得證,只應該是8是交換過來的。 40 */ 41 42 // 判斷 pre 是否已經設置 43 if (pre != null && pre.val > root.val) { 44 if (first == null) { 45 // 首次找到反序. 46 first = pre; 47 second = root; 48 } else { 49 // 第二次找到反序,更新Second. 50 second = root; 51 } 52 } 53 54 pre = root; 55 56 // inorder traverse. 57 inOrder(root.right); 58 }
也能夠採用非遞歸方法,不須要加全局變量,空間複雜度是O(logn):
1 public void recoverTree1(TreeNode root) { 2 if (root == null) { 3 return; 4 } 5 6 TreeNode node1 = null; 7 TreeNode node2 = null; 8 9 TreeNode pre = null; 10 11 Stack<TreeNode> s = new Stack<TreeNode>(); 12 TreeNode cur = root; 13 14 while (true) { 15 while (cur != null) { 16 s.push(cur); 17 cur = cur.left; 18 } 19 20 if (s.isEmpty()) { 21 break; 22 } 23 24 TreeNode node = s.pop(); 25 26 if (pre != null) { 27 // invalid order 28 if (pre.val > node.val) { 29 if (node1 == null) { 30 node1 = pre; 31 node2 = node; 32 } else { 33 node2 = node; 34 } 35 } 36 } 37 38 pre = node; 39 40 cur = node.right; 41 } 42 43 int tmp = node1.val; 44 node1.val = node2.val; 45 node2.val = tmp; 46 47 return; 48 }
還有更厲害的做法,能夠達到O(1)的空間複雜度。之後再補上。
ref: http://fisherlei.blogspot.com/2012/12/leetcode-recover-binary-search-tree.html
=================
代碼請參考主頁君的實現:
請戳主頁君的代碼哦