LeetCode从前序与中序遍历序列构造二叉树
给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。
示例 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
示例 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]
思路:
从两个遍历序列中构造出二叉树是一个非常经典的考题了,大学课上学数据结构的时候应该都有学过。一般就两种搭配方式,一种就是这一题的前序+中序;还有一种就是后序+中序。可以发现要恢复一棵二叉树,中序是一定要有的,因为中序遍历是“左中右”,“中”可以把“左”和“右”分开,我们方便知道“左”和“右”的长度。
具体来看,给了前序遍历“中左右”和中序遍历“左中右”的顺序,我们首先根据前序遍历得到根节点(第一个)。其次,我们通过根节点去中序遍历中定位它的位置,一旦定位到,它左边全部就是“左”的长度,右边全部就是“右”的长度。最后,我们拿到这个长度回到前序遍历去截取,就可以得到前序遍历的“左”是哪些,“右”是哪些。
拿到前序遍历的“左”之后,我们与中序遍历的“左”进行比较分析,我们知道前者依然是个前序遍历结果,后者依然是个中序遍历结果——问题又回到了“从前序遍历和中序遍历序列构造二叉树”!只不过我们的序列比原问题缩短了。就是通过这样一点点缩小问题,知道缩小至我们的base caes,递归结束,问题解决。
代码:
class Solution(object):
def buildTree(self, preorder, inorder):
#定义base case 前序遍历或中序遍历列表有任何一个是空,则要么不合法要么遍历结束,直接return
if not preorder or not inorder:return
#拿到根节点,也就是“中”
ro = preorder[0]
root = TreeNode(ro)#将它构造成根节点
#根节点的“左”,需要把两个列表的“左”拿出来放入递归生成
root.left = self.buildTree(preorder[1:inorder.index(root.val)+1],inorder[:inorder.index(root.val)])
#根节点的“右”,需要把两个列表的“右”拿出来放入递归生成
root.right = self.buildTree(preorder[inorder.index(root.val)+1:],inorder[inorder.index(root.val)+1:])
return root
小结:
我们之所以可以写出这么简洁的代码,是因为我们使用python提供的非常方便的index函数。Index函数可以定位到元素并返回下标,至于细节上如+1等操作,结合前序、中序的顺序就很清楚了,就是为了定位到具体的“左”和具体的“右”而已。
需要注意的是:在这种题中,虽然题目没有给出,但默认二叉树是没有重复元素的,因为一旦有重复元素,我们就无法在中序遍历中定位到根节点了(因为有很多这样的值,并且index功能只能定位到第一个)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了