7.重建二叉树

问题描述:

input:两个数组pre,vin

output:指向重建出的二叉树的根节点的指针root

根据二叉树的前序和中序遍历得到的数组,重建出二叉树

解法:

思想:

递归建立二叉树的左右子树

利用前序遍历序列的特点:第一个数即为左(右)子树的根节点

利用中序遍历序列的特点:根节点将整个序列划分为左右子树

利用中序遍历序列确定左右子树节点的数量

步骤:

(1)根据在前序序列中得到的根节点,并在中序序列中找到根节点所在的位置

(2)根节点将中序序列分为左右两部分,根据左右子树中节点的数量,在前序序列中也找到左右子树节点的划分

(3)递归建立当前节点的左右子树(通过将pre和vin的节点索引传入)

own:

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        if(pre.size() == 0)
            return NULL;
        TreeNode* root = NULL;
        root = helper(pre, vin, 0, pre.size() - 1, 0, vin.size() - 1);
        return root;
    }
    
    //递归建树
    TreeNode* helper(const vector<int> &pre,
                     const vector<int> &vin, 
                     int b1, int e1,
                     int b2, int e2
                     )
    {
        if(b1 > e1 && b2 > e2)
            return NULL;
        TreeNode* root = new TreeNode(pre[b1]);
        if(b1 == e1)
            return root;
       //在中序数组中查找根节点
        int sub_root;
        for(int i = 0; i < vin.size(); i++)
        {
            if(vin[i] == pre[b1])
            {
                sub_root = i;
                break;
            }
        }
        root->left = helper(pre, vin, b1 + 1, b1 + sub_root - b2, b2, sub_root - 1);
        root->right = helper(pre, vin, b1 + sub_root - b2 + 1, e1,  sub_root + 1, e2);
        return root;
    }
};

剑指offer:

注意当子树的节点数量为1时,直接返回新建的节点,递归终止;记得判断此时pre和vin中的这个节点值是否相同,如果不相同说明pre或者vin数组错误,要抛出异常

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        if(pre.size() == 0 || vin.size() == 0)
            return NULL;
        TreeNode* root = NULL;
        root = helper(pre, vin, 0, pre.size() - 1, 0, vin.size() - 1);
        return root;
    }
    
    //递归建树
    TreeNode* helper(const vector<int> &pre,
                     const vector<int> &vin, 
                     int b1, int e1,
                     int b2, int e2
                     )
    {
        if(b1 > e1 && b2 > e2)
            return NULL;
        TreeNode* root = new TreeNode(pre[b1]);
        //***********************change1
        //if(b1 == e1)
        //    return root;
        if(b1 == e1)
        {
            if(b2 == e2 && pre[b1] == vin[b2])
            {
                return root;
            }
            else
            {
                throw "invaild input";
            }
        }
        //***********************change1
        
       //在中序数组中查找根节点
        int sub_root = b1;//***********************
        for(int i = 0; i < vin.size(); i++)
        {
            if(vin[i] == pre[b1])
            {
                sub_root = i;
                break;
            }
        }
        
        //***********************change2
        //注意input数组错误的问题,在中序序列里找不到对应节点
        if(sub_root == e2 && vin[sub_root] != pre[b1])
            throw "invaild input";
        //***********************change2
        
        //***********************change3
        //让代码更整洁易读
        int leftsub_length = sub_root - b2;
        int leftsub_end = b1 + leftsub_length;
        //***********************change3
        
        if(leftsub_length > 0)//***********************加入条件判断
        {
            root->left = helper(pre, vin, b1 + 1, leftsub_end, b2, sub_root - 1);
        }
        int rightsub_length = e2 - b2 - leftsub_length;
        if(rightsub_length > 0)//***********************加入条件判断
        {
            root->right = helper(pre, vin, leftsub_end + 1, e1,  sub_root + 1, e2);
        }
        return root;
    }
};

猜你喜欢

转载自blog.csdn.net/u012370185/article/details/89702718