LeetCode—105.从前序与中序遍历序列构造二叉树(Construct Binary Tree from Preorder and Inorder Traversal)——分析及代码(C++)

LeetCode—105.从前序与中序遍历序列构造二叉树[Construct Binary Tree from Preorder and Inorder Traversal]——分析及代码[C++]

  • 一、题目
  • 二、分析及代码
    • 1. 递归
      • (1)思路
      • (2)代码
      • (3)结果
    • 2. 栈迭代(DFS)
      • (1)思路
      • (2)代码
      • (3)结果
  • 三、其他

一、题目

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

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

例如,给出

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

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、分析及代码

1. 递归

(1)思路

前序遍历首先访问的是根节点,而中序遍历中根节点左、右的数字分别对应左、右子树的节点。
结合上述特征,可先找到根节点,再将问题分解为左、右子树的构造,递归求解。

(2)代码

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.empty())
            return NULL;
        return bTree(preorder, inorder, 0, 0, preorder.size());                
    }
    //递归函数, pi前序遍历中当前对应的起始下标,ii中序遍历中当前对应的起始下标,size当前子树规模
    TreeNode* bTree(vector<int>& preorder, vector<int>& inorder, int pi, int ii, int size) {
        if (size == 0)
            return NULL;
        TreeNode* root = new TreeNode(preorder[pi]);//构造当前根节点
        int lsize = ii;
        while (inorder[lsize] != preorder[pi])//寻找左子树部分
            lsize++;
        lsize -= ii;//左子树规模
        int rsize = size - lsize - 1;//右子树规模
        root->left = bTree(preorder, inorder, pi + 1, ii, lsize);
        root->right = bTree(preorder, inorder, pi + lsize + 1, ii + lsize + 1, rsize);
        return root;
    }
};

(3)结果

执行用时 :20 ms, 在所有 C++ 提交中击败了 90.89% 的用户;
内存消耗 :16.7 MB, 在所有 C++ 提交中击败了 45.97% 的用户。

2. 栈迭代(DFS)

(1)思路

先依次添加左节点,并用栈记录添加的节点,到达当前最大深度后(栈顶 == 中序遍历当前值),回退并添加右子树。

(2)代码

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.empty())
            return NULL;
        stack<TreeNode*> stk;//栈存放添加的节点
        TreeNode* root = new TreeNode(preorder[0]);
        stk.push(root);
        int psize = preorder.size(), isize = inorder.size();
        for (int i = 1, j = 0; i < psize && j < isize; i++) {
            TreeNode* back = NULL;
            TreeNode* node = new TreeNode(preorder[i]);//待添加节点
            while (!stk.empty() && stk.top()->val == inorder[j]) {//寻找此时对应的根节点
                back = stk.top();//记录当前对应根节点
                stk.pop();
                j++;
            }
            if (back == NULL)//为左节点
                stk.top()->left = node;
            else //为右节点
                back->right = node;
            stk.push(node);//node成为新的根节点
        }
        return root;        
    }
};

(3)结果

执行用时 :12 ms,在所有 C++ 提交中击败了 99.26% 的用户;
内存消耗 :14.4 MB,在所有 C++ 提交中击败了 99.09% 的用户。

三、其他

暂无。

你可能感兴趣的:(数据结构与算法,LeetCode,C++,题解)