【LeetCode & 剑指offer刷题】树题12:7 重建二叉树(系列)

【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

105. Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
Return the following binary tree:
3
/ \
9 20
    / \
    15 7
 
/**
 * 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 buildOneLevel(preorder, 0, preorder.size()-1,inorder, 0 ,inorder.size()-1);
    }
   
    //递归函数功能:构建树的某一层结构
    TreeNode* buildOneLevel(vector<int>& preorder, int pre_begin, int pre_end, vector<int>& inorder, int in_begin, int in_end)//这里用下标法,需要6个形参,也可以用迭代器只需4个形参
    {
       
        if(pre_begin>pre_end || in_begin>in_end) return NULL; //递归子函数的出口
       
        //先找根节点(用前序遍历序列)
        TreeNode* root = new TreeNode(preorder[pre_begin]);
       
        //在找左子树和右子树(用中序遍历序列)
        int left_length = 0; //左子树长度
        for(int i = in_begin; i<= in_end; i++)
        {
            if(inorder[i] == root->val)
            {
                left_length = i;
                break; //先找到中序遍历序列中根节点的位置
            }
        }
        left_length -= in_begin; //左子树长度
       
        root->left = buildOneLevel(preorder, pre_begin+1, pre_begin+left_length, inorder, in_begin, in_begin+left_length-1);//左子树
        root->right = buildOneLevel(preorder, pre_begin+left_length+1, pre_end, inorder,in_begin+left_length+1,in_end); //右子树
       
        return root; //递归母函数的出口
               
    }
};*/
#include <algorithm>
class Solution
{
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
    {
        return buildOneLevel(preorder.begin(), preorder.end(), inorder.begin(), inorder.end()); //!!注意end指向容器末尾(最后一个元素的下一个位置)
    }
   
    //递归函数功能:构建树的某一层结构
 //   template<typename iterator> //也可直接用vector<int>::iterator类型,模板可以进行类型延伸(泛型编程),避免不同类型写多个函数(自己的思考),但函数内部的很多变量名需用auto
    using iter = vector<int>::iterator;//为便于书写,也可使用类型别名 (同typedef)
    TreeNode* buildOneLevel(iter pre_begin, iter pre_end, iter in_begin, iter in_end)
    {
       
        if(pre_begin == pre_end || in_begin == in_end) return nullptr; //递归出口一(除结尾外还需要一个内部return,即两个return吧)
       
        //找根节点用前序遍历序列)
        TreeNode* root = new TreeNode(*pre_begin); //前序遍历序列首元素即为根结点
       
        //在找左子树和右子树(用中序遍历序列) (具体只用求左子树序列长度就可以了)
        vector<int>::iterator in_root_pos = find(in_begin, in_end, root->val); //先找到中序遍历序列中根节点的位置 (由于序列中不含重复元素,故可以用此方法)
        int left_length = in_root_pos - in_begin; //左子树序列长度
       
        root->left = buildOneLevel(pre_begin+1, pre_begin+left_length+1, in_begin, in_root_pos);//左子树(对于顺序容器的迭代器可以直接加某个常数,其他容器迭代器需用distance、next等函数)
        root->right = buildOneLevel(pre_begin+left_length+1, pre_end, in_root_pos+1, in_end); //右子树
       
        // !!注意end指向容器末尾(最后一个元素的下一个位置)
       
        return root; //递归出口二
               
    }
};
 
106. Construct Binary Tree from Inorder and Postorder Traversal
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
3
/ \
9 20
    / \
    15 7
 
/**
 * 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 build(postorder.begin(), postorder.end(), inorder.begin(), inorder.end());
    }
private:
    using iter = vector<int>::iterator; //类型别名
    TreeNode* build(iter post_begin, iter post_end, iter in_begin, iter in_end)
    {
        if(post_begin == post_end || in_begin == in_end) return nullptr;
       
        //先找根结点(后序遍历最一个元素)
        TreeNode* root = new TreeNode(*(post_end-1)); //注意容器的end迭代器指向最后一个元素的下一个位置,而非最后一个元素!!
       
       // cout<<root->val<<endl;
        //再找左右子树(通过中序遍历,找到左右子树的分割点,求出左子树的长度)
        vector<int>::iterator in_root_pos = find(in_begin, in_end, root->val); //同过迭代器将STL中容器与算法联系起来
        int left_length = in_root_pos - in_begin;
       
        //左子树
        root->left = build(post_begin, post_begin + left_length, in_begin, in_root_pos);
        //右子树
        root->right = build(post_begin + left_length, post_end - 1, in_root_pos + 1, in_end);
       
        return root;
    }
};
 
 

 

posted @ 2019-01-05 19:47  wikiwen  阅读(462)  评论(0编辑  收藏  举报