1. 程式人生 > >面試題6:根據前序和中序序列構建二叉樹(Leetcode-106)

面試題6:根據前序和中序序列構建二叉樹(Leetcode-106)

題目:輸入二叉樹的前序遍歷和中序遍歷序列,重構其二叉樹,假設輸入的數字都是不重複的。
例如前序序列是 {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)