面試題6:根據前序和中序序列構建二叉樹(Leetcode-106)
阿新 • • 發佈:2019-02-11
題目:輸入二叉樹的前序遍歷和中序遍歷序列,重構其二叉樹,假設輸入的數字都是不重複的。
例如前序序列是 {1,2,4,7,3,5,6,8},中序序列是{4,7,2,1,5,3,8,6}。
分析如下圖所示:
演算法步驟:
1. 前序序列的第一個元素即根節點。
2. 根據找到的根節點在中序序列中找到根節點,找出左、右子樹的範圍。
3. 函式輸入引數有三個:前序序列的start位置,中序序列的start位置,序列長度。
4. help遞迴函式引數有四個引數:前序序列的start位置,前序序列的end位置,中序序列的start位置,中序序列的end位置。
程式碼如下:
BTNode* ConstructHelper(int * pre_start, int* pre_end, int* in_start, int* in_end)
{
//前序遍歷的第一個元素是根節點
int root_value = pre_start[0];
BTNode* root = new BTNode(root_value);
//如果只有一個元素,並且中序遍歷和前序遍歷元素相同
if(pre_start == pre_end)
{
if((in_start == in_end) && (*pre_start == *in_end))
{
return root;
}
else
{
return NULL;//輸入錯誤,無法構建排序二叉樹
}
}
//在中序遍歷序列中找到根節點
int* root_inorder = in_start;
bool is_find_root = false;
while(root_inorder <= in_end)
{
if(*root_inorder == root_value)
{
is_find_root = true ;
break;
}
root_inorder++;
}
//在中序遍歷中未找到根節點
if(!is_find_root)
{
return NULL;//輸入錯誤,無法構建排序二叉樹
}
int left_length = root_inorder - in_start;
int* left_preorder_end = pre_start + left_length;//前序遍歷中左子樹的最右邊的位置
if(left_length > 0)//構建左子樹
{
//左子樹的前序中序遍歷序列的end指標都變化了
root->left = ConstructHelper(pre_start+1, left_preorder_end, in_start, root_inorder-1);
}
int* right_preorder_start = left_preorder_end + 1;//前序遍歷中右子樹的最左邊位置
int right_length = pre_end - right_preorder_start + 1;
if(right_length > 0)//構建右子樹
{
root->right = ConstructHelper(right_preorder_start, pre_end, root_inorder+1, in_end);
}
return root;
}
呼叫ConstructHelper函式,生成二叉樹:
BTNode* Construct(int* pre_order, int* in_order, int len)
{
if(pre_order == NULL || in_order == NULL || len <= 0)
{
return NULL;
}
return ConstructHelper(pre_order, pre_order+len-1, in_order, in_order+len-1);
}
主函式呼叫:
int len = 8;
int pre_order[8] = {1,2,4,7,3,5,6,8};
int in_order[8] = {4,7,2,1,5,3,8,6};
BTNode* root = Construct(pre_order, in_order, len);
二.Construct Binary Tree from Inorder and Postorder Traversal(Leetcode-106)