leetcode刷题日记——从前序与中序遍历序列构造二叉树
[ 题目描述 ]:
[ 思路 ]:
- 递归构建,前序遍历是 [ 根节点,左孩子节点,右孩子节点 ],中序遍历是 [ 左孩子节点,根节点,右孩子节点]
- 根据这一特性,可以知道,前序遍历中前面的节点是后面节点的,父亲或祖宗
- 中序遍历中某个节点左边是他的左孩子们,右边是他的右孩子们
- 由此我们对前序遍历的第一个节点开始构建,他一定是父节点,再将他在中序遍历中左边的节点和右边的节点划分出来,用于构建他的左右孩子
- 以构建左孩子为例,求出左边孩子的个数n,由于前序遍历是 根左右 ,也就是说这些孩子一定在前序遍历的前 n+1个节点(第一个节点是父节点),将这 n 个前序遍历的节点和中序遍历的节点顺序列表进行新一轮递归
- 运行如下
# python代码
class Solution(object):def buildTree(self, preorder, inorder):""":type preorder: List[int]:type inorder: List[int]:rtype: Optional[TreeNode]"""if not preorder or not inorder:return Noneroot=TreeNode(preorder[0])val_index=inorder.index(preorder[0])left_inorder=inorder[0:val_index]right_inorder=inorder[val_index+1:]left_preoder=preorder[1:1+len(left_inorder)]right_preoder=preorder[1+len(left_inorder):]root.left=self.buildTree(left_preoder,left_inorder)root.right=self.buildTree(right_preoder,right_inorder)return root
[ 官方题解 ]:
- 方法一:递归,基本同上
- 方法二:迭代,依次枚举前序遍历中除了第一个节点以外的每个节点。如果 index 恰好指向栈顶节点,那么不断地弹出栈顶节点并向右移动 index,并将当前节点作为最后一个弹出的节点的右儿子;如果 index 和栈顶节点不同,则将当前节点作为栈顶节点的左儿子;
- 无论是哪一种情况,最后都将当前的节点入栈。
class Solution:def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:if not preorder:return Noneroot = TreeNode(preorder[0])stack = [root]inorderIndex = 0for i in range(1, len(preorder)):preorderVal = preorder[i]node = stack[-1]if node.val != inorder[inorderIndex]:node.left = TreeNode(preorderVal)stack.append(node.left)else:while stack and stack[-1].val == inorder[inorderIndex]:node = stack.pop()inorderIndex += 1node.right = TreeNode(preorderVal)stack.append(node.right)return root