【劍指offer】面試題7:重建二叉樹【C++版本】
阿新 • • 發佈:2019-02-02
題目:
重建二叉樹
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹(假設沒有重複數字)。樹節點定義如下:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
};
解題思路:
1.前序遍歷的第一個數字總是樹的根節點的值。但在中序遍歷中,根節點的值在序列的中間,其中左子樹的節點的值位於根節點的值的左邊,右子樹的節點的值位於根節點的值的右邊。要掃描中序遍歷序列,才能找到根節點的值。
2.又因為前序遍歷總是在根節點後先遍歷完左子樹,才會遍歷右子樹,所以由後續遍歷推斷出左子樹中節點的數目之後,前序遍歷中根節點之後的相同數目的值都是左子樹的節點的值。剩下的就是右子樹的值。這樣就分別找到了左右子樹序列。
3.分別確定了根節點和左右子樹的前序、中序遍歷,我們可以用同樣的方法構建左右子樹,剩下的可以用遞迴來完成。
可以AC的解法【C++版本】
#include <vector>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <algorithm>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
};
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin);
int main()
{
vector<int> pre{1,2,4,5,3,6,7};
vector <int> vin{4,2,5,1,6,3,7};
TreeNode *newRoot = reConstructBinaryTree(pre, vin);
system("pause");
return 0;
}
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin)
{
if (pre.size() == 0 || pre.size() != vin.size())
return nullptr;
int root = pre[0];
TreeNode *newNode = new TreeNode(root);
//如果只剩一個節點了,那麼可以直接返回
if (pre.size() == 1)
return newNode;
auto posi = find(vin.begin(), vin.end(), root);
//錯誤檢測
if (posi == vin.end()) {
return nullptr;
}
int leftSize = posi - vin.begin();
int rightSize = vin.end() - posi - 1;
//遞迴求解
//這裡取前序和後序遍歷的左右子樹可能有點繞,可以好好思考一下
newNode->left = reConstructBinaryTree(vector<int>(pre.begin() + 1, pre.begin() + 1 + leftSize),
vector<int>(vin.begin(), vin.begin() + leftSize));
newNode->right = reConstructBinaryTree(vector<int>(pre.begin() + 1 + leftSize, pre.end()),
vector<int>(vin.begin() + leftSize + 1, vin.end()));
return newNode;
}