剑指Offer之重建二叉树

版权声明:所有的博客都是作为个人笔记的。。。。。。 https://blog.csdn.net/qq_35976351/article/details/82779869

问题描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解题思路

该题目用到了递归分治的思想。先序遍历二叉树的第一个节点肯定是根节点,那么在中序序列中找到先序的对应数据的下标。根据前序和中序遍历的性质可知,下标左侧的数据是左子树,下标右侧的数据是右子树。同时,下标左侧元素的个数是左子树元素的个数,所以根据这个来划分先序序列的左子树部分;下标右侧的数据的个数是右子树元素的个数,同理划分前序序列右子树部分。递归的求解左右子树,把子序列放入递归函数中求解。递归终止的情况是没有数据可以划分了,此时返回空值。

AC代码

代码中需要注意的是vector的下标,这是最容易出错的地方,没有把握的情况就找一个简单的例子测试一下。还有,递归的时候vector的数据是拷贝的,这对效率有一定的影响,不过题目是这么给的,肯定不会超时了。

提交代码

/**
 * 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 nullptr;
        }
        int r = 0;
        for(r = 0; r < vin.size(); r++) {  // 找根节点
            if(pre[0] == vin[r]) {
                break;
            }
        }
        TreeNode *root = new TreeNode(pre[0]);
        vector<int>preleft(pre.begin() + 1, pre.begin() + r + 1); // 左子树前序
        vector<int>vinleft(vin.begin(), vin.begin() + r);    // 左子树前序中序
        vector<int>preright(pre.begin() + r + 1, pre.end()); // 右子树前序
        vector<int>vinright(vin.begin() + r + 1, vin.end()); // 右子树中序
        root->left = reConstructBinaryTree(preleft, vinleft);
        root->right = reConstructBinaryTree(preright, vinright);
        return root;
    }
};

本地测试代码

#include <iostream>
#include <vector>
using namespace std;
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

// 前序序列建树,空节点输入0
TreeNode* createTree() {
    int n;
    cin >> n;
    if(n == 0) {
        return nullptr;
    }
    TreeNode* r = new TreeNode(n);
    r->left = createTree();
    r->right = createTree();
}

// 前序遍历
void preOrder(TreeNode* root) {
    if(root == nullptr) {
        return;
    }
    cout << root->val << " ";
    preOrder(root->left);
    preOrder(root->right);
}

class Solution {
  public:
    TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
        if(pre.size() == 0 || vin.size() == 0) {
            return nullptr;
        }
        int r = 0;
        for(r = 0; r < vin.size(); r++) {  // 找根节点
            if(pre[0] == vin[r]) {
                break;
            }
        }
        TreeNode *root = new TreeNode(pre[0]);

        vector<int>preleft(pre.begin() + 1, pre.begin() + r + 1); // 左子树前序
        vector<int>vinleft(vin.begin(), vin.begin() + r);    // 左子树前序中序
        vector<int>preright(pre.begin() + r + 1, pre.end()); // 右子树前序
        vector<int>vinright(vin.begin() + r + 1, vin.end()); // 右子树中序
        root->left = reConstructBinaryTree(preleft, vinleft);
        root->right = reConstructBinaryTree(preright, vinright);
        return root;
    }
};

int main() {
//  这里是自己建树测试
//  TreeNode *r=createTree();
//  preOrder(r);
//  测试题目数据
    vector<int>pre{1, 2, 3, 4, 5, 6};
    vector<int>vin{3, 2, 4, 1, 6, 5};
    Solution so = Solution();
    TreeNode *r = so.reConstructBinaryTree(pre, vin);
    preOrder(r);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35976351/article/details/82779869