654.最大二叉树
文档讲解:代码随想录
题目链接:. - 力扣(LeetCode)
递归的三要素:
第一要素:明确这个函数想要干什么
传入一个数组,针对这个数组构造一个最大二叉树
第二要素:寻找递归结束条件
如果传入的是空那么就return 空
如果传入的只有一个节点,那么就返回这个节点
第三要素:找出函数的等价关系式
首先可以找出来最大的根节点root,就是数组中的最大值对应的节点
然后我们就需要分别构造根节点的左右子树。左子树是通过根节点左边的元素数组构造的最大二叉树,右子树是通过根节点的右边构造的最大二叉树,构造最大二叉树的过程即为递归
注意:要判断是否存在左右子树的情况(左右区间长度至少大于1,我们的递归判断条件是1才返回),再进行递归
递归中有时候写if,有时候不写if,主要是看终止条件,该终止条件限定了数组中至少有一个元素
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
##递归终止条件
if len(nums) == 1:
return TreeNode(nums[0])
##找到数组中的最大值以及最大值对应的下标
max_value,max_index = self.find_max_list(nums)
#根节点是数组中的最大值
root_val = max_value
root = TreeNode(root_val)
#根据根节点的位置划分左右子区间, 构造根节点的左右子树
#注意index可能为0或者是数组的最后面,导致左右区间为空,如果左右区间为空,那么就没有左或者右子树
if max_index >0:
left = nums[:max_index]
root.left = self.constructMaximumBinaryTree(left)
if max_index < len(nums)-1:
right = nums[max_index+1:]
root.right = self.constructMaximumBinaryTree(right)
return root
def find_max_list(self,nums):
#找到数组中的最大值以及最大值对应的下标
max_value = 0
max_index = 0
for i in range(len(nums)):
if nums[i] > max_value:
max_value = nums[i]
max_index = i
return max_value,max_index
617.合并二叉树
文档讲解:代码随想录
题目链接:. - 力扣(LeetCode)
递归的三要素:
第一要素:明确这个函数想要干什么
传入两个二叉树,返回合并后的二叉树
第二要素:寻找递归结束条件
两棵树是一起遍历的
如果有一个树是空,那么就返回另一个树;如果两个树都是空,那么就return null(这种情况其实已经包含在了前面的条件中)
第三要素:找出函数的等价关系式
从根节点开始,直接去改tree1的结构,不再新定义一棵二叉树了,根节点合并完之后,就要去合并左右子树了,这时候就进入了递归
class Solution:
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
###终止条件
if root1 == None:
return root2
if root2 == None:
return root1
##单层逻辑递推关系
root1.val = root1.val + root2.val
#递归
root1.left = self.mergeTrees(root1.left,root2.left)
root1.right = self.mergeTrees(root1.right,root2.right)
return root1
700.二叉搜索树中的搜索
文档讲解:代码随想录
题目链接:. - 力扣(LeetCode)
递归法
递归的三要素:
第一要素:明确这个函数想要干什么
给定二叉搜索树(BST)的根节点和一个值。在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。
第二要素:寻找递归结束条件
如果根节点的值即为要找的目标值,那么直接return 根节点即可
如果二叉树中只有一个节点,并且根节点的值与目标值不等,那么就返回Null
第三要素:找出函数的等价关系式
如果当前遍历的根节点的值大于目标值,那么接下来就遍历该节点的左子树
如果当前遍历的根节点的值小于目标值,那么接下来就遍历该节点的右子树
class Solution:
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
###递归终止条件
if root == None:
return None
if root.val == val:
return root
if root.left==None and root.right == None and root.val != val:
return None
###递归,根据二叉搜索树的特性,选择遍历左子树还是右子树
if root.val > val:
node = self.searchBST(root.left,val)
else:
node = self.searchBST(root.right,val)
return node
迭代法
从根节点开始查询,根据二叉搜索树的特性,决定向右还是向左搜索
class Solution:
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
while root:
if root.val > val:
root = root.left
elif root.val < val:
root = root.right
else:
return root
if root == None:
return None
98.验证二叉搜索树
文档讲解:代码随想录
题目链接:. - 力扣(LeetCode)
二叉搜索树的性质:
如果该二叉树的左子树不为空,则左子树上所有节点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;它的左右子树也为二叉搜索树。
节点的位置越深,节点的值的限制就越多,所以我们可以判断节点是不是满足左右区间的限制,在遍历的过程中,不断去更新左右区间
递归的三要素:
第一要素:明确这个函数想要干什么
传入一个根节点,判断该节点对应的二叉树是否是二叉搜索树
并传入一个区间左端点,一个区间右端点,查看节点值是否满足区间限制,来辅助我们判断
第二要素:寻找递归结束条件
如果传入为空,返回True
如果节点的值不在区间中,那么return false
第三要素:找出函数的等价关系式
如果根节点满足要求,接下来要去看左右子树是否是二叉搜索树,在遍历过程中,如果向左遍历,那么就要更新区间的右端点,如果向右遍历,那么就要更新区间的左端点。
class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
def helper(root,low,upper):
###递归终止条件
if not root:
return True
if root.val<=low or root.val>=upper: #不要忘记等于的情况
return False
###递归遍历左右子树
left = True
right = True
if root.left:
left = helper(root.left,low,root.val)
if root.right:
right = helper(root.right,root.val,upper)
return left and right
return helper(root,float('-inf'),float('inf')) #刚开始根节点的范围是任意的
没有写出来的想法,先不看了
(如果传入节点不是空节点
我们需要递归验证该节点的左子树和右子树是否是二叉搜索树
并且,如果是,那么此时我们还不能确定传入节点是否就是二叉搜索树,因为可能出现这种情况
所以我们还需要比较左子树的最大值是否比节点小,右子树的最小值是否比节点大,但是如何去找左子树的最大值和右子树的最小值呢)