LeetCode: Recover Binary Search Tree 解題報告


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?

 

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

 

Hide Tags Tree Depth-first Search

 SOLUTION 1:

采用遞歸+全局變量完成:

空間復雜度是O(logn)

REF: http://huntfor.iteye.com/blog/2077665
這一篇講得蠻清楚:
http://yucoding.blogspot.com/2013/03/leetcode-question-75-recover-binary.html

具體的思路,還是通過中序遍歷,只不過,不需要存儲每個節點,只需要存一個前驅即可。

例如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

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

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM