题目
(1)给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
(2)示例如下:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
解决思路
- 思路:采用递归思想解决。
- 本题中递归函数表示的意义:找到根节点并建立左右子树。
- 具体步骤:
- 第一步:找到根节点的位置以及左子树和右子树对应的点(前序遍历的第一个节点为根节点,中序遍历中根节点左边的点为左子树对应的点,根节点右边的点为右子树对应的点)。
- 第二步:递归建立左子树。
- 第三步:递归建立右子树。
代码
- C++代码:
# include <stdio.h>
# include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(): val(0), left(nullptr), right(nullptr) {}
TreeNode(int _val): val(_val), left(nullptr), right(nullptr) {}
TreeNode(int _val, TreeNode* _left, TreeNode* _right): val(_val), left(_left), right(_right) {}
};
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (0 == preorder.size() || 0 == inorder.size()) {
return nullptr;
}
int position = 0; // 记录根节点的位置
// 遍历中序序列,找到根节点的位置(前序遍历的第一个元素是根节点)。
while (inorder[position] != preorder[0]) {
position++;
}
vector<int> preorder_l, inorder_l; // 存储左子树的前序遍历和中序遍历序列
vector<int> preorder_r, inorder_r; // 存储右子树的前序遍历和中序遍历序列
// 找到前序遍历和中序遍历中左子树的节点(中序遍历中,根节点左边的节点为左子树中的节点)。
for (int i = 0; i < position; i++) {
preorder_l.push_back(preorder[i + 1]); // 前序遍历序列的第一个元素根节点,因此是i + 1
inorder_l.push_back(inorder[i]); // 中序遍历序列中,根节点前面的数为左子树中的节点
}
// 找到前序遍历和中序遍历中右子树的节点(中序遍历中,根节点右边的节点为右子树的节点)。
for (int i = position + 1; i < inorder.size(); i++) {
preorder_r.push_back(preorder[i]);
inorder_r.push_back(inorder[i]);
}
// 递归建立左子树和右子树。
TreeNode* root = new TreeNode(inorder[position]);
root->left = buildTree(preorder_l, inorder_l);
root->right = buildTree(preorder_r, inorder_r);
return root;
}
};
class MySolution {
public:
void myPreOrder(TreeNode* root, vector<int>& answer) {
if (nullptr == root) {
return;
}
answer.push_back(root->val);
myPreOrder(root->left, answer);
myPreOrder(root->right, answer);
}
// 前序遍历树,并将结果保存在数组中
vector<int> preOrder(TreeNode* root) {
if (nullptr == root) {
return vector<int> ();
}
vector<int> answer;
myPreOrder(root, answer);
return answer;
}
};
int main() {
vector<int> preorder = {3, 9, 20, 15, 7};
vector<int> inorder = {9, 3, 15, 20, 7};
Solution* solution = new Solution();
TreeNode* ret = solution->buildTree(preorder, inorder);
MySolution* mysolution = new MySolution();
vector<int> answer = mysolution->preOrder(ret);
for (auto ans: answer) {
printf("%d ", ans);
}
printf("\n");
return 0;
}
- Python代码
# -*- coding: utf-8 -*-
from typing import List
class TreeNode:
def __init__(self, _val=0, _left=None, _right=None):
self.val = _val
self.left = _left
self.right = _right
class Solution:
def __init__(self):
pass
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if 0 == len(preorder) or 0 == len(inorder):
return None
position: int = 0 # 记录根节点的位置
# 遍历中序序列,找到根节点的位置(前序遍历的第一个元素是根节点)。
while inorder[position] != preorder[0]:
position += 1
# 存储左子树和右子树的前序遍历和中序遍历序列
preorder_l, inorder_l, preorder_r, inorder_r = [], [], [], []
# 找到前序遍历和中序遍历中左子树的节点(中序遍历中,根节点左边的节点为左子树中的节点)。
for i in range(position):
preorder_l.append(preorder[i + 1]) # 前序遍历序列的第一个元素根节点,因此是i + 1
inorder_l.append(inorder[i]) # 中序遍历序列中,根节点前面的数为左子树中的节点
# 找到前序遍历和中序遍历中右子树的节点(中序遍历中,根节点右边的节点为右子树的节点)。
for i in range(position + 1, len(preorder)):
preorder_r.append(preorder[i])
inorder_r.append(inorder[i])
# 递归建立左子树和右子树。
root = TreeNode(preorder[0])
root.left = self.buildTree(preorder_l, inorder_l)
root.right = self.buildTree(preorder_r, inorder_r)
return root
class MySolution:
def __init__(self):
pass
def myPreorder(self, root: TreeNode, answer: List[int]):
if not root:
return
answer.append(root.val)
self.myPreorder(root.left, answer)
self.myPreorder(root.right, answer)
# 前序遍历树,并将结果保存在数组中
def preorder(self, root: TreeNode):
if not root:
return []
answer = []
self.myPreorder(root, answer)
return answer
def main():
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]
solution = Solution()
ret: TreeNode = solution.buildTree(preorder, inorder)
mysolution = MySolution()
ans = mysolution.preorder(ret)
print(ans)
if __name__ == "__main__":
main()
说明
- 对应LeetCode第105题。
- LeetCode链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/