五一一师兄结婚
去给他当了伴郎
师兄家是在孝感的
发现那边的习俗真的是和我老家不一样
吃饭得吃三天
等等等等
还是挺好玩的!
话不多说,直接上我和我朋友的合照
啊哈哈哈哈哈哈哈
105-从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/
9 20
/
15 7
思路:
首先我们都知道先序遍历的递归定义是 根-左-右,中序遍历的定义为 左-中-右。
其实如果给你,前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7],大部分人能直接把这棵树徒手画出来,思路大致为:先序遍历的第一个节点是根节点,再找到它在中序遍历中的位置,那么左右子树就找到了,接着重复上述步骤直到结束。那么用代码该怎么表示呢。
所以我们先要有四个参数:l1,r1,l2,r2,[l1, r1]代表先序遍历序列,[l2, r2]代表后序遍历序列。而[l1]就是根节点,接着我们找到[l1]在[l2, r2]中的位置mid,lsize = mid - l2 就是左子树的长度,rsize = r2 - mid 就是右子树的长度。我们可以通过以上信息可以得到子树在先序和中序遍历中的“起止索引”,接着递归处理(其实也可以用栈来处理)
代码如下:
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if preorder is None or inorder is None:
return None
# 定义一链表用来记录中序序列中元素的下标值
dict_in = {}
for index, value in enumerate(inorder):
dict_in[value] = index
length = len(preorder)-1
# 使用深度遍历方法遍历
def dfs(pre_start, pre_end, in_start, in_end, preorder,inorder,dict_in):
if pre_end >= pre_start and in_end >= in_start:
root = TreeNode(preorder[pre_start])
# 求得根节点的val值在中序序列中的下标值
mid_index = dict_in[preorder[pre_start]]
# 分别求得左、右子树的长度
l_len = mid_index - in_start
r_len = in_end - mid_index
# 求得根节点root的左子树
root.left = dfs(pre_start+1,pre_start+l_len,in_start,
in_start+l_len-1, preorder, inorder,dict_in)
root.right = dfs(pre_start+l_len+1,pre_start+l_len+r_len,mid_index+1,
mid_index+r_len, preorder, inorder,dict_in)
return root
return dfs(0, length, 0, length, preorder, inorder, dict_in)
if __name__ == "__main__":
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]
BTree = Solution().buildTree(preorder, inorder)
print(BTree)
执行效率还是挺不错的,在90%以上。
2019/5/5 更新
上面那种方法的参数好像偏多,我估计很多人都晕乎了。突然get到一种参数很少的方法,想来分享一波。其实本题的核心算法还是动态规划方法,对这个算法思想还不熟悉的读者可以看看我之前写的一篇博文。
程小新同学:动态规划方法心得zhuanlan.zhihu.com于本题而言,就是不停找一个节点的左子树和右子树的问题,如下图所示:
代码如下:
class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if len(preorder) == 0:
return
# 获得根节点在中序序列中的下标值
mid_index = inorder.index(preorder[0])
# 开始创建节点
root = TreeNode(preorder[0])
# preorder[1:mid_index+1], inorder[:mid_index] 对应着先序序列和中序序列的左子树的值
root.left = self.buildTree(preorder[1:mid_index+1], inorder[:mid_index])
# preorder[mid_index+1:], inorder[mid_index+1:] 对应着先序序列和中序序列的右子树的值
root.right = self.buildTree(preorder[mid_index+1:], inorder[mid_index+1:])
return root
if __name__ == "__main__":
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]
BTree = Solution().buildTree(preorder, inorder)
print(BTree)
不过执行效率有些低,在50%左右。