目录
#刷题记录#
今天来分享三道关于二叉树的算法题
对应力扣:
1.最大二叉树
2.从前序与中序遍历序列构造二叉树
105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
3.从中序与后序序列构造二叉树
106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
这三道题的共性都是通过列表创建二叉树,需要涉及到对数组切分然后根据子数组创建二叉树的操作。
我们一起来看:
1.最大二叉树
1.1题目描述
1.2 思路
既然要求我们每次找出最大值,然后左右子列表的最大值,我们很自然的想到递归来解决,每次找出当前列表最大值,按照最大值索引,切分左右列表,再次进行操作。
(1)确定输入和输出:
输入的是nums数组,输出自然是根节点root
(2) 确定递归终止条件/也可以理解为特殊情况处理:
if not nums:
return None
(3)确定中间过程
首先我们需要找出最大值的下标索引并创建根节点
然后根据最大索引对列表进行切分即可,左列表到最大值索引的左边一个索引,切片操作右边的索引不包含,所以我们可以写nums[:max_index],右列表的左边到最大值索引的右边一个索引,切片操作冒号左边会包含当前索引,所以我们写成nums[max_index+1:]
# 最大值的下标
max_index = nums.index(max(nums))
# 创建根节点
root = TreeNode(val = nums[max_index])
# 根据最大值索引对列表进行切分
left_nums = nums[:max_index]
right_nums = nums[max_index+1:]
之后分别求得左右节点
root.left = self.constructMaximumBinaryTree(left_nums)
root.right = self.constructMaximumBinaryTree(right_nums)
(4)汇总
class Solution(object):
def constructMaximumBinaryTree(self, nums):
"""
:type nums: List[int]
:rtype: TreeNode
"""
# 处理特殊情况/二叉树的终止条件
if not nums:
return None
# 确定最大值所在下标
max_index = nums.index(max(nums))
# 创建根节点
root = TreeNode(val = nums[max_index])
# 对数组进行切分
left_nums = nums[:max_index]
right_nums = nums[max_index+1:]
# 左右节点
root.left = self.constructMaximumBinaryTree(left_nums)
root.right = self.constructMaximumBinaryTree(right_nums)
return root
可能会有同学有疑问,如果切片操作中的max_index+1超出索引范围,不会报错(out of range)吗?
事实上并不会,当使用 list[start:end]
这样的切片操作时,如果 start
或 end
超出了列表的索引范围,Python 不会报错,而是会返回一个适当的列表。如果 start
大于列表的最大索引,你会得到一个空列表。同样,如果 end
大于列表的最大索引,切片操作会返回从 start
到列表末尾的所有元素。
2.从前序与中序遍历序列构造二叉树
2.1题目描述
2.2 思路
根据前序和中序的遍历顺序“中左右”我们可以得知,前序遍历序列中的第一个元素就是当前序列的根节点。我们就可以通过中序序列确定根节点所在,从而我们可以通过中序序列“左中右”的特点,根据从前序序列获得的中节点,将中序序列切分为左右两个部分。
而后,我们再根据从中序序列获取的左右子序列的长度,可以对前序序列的左右进行划分。在利用递归,求的左右子树。
(1)确定输入和输出:
容易知道,我们的输入是前序序列preorder和中序序列inorder,输出是root根节点
(2)确定递归终止条件:
当前序序列或中序序列为空时返回None
if not preorder:
return None
(3)确定中间过程
首先我们创建根节点,根据前序序列的第一个元素,并找到中序序列中根节点所在位置便于切分:
# 创建根节点,先序数组中的第一个是根节点
root = TreeNode(preorder[0])
# 确定切分中序数组的下标
split_index = inorder.index(root.val)
而后我们根据获得的split_index,对中序数组进行左右切分,在获中序左右序列之后,我们就可以根据其长度切分前序序列:
# 确定左和右的中序数组
left_inorder = inorder[:split_index]
right_inorder = inorder[split_index+1:]
# 根据前序和中序数组的左右长度必然相同,对前序数组进行切分
left_preorder = preorder[1:len(left_inorder)+1]
right_preorder = preorder[len(left_inorder)+1:]
最后我们确定左右子树即可:
# 左右节点
root.left = self.buildTree(left_preorder,left_inorder)
root.right = self.buildTree(right_preorder,right_inorder)
(4)汇总
class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
# 先来处理递归跳出的条件/处理特殊情况
if not preorder:
return None
# 创建根节点,先序数组中的第一个是根节点
root = TreeNode(preorder[0])
# 确定切分中序数组的下标
split_index = inorder.index(root.val)
# 确定左和右的中序数组
left_inorder = inorder[:split_index]
right_inorder = inorder[split_index+1:]
# 根据前序和中序数组的左右长度必然相同,对前序数组进行切分
left_preorder = preorder[1:len(left_inorder)+1]
right_preorder = preorder[len(left_inorder)+1:]
# 左右节点
root.left = self.buildTree(left_preorder,left_inorder)
root.right = self.buildTree(right_preorder,right_inorder)
# 返回节点
return root
3.从中序与后序序列构造二叉树
3.1 题目描述
3.2思路
这道题和第二道题异曲同工,要注意的地方就是对于序列切分的把控,这里不过多赘述
题解:
class Solution(object):
def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
"""
# 递归终止条件/特殊情况讨论
if not inorder:
return None
# 后序数组的最后一个元素就是根节点
root = TreeNode(val = postorder[-1])
# 中序数组切分索引
split_index = inorder.index(root.val)
# 对中序数组进行切分,右边会-1
left_inorder = inorder[:split_index]
right_inorder = inorder[split_index+1:]
# 对后序数组进行切分(根据中序和后序数组长度必须相同进行切分)
left_postorder = postorder[:len(left_inorder)]
right_postorder = postorder[len(left_inorder):-1]
# 左右节点
root.left = self.buildTree(left_inorder,left_postorder)
root.right = self.buildTree(right_inorder,right_postorder)
# 返回值
return root
4.将有序数组转换为二叉搜索树:
4.1 题目描述
4.2思路
相比于最大二叉树,这道题更为简单,因为所给的是有序数组,相信大家也能看出来,要想构造出平衡的二叉树,我们每次取有序数组的中节点作为根节点,然后递归地构建左子树和右子树即可。
代码如下:
class Solution(object):
def sortedArrayToBST(self, nums):
"""
:type nums: List[int]
:rtype: TreeNode
"""
if not nums:
return None
index_mid = len(nums) // 2
root = TreeNode(nums[index_mid])
root.left = self.sortedArrayToBST(nums[:index_mid])
root.right = self.sortedArrayToBST(nums[index_mid+1:])
return root
以上,学习在与总结和坚持,共勉