2021-02-05 前序中序遍历生成树

题目 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

示例:
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

解1 递归解法

前序:{根,{左子树},{右子树}}
中序:{{左子树},根,{右子树}}

  1. 通过一个计数指针nCount,遍历前序链表的值
  2. 获取中序序列中,前序序列中nCount所指元素的位置index(为了提高效率,这里可以通过遍历一遍中序序列建哈希表,将位置和值对应)
  3. index左边为左子树遍历,右边为右子树遍历
  4. 将nCount++,从前序中获取左子树的根,中序中获取左子树的遍历子串,递归处理左子树;左子树处理完毕后,同理递归处理右子树。
class Solution {
public:
    int nCount = -1;
    unordered_map<int,int> inorder_map;
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
    {
    	//中序遍历建立哈希映射表,不用多次遍历了
        for(int i=0 ; i<inorder.size() ; i++)
        {
            inorder_map[inorder[i]] = i;
        }
        return Dfs(preorder,inorder,0,inorder.size()-1);
    }
    TreeNode* Dfs(vector<int>& preorder, vector<int>& inorder,int begin , int end)
    {
    	//1. 异常处理
    	//1.1 子串不存在
        if(begin > end) return NULL;
	    //2. 逻辑处理
	    //前序序列指针+1
        nCount++;
        //创建结点
        TreeNode* pNode = new TreeNode;
        pNode->val = preorder[nCount];
        pNode->left = NULL;
        pNode->right = NULL;
        //如果只有一个元素
        if(begin == end) return pNode;
        //如果有多个元素,在中序中找该节点位置
        int index = inorder_map[preorder[nCount]];
        //3. 递归处理左子树,中序遍历中左子树子串:begin~index-1;
        pNode->left = Dfs(preorder,inorder,begin , index-1);
        //4. 递归处理右子树,中序遍历中右子树子串:index+1~end;
        pNode->right = Dfs(preorder,inorder,index+1,end);
        return pNode;
    }
};

解2 迭代法

借助栈实现

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
    {
    	//异常处理
        if(preorder.size() == 0) return NULL;
        stack<TreeNode*> S;
        //遍历中序序列指针
        int pIn(0);
        //遍历前序序列指针
        int i = 0;
        //生成根节点,并入栈,并通过pHead标记树根
        TreeNode* pHead = new TreeNode(preorder[0]);
        //额外的变量
        TreeNode* pNode = NULL;
        S.push(pHead);
        for(int i=1 ; i<preorder.size() ; i++)
        {
            //如果栈顶结点(即上一个遍历的结点)不等于pIn结点,说明栈顶结点还有左孩子,将左孩子入栈
            if(S.top()->val != inorder[pIn])
            {
                //生成新节点
                pNode = S.top();
                pNode->left = new TreeNode(preorder[i]);
                //栈顶元素的左孩子入栈
                 S.push(pNode->left);
            }
            //若相等,说明左孩子遍历到头
            else
            {
            	//开始遍历中序序列,比较pIn所指元素是否和栈顶相等,
            	//相等则pIn所指元素为其父节点左孩子,出栈
                 while(!S.empty() && S.top()->val == inorder[pIn])
                {
                    //出栈
                    pNode = S.top();
                    S.pop();
                    pIn++;
                }
                //不相等则pIn所指元素为其父节点的右孩子,父节点是上一个出栈结点
                pNode->right = new TreeNode(preorder[i]);
                //将该节点入栈
                S.push(pNode->right);
            }
        }
        return pHead;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值