T105. Construct Binary Tree from Preorder and Inorder Traversal【Medium】
題目
給定樹的先序和中序遍歷,構(gòu)造出這個(gè)二叉樹。
注意:可以假設(shè)樹中不存在重復(fù)項(xiàng)。
思路
首先要明白先序和中序是怎么樣的一種遍歷方式:
然后要明白前序和中序怎么求后續(xù),找了博客:
舉個(gè)文章中的例子(還是例子最好):
前序遍歷: GDAFEMHZ
中序遍歷: ADEFGHMZ
第一步,根據(jù)前序遍歷的特點(diǎn),我們知道根結(jié)點(diǎn)為G
第二步,觀察中序遍歷ADEFGHMZ。其中root節(jié)點(diǎn)G左側(cè)的ADEF必然是root的左子樹,G右側(cè)的HMZ必然是root的右子樹。
第三步,觀察左子樹ADEF,左子樹的中的根節(jié)點(diǎn)必然是大樹的root的leftchild。在前序遍歷中,大樹的root的leftchild位于root之后,所以左子樹的根節(jié)點(diǎn)為D。
第四步,同樣的道理,root的右子樹節(jié)點(diǎn)HMZ中的根節(jié)點(diǎn)也可以通過(guò)前序遍歷求得。在前序遍歷中,一定是先把root和root的所有左子樹節(jié)點(diǎn)遍歷完之后才會(huì)遍歷右子樹,并且遍歷的左子樹的第一個(gè)節(jié)點(diǎn)就是左子樹的根節(jié)點(diǎn)。同理,遍歷的右子樹的第一個(gè)節(jié)點(diǎn)就是右子樹的根節(jié)點(diǎn)。
第五步,觀察發(fā)現(xiàn),上面的過(guò)程是遞歸的。先找到當(dāng)前樹的根節(jié)點(diǎn),然后劃分為左子樹,右子樹,然后進(jìn)入左子樹重復(fù)上面的過(guò)程,然后進(jìn)入右子樹重復(fù)上面的過(guò)程。最后就可以還原一棵樹了。
該步遞歸的過(guò)程可以簡(jiǎn)潔表達(dá)如下:
1 確定根,確定左子樹,確定右子樹。
2 在左子樹中遞歸。
3 在右子樹中遞歸。
4 打印當(dāng)前根。
代碼
代碼取自 Top Solution,稍作注釋
public TreeNode buildTree(int[] preorder, int[] inorder) {
return helper(0, 0, inorder.length - 1, preorder, inorder);
}
public TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder) {
// 邊界處理以及遞歸的終點(diǎn)
if (preStart > preorder.length - 1 || inStart > inEnd) {
return null;
}
TreeNode root = new TreeNode(preorder[preStart]);
// 中序的編號(hào)
int inIndex = 0;
for (int i = inStart; i <= inEnd; i++) {
if (inorder[i] == root.val) {
inIndex = i;
}
}
// 對(duì)左邊和右邊的子樹分別處理
root.left = helper(preStart + 1, inStart, inIndex - 1, preorder, inorder);
root.right = helper(preStart + inIndex - inStart + 1, inIndex + 1, inEnd, preorder, inorder);
return root;
}