如题:
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
套路题,考察你有没有学习过这种题型。同样的问题还有知道中序与后序构造二叉树(leetcode 106)。我们知道,前序遍历所得序列从左至右依次是:根节点,跟左子树根节点.....右子树根节点。和后序正好相反,后序遍历所得序列从后往前依次是根节点,根右子树根节点...左子树根节点。因为题目保证没有重复数字,知道了根节点,就可以从中序遍历中找到对应下标i,根据中序遍历性质,i左边的数列表示左子树,i右边的数列表示右子树。这样,我们知道了根结点后,递归从中序数列中分别查找左子树的根结点和右子树根结点即可。
示例中给出的前序遍历数列为【3,9,20,15,7】,由下面的二叉树可以观察到,结点3为根结点,9为3的左子树根结点,20为3右子树根结点。15为20左子树根结点,7为20右子树根结点。递归查找顺序由此可得,先左子树后右子树。总的来说就是找根结点的过程。没有看懂的同学可以结合下面的代码看下:
//这道题和已知中序于后序遍历求二叉树类似,仅仅方向不同,递归求解即可
struct TreeNode *findSubRoot(int* preorder, int* inorder, int *preOrderEnd, int inStart, int inEnd)
{
int i, val;
struct TreeNode *root, *left, *right;
//中序序列找不到,说明是一个空节点
if (inStart > inEnd)
return NULL;
//从前序遍历中取出根节点的值
val = preorder[*preOrderEnd];
//指向下一个子树的根节点
*preOrderEnd = *preOrderEnd + 1;
//找到val节点的左子树和右子树范围
for (i = 0; i <= inEnd; i++)
if (inorder[i] == val)
break;
//找到val的左子树与右子树,顺序不能反,先左后右
left = findSubRoot(preorder, inorder, preOrderEnd, inStart, i - 1);
right = findSubRoot(preorder, inorder, preOrderEnd, i + 1, inEnd);
//组合
root = (struct TreeNode *)calloc(1, sizeof(struct TreeNode));
root->val = val;
root->left = left;
root->right = right;
return root;
}
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
//前序遍历从前往后依次是根结点
int preOrderEnd = 0;
return findSubRoot(preorder, inorder, &preOrderEnd, 0, inorderSize - 1);
}
=============================================================================================
Linux应用程序、内核、驱动开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。