劍指offer-重建二叉樹

代碼原作者的代碼利用了遞歸思想,寫得很好。鏈接在此https://cloud.tencent.com/developer/article/1401290

由於本人腦子笨,有些細節地方轉不過來(其實以前碰到這種情況也是要想好久)。比如本題代碼中的參數問題:

public class Solution {
     
    private TreeNode rebuildTree(int[] pre, int preStart, int preEnd, int[] in, int inStart, int inEnd) {
        if(preStart > preEnd | inStart > inEnd)
            return null;
        // 根節點
        TreeNode root = new TreeNode(pre[preStart]);
       // 尋找根節點在中序序列的位置
        for (int i = inStart; i <= inEnd; i++) {
            if (in[i] == pre[preStart]) {
                // 可以計算出中序序列的左右子樹序列爲:左:inStart~i -1,右:i+1~inEnd。
                // 前序序列的左右子樹:左:preStart+1~preStart+i-inStart,右:preStart+i-inStart+1~preEnd
                root.left = rebuildTree(pre,preStart+1, preStart+i-inStart,in, inStart, i - 1);
                root.right = rebuildTree(pre,preStart+i-inStart+1, preEnd, in, i+1, inEnd);
            }
        }
        return root;
    }
     
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode root;
        root = rebuildTree(pre, 0, pre.length - 1, in, 0, in.length - 1);
 
        return root;
    }
}

問題就在以下兩句

root.left = rebuildTree(pre,preStart+1, preStart+i-inStart,in, inStart, i - 1);
root.right = rebuildTree(pre,preStart+i-inStart+1, preEnd, in, i+1, inEnd);

 

在preStart+i-inStart中爲什麼要減去inStart呢?不減不行嗎?反正inStart剛好是0啊?後來自己走了幾次代碼,遞歸調用函數後發現inStart雖然在左邊,但不會一直是0。(真是菜啊)



如圖所示,劃分後的中序序列的左半部分是要用來構建根節點的左子樹的,這一部分的長度剛好是length=i-inStart,所以在前序序列中,左子樹的序列截取範圍就是從preStart+1到preStart+length,即preStart+i-inStart,然後右子樹的前序序列範圍就是preStart+i-inStart+1到preEnd了。

其實以前做題也碰到過類似的情況,某個參數傳進去的時候加1或者減1就對了,差了個1就不行。大一的時候剛學冒泡排序,有的地方已經不用遍歷到結尾了,傳參j<n-i,還不知道爲啥,關鍵也在沒弄明白i的改變會有什麼影響。二叉樹這一題,也犯了類似的錯誤,本應該宏觀一點切割序列,一段一段來看,卻只切割了一次,使用了類似暴力的方式從preStart往右邊數了幾個數字,剛好有i個,於是覺得preStart+i沒毛病,錯就錯在第一遍切割inStart是剛好是0,所以沒影響。preStart的偏移量應該剛好是左子樹序列的長度纔對,想到了“一段長度”這個概念會更早發現錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章