劍指Offer 07 重建二叉樹

2022-06-16 02:48:12 字數 3800 閱讀 1340

首先應該明確:(前序遍歷+中序遍歷)(後序遍歷+中序遍歷)能唯一確定一棵二叉樹;而前序遍歷[根節點 左子樹 右子樹]和後序遍歷[左子樹 右子樹 根節點]不能唯一確定一顆二叉樹。

因為我們不能從這兩種遍歷中區分出左子樹和右子樹的區間。這裡有乙個例子

但是如果這棵樹是真二叉樹(所有節點的度要麼為0,要麼為2,即左兒子和右兒子同時存在),那麼(前序遍歷+後序遍歷)就能重構一棵二叉樹。如下圖所示:

分析一下:二叉樹前序遍歷的第乙個元素和後序遍歷的最後乙個元素為樹根,後序遍歷序列的倒數第二個元素為右子樹的根,前序遍歷中右子樹的根的前面的元素均為左子樹元素,從而分隔左右子樹的元素,因此可以採用遞迴依次構建每一棵子樹。

前序[1,2,4,5,3,6,7]

後序[4,5,2,6,7,3,1]

對於前序遍歷,1後面的2是左子樹的根節點;對於右子樹,1前面的3是右子樹的根節點。左子樹的根節點2,在後序遍歷中2之前的(包括2,都是左子樹的部分)。

下面給出重構一棵二叉樹的各種形式:

1、前序+中序

public hashmapmap;   //

建立《節點值,陣列下標》的對映關係

/*重構一棵二叉樹:前序遍歷 + 中序遍歷

public treenode buildtree(int preorder, int inorder)

return mybuildtree(preorder, inorder, 0, len-1, 0, len-1);

}public treenode mybuildtree(int preorder, int inorder, int preorderleft, int preorderright, int inorderleft, int inorderright)

//確定根節點

int preorderroot = preorderleft;

treenode root = new treenode(preorder[preorderroot]);

int inorderroot = map.get(root.val);

int sizeoflefttree = inorderroot - inorderleft; // 左子樹的大小

//構建左子樹

root.left = mybuildtree(preorder, inorder, preorderleft+1, preorderleft+sizeoflefttree, inorderleft,inorderroot-1);

//構建右子樹

root.right = mybuildtree(preorder, inorder, preorderleft+sizeoflefttree+1, preorderright, inorderroot+1,inorderright);

return root;

}

2、中序+後序

public treenode buildtree(int inorder, int

postorder)

return mybuildtree(inorder, postorder, 0, len-1, 0, len-1);

}public treenode mybuildtree(int inorder, int postorder, int inorderleft, int inorderright, int postorderleft, int

postorderright)

//根節點

int postorderroot =postorderright;

treenode root = new

treenode(postorder[postorderroot]);

int inorderroot =map.get(root.val);

int sizeoflefttree = inorderroot -inorderleft;

//建立左子樹

root.left = mybuildtree(inorder, postorder, inorderleft, inorderroot-1, postorderleft, postorderleft + sizeoflefttree-1);

//建立右子樹

root.right = mybuildtree(inorder, postorder, inorderroot+1, inorderright, postorderleft+sizeoflefttree+1, postorderroot-1);

return

root;

}

3、前序+後序

private hashmapmap; //

《值,下標》

public treenode buildtree(int preorder, int

postorder)

map = new hashmap<>();

int len =preorder.length;

for (int i = 0; i < len; i++)

return mybuildtree(preorder, postorder, 0, len-1, 0, len-1);

}public treenode mybuildtree(int preorder, int postorder, int preorderleft, int preorderright, int postorderleft, int

postorderright)

//注意這個特判條件,否則4會出現陣列越界

if (preorderleft == preorderright || postorderleft ==postorderright)

//根節點

int preorderroot =preorderleft;

treenode root = new

treenode(preorder[preorderleft]);

//前序遍歷的第二個節點就是左子樹的根節點

int preorderlefttreeroot = preorderleft + 1; //

3int postorderlefttreeroot = map.get(preorder[preorderlefttreeroot]); //

4

//確定左子樹的長度

int sizeoflefttree = postorderlefttreeroot - postorderleft + 1;

//確定右子樹的長度

int sizeofrighttree = postorderright - postorderlefttreeroot - 1;

//構建左子樹

root.left = mybuildtree(preorder, postorder, preorderlefttreeroot, preorderlefttreeroot+sizeoflefttree-1, postorderleft, postorderlefttreeroot);

//構建右子樹

root.right = mybuildtree(preorder, postorder, preorderlefttreeroot+sizeoflefttree, preorderright, postorderlefttreeroot+1, postorderlefttreeroot+sizeofrighttree);

return

root;

}

劍指offer07 重建二叉樹

這是乙個非常高頻的面試題。題目 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例子 前序遍歷 preorder 3,9,20,15,7 中序遍歷 inorder 9,3,15,20,7 思路 題目給出了前序和中序遍歷,我們可以知道前序的...

劍指 Offer 07 重建二叉樹

難度 中等 題目描述 解題思路 這道題之前做過,但是忘得乾乾淨淨了。現在再做一遍撿一撿,說不定哪次面試就出到了呢 總體思想就是遞迴,用雜湊表來儲存對應的中序遍歷的下標,空間換時間,免得每次都要去遍歷找下標。然後每次遞迴的時候,要給對應的左子樹和右子樹在對應陣列裡的下標,左端點大於右端點的時候返回空。...

劍指 Offer 07 重建二叉樹

首先要懂得前序遍歷和中序遍歷,可以寫出兩個陣列,自己手動來重建一下二叉樹,來看看重建二叉樹是怎麼乙個流程。以圖中給出的二叉樹為例,根據前序遍歷的特點,可知前序遍歷的首尾數字是根節點,比如這個時候根節點數值為3,可以在中序遍歷中第2個位置找到數值3,在3左邊的9為3的左子樹,右邊的15,20,7為右子...