如题,根据前序与中序遍历序列构造二叉树
整体思路:
① 前序遍历的第一个元素,必然是二叉树的根节点
② 在中序遍历中找到前序遍历第一个元素的位置
③ 该位置左边的所有点都是二叉树的左子树元素,该位置右边的所有点都是二叉树的右子树元素
思路一:递归+字典
由整体思路可以构建子函数用于递归,不断求子树的左右子树,直到叶子节点。
代码如下:
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
from typing import List
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
inorder_dic = {val: i for i, val in enumerate(inorder)} #求每个字母在中序遍历中的位置
print(inorder_dic)
# 递归求解子树的左右子树,直到叶子节点
# pre1, pre2, in1, in2 分别表示子树在前序遍历和中序遍历序列的开始位置和结束位置
def buildSubTree(pre1, pre2, in1, in2, inorder_dic):
# 子序列只有一个元素,说明是叶子节点了,返回该节点
if pre1 == pre2:
return TreeNode(preorder[pre1])
if pre1 > pre2:
return None
# 前序遍历子序列的第一个元素,表示该子树的根节点,用top存放
top = preorder[pre1]
# 构建子树
tree = TreeNode(top)
# 获得该子树的根节点在中序遍历序列的位置
location = inorder_dic[top]
# 求该子树的左子树
# pre1 = pre+1; pre2 = pre1 + (location - in1);
# (location - in1)表示左子树的元素个数,子树根节点在中序遍历的位置减去中序遍历初始位置
# in1 = in1; in2 = location -1
tree.left = buildSubTree(pre1+1, pre1+(location-in1), in1, location-1, inorder_dic)
# 求该子树的右子树
# pre1 = pre1 + (location - in1) + 1; pre2 = pre2;
# 前序遍历初始位置加上左子树元素数后及根节点+1,为右子树前序遍历初始位置
# in1 = location + 1; in2 = in2
tree.right = buildSubTree(pre1+(location-in1)+1, pre2, location+1, in2, inorder_dic)
return tree
return buildSubTree(0, len(preorder) - 1, 0, len(inorder) - 1, inorder_dic)
if __name__ == "__main__":
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
print(Solution.buildTree("", preorder, inorder))
思路二:栈+迭代+字典
【该思路来自LeetCode题解】
我们用一个栈保存已经遍历过的节点,遍历前序遍历的数组,一直作为当前根节点的左子树,直到当前节点和中序遍历的数组的节点相等了,那么我们正序遍历中序遍历的数组,倒着遍历已经遍历过的根节点(用栈的 pop 实现),找到最后一次相等的位置,把它作为该节点的右子树。
作者:windliang
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by–22/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
代码如下:
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder.length == 0) {
return null;
}
Stack<TreeNode> roots = new Stack<TreeNode>();
int pre = 0;
int in = 0;
//先序遍历第一个值作为根节点
TreeNode curRoot = new TreeNode(preorder[pre]);
TreeNode root = curRoot;
roots.push(curRoot);
pre++;
//遍历前序遍历的数组
while (pre < preorder.length) {
//出现了当前节点的值和中序遍历数组的值相等,寻找是谁的右子树
if (curRoot.val == inorder[in]) {
//每次进行出栈,实现倒着遍历
while (!roots.isEmpty() && roots.peek().val == inorder[in]) {
curRoot = roots.peek();
roots.pop();
in++;
}
//设为当前的右孩子
curRoot.right = new TreeNode(preorder[pre]);
//更新 curRoot
curRoot = curRoot.right;
roots.push(curRoot);
pre++;
} else {
//否则的话就一直作为左子树
curRoot.left = new TreeNode(preorder[pre]);
curRoot = curRoot.left;
roots.push(curRoot);
pre++;
}
}
return root;
}
作者:windliang
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--22/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。