【LeetCode】Recover BinarySearch Tree

原題鏈接: http://oj.leetcode.com/problems/recover-binary-search-tree/ 
這道題是要求恢復一顆有兩個元素調換錯了的二叉查找樹。一開始拿到可能會覺得比較複雜,其實觀察出規律了就比較簡單。主要還是利用二叉查找樹的主要性質,就是中序遍歷是有序的性質。那麼如果其中有元素被調換了,意味着中序遍歷中必然出現違背有序的情況。那麼會出現幾次呢?有兩種情況,如果是中序遍歷相鄰的兩個元素被調換了,很容易想到就只需會出現一次違反情況,只需要把這個兩個節點記錄下來最後調換值就可以;如果是不相鄰的兩個元素被調換了,舉個例子很容易可以發現,會發生兩次逆序的情況,那麼這時候需要調換的元素應該是第一次逆序前面的元素,和第二次逆序後面的元素。比如1234567,1和5調換了,會得到5234167,逆序發生在52和41,我們需要把4和1調過來,那麼就是52的第一個元素,41的第二個元素調換即可。
搞清楚了規律就容易實現了,中序遍歷尋找逆序情況,調換的第一個元素,永遠是第一個逆序的第一個元素,而調換的第二個元素如果只有一次逆序,則是那一次的後一個,如果有兩次逆序則是第二次的後一個。算法只需要一次中序遍歷,所以時間複雜度是O(n),空間是棧大小O(logn)。代碼如下: 
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public void recoverTree(TreeNode root) {  
  2.     if(root == null)  
  3.         return;  
  4.     ArrayList<TreeNode> pre = new ArrayList<TreeNode>();  
  5.     pre.add(null);  
  6.     ArrayList<TreeNode> res = new ArrayList<TreeNode>();  
  7.     helper(root,pre, res);  
  8.     if(res.size()>0)  
  9.     {  
  10.         int temp = res.get(0).val;  
  11.         res.get(0).val = res.get(1).val;  
  12.         res.get(1).val = temp;  
  13.     }  
  14. }  
  15. private void helper(TreeNode root, ArrayList<TreeNode> pre, ArrayList<TreeNode> res)  
  16. {  
  17.     if(root == null)  
  18.     {  
  19.         return;  
  20.     }  
  21.     helper(root.left, pre, res);  
  22.     if(pre.get(0)!=null && pre.get(0).val>root.val)  
  23.     {  
  24.         if(res.size()==0)  
  25.         {  
  26.             res.add(pre.get(0));  
  27.             res.add(root);  
  28.         }  
  29.         else  
  30.         {  
  31.             res.set(1,root);  
  32.         }  
  33.     }  
  34.     pre.set(0,root);  
  35.     helper(root.right,pre,res);  
  36. }  
可以看到實現中pre用了一個ArrayList來存,這樣做的原因是因爲java都是值傳遞,所以我們要全局變化pre的值(而不是在當前函數裏),只能傳一個數組,才能改變結點的地址,這一點非常重要,也是java和C++一個比較大的區別,不瞭解的朋友可以研究一下哈。
這道題還是考察二叉樹遍歷,不過應用題目要求套了一個不同的外殼,需要我們利用二叉查找樹的性質觀察出規律之後才能求
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章