Day20|654.最大二叉树, 617.合并二叉树, 700.二叉搜索树中的搜索, 98.验证二叉搜索树
654.最大二叉树
思路
前序遍历
流程与前两题相似
根据最大值所在的index,切割数组,得到的左数组和右数组分别递归
尝试写代码
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
if not nums:
return None
root_val = max(nums)
root = TreeNode(root_val)
index = nums.index(root_val)
left = nums[:index]
right = nums[index + 1:]
root.left = self.constructMaximumBinaryTree(left)
root.right = self.constructMaximumBinaryTree(right)
return root
成功通过!
617.合并二叉树
思路
终止条件:如果两个二叉树都是叶子节点,则返回None
尝试写代码
class Solution:
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
if not root1.left and not root1.right and not root2.left and not root2.right:
return None
if not root1.left and root2.left:
return root2.left
if not root2.left and root1.left:
return root1.left
if not root1.right and root2.right:
return root2.right
if not root2.right and root1.right:
return root1.right
if root1 and root2:
root_val = root1.val + root2.val
root = TreeNode(root_val)
root.left = self.mergeTrees(root1.left, root2.left)
root.right = self.mergeTrees(root1.right, root2.right)
return root
结果不对
根据代码随想录视频
要点:
- 使用前序,最容易理解
- 确定参数和返回值,参数为传入的两个树,返回值就是返回的树的根节点
- 终止条件:如果tree1为空,返回tree2;如果tree2为空,返回tree1;如果都为空,返回None,不需要额外写,已经包含在前两个条件里了。
- 如何处理返回值:如果tree1为空,要返回tree2的该节点,即此时要返回以该节点为根节点的整个子树,需要将该节点返回给上一层。
- 不需要重新创建二叉树,直接更改tree1就好
最终代码:
class Solution:
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
if not root1:
return root2
if not root2:
return root1
root = TreeNode(0)
root.val = root1.val + root2.val
root.left = self.mergeTrees(root1.left, root2.left)
root.right = self.mergeTrees(root1.right, root2.right)
return root
总结
处理当前节点,考虑的比较简单,就不用分左右了。终止条件中,处理的方式,简单有效,是我一开始想复杂了。
根据视频的思路,写出来非常简单!
700.二叉搜索树中的搜索
思路
写终止条件时,不确定如果找到了节点值等于val的节点 这一条件是否应该算作终止条件,还是算中的处理逻辑。
如果算终止条件,那返回值应该是root,而如果遍历到叶子节点,返回None。
这样在左右递归时,需要判断,如果有返回值,则继续向上返回,最后返回None。
尝试写代码:
class Solution:
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if not root:
return None
if root.val == val:
return root
left = self.searchBST(root.left, val)
if left:
return left
right = self.searchBST(root.right, val)
if right:
return right
return None
成功通过!
但是有点不明白,为什么最后返回None,而不是空列表。
debug之后,确实是返回None;题目要求也是返回None,只不过例子给出的返回了[]。注意审题!
根据代码随想录,本题是一个二叉搜索树,上面自己写的代码思路适用于普通二叉树,应该根据二叉搜索树的特性写。
要点:
- 二叉搜索树自带顺序,不需要考虑递归的顺序
- 终止条件有两个,一个是节点为空,另一个是满足条件。写的时候可以写成都返回root的形式。
- 给定值比节点小,搜索左子树;比节点值大,搜索右子树。
- 注意递归函数有返回值,需要定义一个临时变量,用来接住返回值。
最终代码:
class Solution:
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if not root or root.val == val:
return root
result = TreeNode(None)
if val < root.val:
result = self.searchBST(root.left, val)
if val > root.val:
result = self.searchBST(root.right, val)
return result
98.验证二叉搜索树
思路
如何判断整个右子树大于当前节点?
如果只分析当前节点,那就有可能只有右节点满足,而右节点的左节点可能比当前值小。
那就需要右子树的全部节点与当前节点比较,这样时间复杂度很高
不知道有没有什么简单有效的算法。
尝试用后序遍历写代码:
class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
if not root.left and not root.right:
return True
if root.left:
if not self.isValidBST(root.left):
return False
if root.right:
if not self.isValidBST(root.right):
return False
if root.left and root.right and root.left.val < root.val and root.right.val > root.val:
return True
else:
return False
测试用例正确,但结果不对。
感觉终止条件设的不对,该思路也没有解决一开始想到的问题。
根据代码随想录:
要点:
- 中序遍历二叉搜索树,元素单调递增
- 定义一个pre节点,在中的处理逻辑中,比较当前节点和前一节点的值,不满足则返回True
- 终止条件,考虑极端情况,返回True
最终代码:
class Solution:
def __init__(self):
self.prev = None
def isValidBST(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
left = self.isValidBST(root.left)
if self.prev and self.prev.val >= root.val:
return False
self.prev = root
right = self.isValidBST(root.right)
return left and right
注意:
只需要定义类内全局变量时,创建init函数
解法二:中序遍历后的数组,判断其是不是单调递增
class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
self.result = []
self.is_asc(root)
for i in range(1, len(self.result)):
if self.result[i - 1] >= self.result[i]:
return False
return True
def is_asc(self, root):
if not root:
return
self.is_asc(root.left)
self.result.append(root.val)
self.is_asc(root.right)