題型一:105. 從前序與中序遍歷序列構造二叉樹
根據一棵樹的前序遍歷與中序遍歷構造二叉樹。
注意:
你可以假設樹中沒有重複的元素。
例如,給出
前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]
返回如下的二叉樹:
3
/ \
9 20
/ \
15 7
思路分析:
1、從前序遍歷結果中找到樹根節點的值: pretorder[index];
2、在中序遍歷結果中找到根節點的位置rootIndex,將中序遍歷分成兩部分:
①左子樹的節點數據範圍:[ left ,rootIndex )
②左子樹的節點數據範圍:[rootIndex+1,right )
3、創建根節點:
①遞歸創建根的左子樹;
②遞歸創建根的右子樹;
實現代碼:
class Solution {
// preorder:前序遍歷結果
// inorder:中序遍歷結果
// [left,right):標記在中序遍歷中節點的位置範圍
int index = 0;
private TreeNode reBuildTree(int[] preorder, int[] inorder, int left, int right){
if(index >= preorder.length || left>=right){
return null;
}
//前序找根節點 preorder[index]
//在中序遍歷中找根的位置
//確認左右子樹的區間
int rootindex = left;
while(rootindex<right){
if(inorder[rootindex]==preorder[index]){
break; //如果找到了,直接退出
}
rootindex++; //如果沒找到,往後繼續走
}
//創建根節點
TreeNode root = new TreeNode(preorder[index]);
++index;//根的位置還包括左子樹/右子樹的根 所以需要移動
//遞歸調用左子樹[left,rootindex):
root.left = reBuildTree(preorder,inorder,left,rootindex);
//遞歸調用右子樹[rootindex+1,right):
root.right = reBuildTree(preorder,inorder,rootindex+1,right);
return root;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
return reBuildTree(preorder, inorder,0,inorder.length);
}
}
【注意】:
關於前序裏找根節點(index)的一個知識點:
在不斷遞歸的過程中,index的值實際會發生變化,需要再遞歸中對index的改變帶出到上一層遞歸中,但是參數index是按照int的方式傳遞的,在裏層的遞歸中對index是按照int的方式傳遞的,在裏層對Index所做的修改並不能夠體現到外層遞歸中。
<解決辦法>
1、參數int直接使用Integer方式傳遞 ------錯誤
Integer 中的內容是無法修改的,如果修改,實際虛擬機會重新創建一個index。
2、將index重新封裝一種新的類型------正確(沒有意義)
3、將index作爲類的成員變量------正確(如上代碼: int index = 0)
題型二:106. 從中序與後序遍歷序列構造二叉樹
根據一棵樹的中序遍歷與後序遍歷構造二叉樹。
注意:
你可以假設樹中沒有重複的元素。
例如,給出
中序遍歷 inorder = [9,3,15,20,7]
後序遍歷 postorder = [9,15,7,20,3]
返回如下的二叉樹:
3
/ \
9 20
/ \
15 7
思路分析:
1、從後序遍歷結果中找到樹根節點的值: postorder[index];
2、在中序遍歷結果中找到根節點的位置rootIndex,將中序遍歷分成兩部分:
①左子樹的節點數據範圍:[ left ,rootIndex )
②左子樹的節點數據範圍:[rootIndex+1,right )
3、創建根節點:
①遞歸創建根的右子樹;
②遞歸創建根的左子樹;
實現代碼:
class Solution {
int index = 0 ;
private TreeNode buildTree(int[] inorder, int[] postorder,int left, int right) {
if(index<0 || left>=right){
return null;
}
int rootIndex = left;
while(rootIndex<right){
if(inorder[rootIndex]==postorder[index]){
break;
}
rootIndex++;//沒找到 繼續往後找
}
TreeNode root = new TreeNode(postorder[index]);
--index;//後序遍歷根節點在最後 所以需要向前
//遞歸右子樹
root.right=buildTree(inorder,postorder,rootIndex+1,right);
//遞歸左子樹
root.left=buildTree(inorder,postorder,left,rootIndex);
return root;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
index=postorder.length-1;
return buildTree(inorder,postorder,0,postorder.length);
}
}