正則表示式--grep
從前序與中序遍歷序列構造二叉樹
給定一棵樹的前序遍歷 preorder 與中序遍歷 inorder。請構造二叉樹並返回其根節點
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
作者:力扣 (LeetCode)
連結:https://leetcode-cn.com/leetbook/read/top-interview-questions-medium/xvix0d/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
答案參考了評論區大佬。
首先,需要明白,前序遍歷二叉樹的順序。其第一個結點必然是根節點,然後若根節點有左子樹,其根節點的下一個節點必然為其左子樹的根節點。否則,若有右子樹,則下一個節點必然為右子樹的根節點。(前序是從前往後看,後序從後往前看就可以)
明確這個邏輯就好辦了,那麼我們如何知道根節點有無左右子樹呢?這就需要通過中序遍歷順序來確定了。在中序順序中,根節點左側為其左子樹,右側為其右子樹。我們只想要知道有沒有左右子樹即可,所以只需確定中序順序中根節點的左右兩側的元素個數即可。
1.遞迴
1.每輪遞迴返回當前前序序列的根節點,返回後在前序序列中刪掉根節點。
2.由中序序列遞迴其左右子樹。
3.遞迴返回結果連線到當前根節點的左右孩子上。
public TreeNode buildTree(int[] preorder, int[] inorder) { if(preorder.length == 0){ return null; } List<Integer> pre = new ArrayList<>(); List<Integer> in = new ArrayList<>(); for(int i = 0; i < preorder.length; i++){ pre.add(preorder[i]); in.add(inorder[i]); } return recursion(pre, in); } public TreeNode recursion(List<Integer> pre, List<Integer> in){ if(in.size() == 0){ return null; } int midVal = pre.remove(0); TreeNode root = new TreeNode(midVal); int mid = in.indexOf(midVal); root.left = recursion(pre, in.subList(0, mid)); root.right = recursion(pre, in.subList(mid + 1, in.size())); return root; }
2.非遞迴
擷取主集合的操作都可以轉換成由雙指標指示陣列範圍。唯一需要注意的就是由於不能在陣列中刪除元素。所以當前的根節點的左右子樹根節點位置需要想辦法獲取,如果是左子樹根,那麼就下一位就是,如果是右子樹根那麼就需要跨過中間的所有左子樹的結點。也就是中序序列中的:根位置-當前樹起始位置+1
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length == 0){
return null;
}
return recursion(preorder, inorder, 0, 0, inorder.length - 1);
}
public TreeNode recursion(int[] preorder, int[] inorder, int preCur, int inBegin, int inEnd){
if(preCur > preorder.length - 1 || inBegin > inEnd){
return null;
}
int midVal = preorder[preCur];
TreeNode root = new TreeNode(midVal);
int mid = -1;
for(int i = 0; i < inorder.length; i++){
if(inorder[i] == midVal){
mid = i;
break;
}
}
root.left = recursion(preorder, inorder, preCur + 1, inBegin, mid - 1);
root.right = recursion(preorder, inorder, preCur + mid - inBegin + 1, mid + 1, inEnd);
return root;
}