1. 程式人生 > >Recover Binary Search Tree -- LeetCode

Recover Binary Search Tree -- LeetCode

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

                原題連結:  http://oj.leetcode.com/problems/recover-binary-search-tree/  
這道題是要求恢復一顆有兩個元素調換錯了的二叉查詢樹。一開始拿到可能會覺得比較複雜,其實觀察出規律了就比較簡單。主要還是利用二叉查詢樹的主要性質,就是中序遍歷是有序的性質。那麼如果其中有元素被調換了,意味著中序遍歷中必然出現違背有序的情況。那麼會出現幾次呢?有兩種情況,如果是中序遍歷相鄰的兩個元素被調換了,很容易想到就只需會出現一次違反情況,只需要把這個兩個節點記錄下來最後調換值就可以;如果是不相鄰的兩個元素被調換了,舉個例子很容易可以發現,會發生兩次逆序的情況,那麼這時候需要調換的元素應該是第一次逆序前面的元素,和第二次逆序後面的元素。比如1234567,1和5調換了,會得到5234167,逆序發生在52和41,我們需要把4和1調過來,那麼就是52的第一個元素,41的第二個元素調換即可。

搞清楚了規律就容易實現了,中序遍歷尋找逆序情況,調換的第一個元素,永遠是第一個逆序的第一個元素,而調換的第二個元素如果只有一次逆序,則是那一次的後一個,如果有兩次逆序則是第二次的後一個。演算法只需要一次中序遍歷,所以時間複雜度是O(n),空間是棧大小O(logn)。程式碼如下: 
public void recoverTree(TreeNode root) {    if(root == null)        return;    ArrayList<TreeNode> pre = new
ArrayList<TreeNode>();    pre.add(null);    ArrayList<TreeNode> res = new ArrayList<TreeNode>();    helper(root,pre, res);    if(res.size()>0)    {        int temp = res.get(0
).val;        res.get(0).val = res.get(1).val;        res.get(1).val = temp;    }}private void helper(TreeNode root, ArrayList<TreeNode> pre, ArrayList<TreeNode> res){    if(root == null)    {        return;    }    helper(root.left, pre, res);    if(pre.get(0)!=null && pre.get(0).val>root.val)    {        if(res.size()==0)        {            res.add(pre.get(0));            res.add(root);        }        else        {            res.set(1,root);        }    }    pre.set(0,root);    helper(root.right,pre,res);}
可以看到實現中pre用了一個ArrayList來存,這樣做的原因是因為java都是值傳遞,所以我們要全域性變化pre的值(而不是在當前函式裡),只能傳一個數組,才能改變結點的地址,這一點非常重要,也是java和C++一個比較大的區別,不瞭解的朋友可以研究一下哈。
這道題還是考察二叉樹遍歷,不過應用題目要求套了一個不同的外殼,需要我們利用二叉查詢樹的性質觀察出規律之後才能求解。
           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述