[LeetCode]前序中序构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

自己AC的代码没了辣鸡LeetCode吞代码就找了个别人博客的,思想是完全一样的

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution 
{
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        return buildTree(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder, int preStart, int preEnd, int inStart, int inEnd) 
    {
        //不要|| inStart > inEnd这个条件也是可以AC的,自己写的没有加
        if (preStart > preEnd || inStart > inEnd) 
            return NULL;
        TreeNode *res;
        res = new TreeNode(preorder[preStart]);
        int flag;
        for (int i = inStart; i <= inEnd; i++) 
        {
            if (preorder[preStart] == inorder[i]) 
            {
                flag = i;
                break;
            }
        }
        //flag - inStart是左子树(在数组中的)长度,这样就好理解很多了
        res->left = buildTree(preorder, inorder, preStart+1, preStart+flag-inStart, inStart, flag-1);
        res->right = buildTree(preorder, inorder, preStart+flag-inStart+1, preEnd, flag+1, inEnd);
        return res;
    }
};

可以看出,前序遍历的第一个节点就是根节点,在中序中找到这个节点即可将其分为左子树和右子树,很明显对左右子树的处理与之相同,因此要递归处理,但怎么递归这个东西就比较麻烦。

一开始想每次都用新数组(vector)来存,后来觉得这样拷贝stl容器费时费空间于是就没有这样做,想到了重写一个函数,参数增加数组的开始和结束点来处理。

preStart和preEnd指前序遍历数组的始末点,inStart和inEnd则是中序遍历数组的,需要注意的事flag-instart才是左子树(在数组中的)长度,而不是flag,之前一直写flag错了很多遍,其他的起始和终止下标较容易理解不做赘述。

虽说题目不太难,但可能因为还没学过数据结构还是花了好久才写出来。

 

补充:根据中序和后序建立二叉树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution 
{
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) 
    {
        return buildTree(inorder, postorder, 0, inorder.size() - 1, postorder.size() - 1, 0);
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder, int inStart, int inEnd, int postEnd, int postStart) 
    {
        if (inStart > inEnd || postEnd < postStart) 
        {
            return NULL;
        }
        int flag;
        TreeNode *res = new TreeNode(postorder[postEnd]);
        for(int i=inStart;i<=inEnd;i++)
        {
            if(postorder[postEnd]==inorder[i])
            {
                flag=i;
                break;
            }
        }
        res->right=buildTree(inorder,postorder,flag+1,inEnd,postEnd-1,postEnd-(inEnd-flag));
        res->left=buildTree(inorder,postorder,inStart,flag-1,postEnd-(inEnd-flag)-1,postStart);
        return res;
    }
};

与之思想类似,不过根据后序建立的顺序则应该是从后向前的,后序遍历的数组从后向前依次为根节点,右子树的根节点和左子树的根节点,而前序数组则是从前往后依次为根节点,左子树根节点和右子树根节点,相应改变递归参数即可,此时inEnd-flag为右子树(在数组中的)长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值