LeetCode从前序与中序遍历序列构造二叉树

105. 从前序与中序遍历序列构造二叉树

给定一棵树的前序遍历 preorder 与中序遍历  inorder。请构造二叉树并返回其根节点。

示例 1:

LeetCode从前序与中序遍历序列构造二叉树_第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功能只能定位到第一个)。

 

你可能感兴趣的:(leetcode,算法,职场和发展)