LeetCode: Recover Binary Search Tree 解題報告

Recover Binary Search Tree

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

 SOLUTION 1:

採用遞歸+全局變量完成: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:
【LeetCode】Recover <wbr>Binary <wbr>Search <wbr>Tree
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     }
View Code

SOLUTION 2:

也能夠採用非遞歸方法,不須要加全局變量,空間複雜度是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     }
View Code

SOLUTION 3:

還有更厲害的做法,能夠達到O(1)的空間複雜度。之後再補上。

ref: http://fisherlei.blogspot.com/2012/12/leetcode-recover-binary-search-tree.html

=================

代碼請參考主頁君的實現:
請戳主頁君的代碼哦

相關文章
相關標籤/搜索