代码随想录算法训练营第十七天|leetcode654. 最大二叉树、leetcode617.合并二叉树、leetcode700.二叉搜索树中的搜索、leetcode98.验证二叉搜索树
1 leetcode654. 最大二叉树
题目链接:654. 最大二叉树 - 力扣(LeetCode)
文章链接:代码随想录
视频链接:又是构造二叉树,又有很多坑!| LeetCode:654.最大二叉树_哔哩哔哩_bilibili
思路:跟上一道题从中序后序中返回一个二叉树,好了,同理的思路就做出来咯,哈哈哈哈哈哈
1.1 自己的代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
if len(nums) == 0:
return None
root_val = max(nums)
root = TreeNode(root_val)
if len(nums) == 1:
return root
ind = 0
for i in range(len(nums)):
if nums[i] == root_val:
ind = i
break
nums_left = nums[:ind]
nums_right = nums[ind+1:]
root.left = self.constructMaximumBinaryTree(nums_left)
root.right = self.constructMaximumBinaryTree(nums_right)
return root
1.2视频后的思路
差异就是这个构造的二叉树,因为一定有值,所以没必要对其为0进行判断,如果有一个值的话,就可以进行返回
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
if len(nums) == 1:
return TreeNode(nums[0])
root = TreeNode(0)
maxval = 0
maxind = 0
for i in range(len(nums)):
if nums[i]>maxval:
maxval = nums[i]
maxind = i
root.val = maxval
if maxind>0:
root.left = self.constructMaximumBinaryTree(nums[:maxind])
if maxind<len(nums)-1:
root.right = self.constructMaximumBinaryTree(nums[maxind+1:])
return root
1.3 本题小结
- 这道题的第一种思路就是使用前序中序构造一个唯一的二叉树,这么做可以写出来代码,但是会非常的冗余
- 然后就是第二种递归,首先判断什么时候终止,就是这个二叉树只有一个数值的时候,可以直接进行返回,这里发现由于递归的原因,如果直接将数据使用
max
函数的话会直接报错
2 leetcode617.合并二叉树
题目链接:617. 合并二叉树 - 力扣(LeetCode)
文章链接:代码随想录
视频链接:一起操作两个二叉树?有点懵!| LeetCode:617.合并二叉树_哔哩哔哩_bilibili
思路:开始的时候,我想的是这个直接进行合并就行,但是发现有的二叉树我连分开都不能分开,还是直接看视频来写吧
2.1 视频后的思路
思路:
不进行新的二叉树定义,覆盖的方法,就是将另一个二叉树的值加过去就好了,其实理论上真的没新的,就是自己想不出来
2.1.1 覆盖的方法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
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 += root2.val
root1.left = self.mergeTrees(root1.left,root2.left)
root1.right = self.mergeTrees(root1.right,root2.right)
return root1
2.1.2 定义一个新的二叉树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
if root1==None:
return root2
if root2 == None:
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
2.2 本题小结
- 写到这里的时候,我突然发现,这种题真的写的不难,主要是思路上会有想不到的地方,每次卡壳了,但是听视频听了一点就会了
- 二叉树合并其实和两数相加也是同样的原理,要学会举一反三呀
3 leetcode700.二叉搜索树中的搜索
题目链接:700. 二叉搜索树中的搜索 - 力扣(LeetCode)
文章链接:代码随想录
视频链接:不愧是搜索树,这次搜索有方向了!| LeetCode:700.二叉搜索树中的搜索_哔哩哔哩_bilibili
思路:看到题目想使用前序遍历,如果找到了这个值,那就可以返回这个树了;但是吧写的时候,不会了,,
3.1 基础知识
二叉搜索树
二叉搜索树是一个有序树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树
3.2 视频后的思路
3.2.1 递归法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if root ==None or root.val == val:
return root
result = TreeNode(0)
if root.val <val:
result = self.searchBST(root.right,val)
if root.val >val:
result =self.searchBST(root.left,val)
return result
3.2.2 迭代法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
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
3.3 本题小结
- 这道题首先是二叉搜索树的概念,左子树永远比根节点小,右子树永远比根节点大,根据这个思路往下写就行了
- 对于递归而言,如果知道这个,就容易,不过目前没彻底弄明白为什么要赋值result
- 递归法,就是听了会了,写的时候懵了,看题解的时候彻底会了,有点聪明但不多哈哈哈哈哈哈哈
4 leetcode98.验证二叉搜索树
题目链接:98. 验证二叉搜索树 - 力扣(LeetCode)
文章链接:代码随想录
视频链接:你对二叉搜索树了解的还不够! | LeetCode:98.验证二叉搜索树_哔哩哔哩_bilibili
思路:哈哈哈哈哈哈,开始想的是如果左子树和右子树的值满足二叉搜索树的情况,就可以返回True;结果写的时候,根本不会写,,
4.1 自己的代码
写了一句有超级大问题的代码
if root.val>root.left.val and root.val<root.right.val:
return True
result = TreeNode(0)
这里问题出在,只判断了他的左右节点,没有判断左子树和右子树,二叉树的概念有一些混淆!!!!
4.2 视频后的思路
看完了,但是怎么说呢,感觉还是有一点点难度,写起来有一点不知如何下手的感觉,,
重点:判断这个问题的时候,其实很好的一个想法就是使用中序遍历,因为这样可以保证出来的值是从小到大排序的一个过程
4.2.1暴力搜索法
这里之前写错了一句话,非要先判断正确的,后来发现其实上去对的可能在中间会出现错误,就会有问题。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
self.vec = []
self.traversal(root)
for i in range(len(self.vec)-1):
if self.vec[i]>=self.vec[i+1]:
return False
return True
def traversal(self,node):
if node ==None:
return True
self.traversal(node.left)
self.vec.append(node.val)
self.traversal(node.right)
4.2.2 使用极小值的方法
定义一个极值,然后就是在中序的时候比较当前值和极值的关系,做一个返回的操作
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.maxval = float('-inf')
def isValidBST(self, root: Optional[TreeNode]) -> bool:
if root == None:
return True
left = self.isValidBST(root.left)
if root.val>self.maxval:
self.maxval = root.val
else:
return False
right = self.isValidBST(root.right)
return left and right
4.2.3 双指针的方法
这种方法就是定义一个前指针,然后比较前一个值和当前值的关系,如果遇到了不符合的就返回
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.pre = None
def isValidBST(self, root: Optional[TreeNode]) -> bool:
if root == None:
return True
left = self.isValidBST(root.left)
if self.pre !=None and self.pre.val>=root.val:
return False
self.pre = root
right = self.isValidBST(root.right)
return left and right
4.3 本题小结
- 本题的主要难点对我而言,就是上去思路就错了,其次分析二叉树的题目没有严格按照遍历顺序去思考,导致这个题目花费了挺多时间的
- 思路上的总结,首先,这个是验证,所以传入的是这个二叉树,终止条件找不正确的,然后第三部就是递归的内部逻辑,按照这个来就容易一些
- 记住使用的是中序遍历方法
5 今日小结
- 前两道题是对递归方法的一个总结吧,我觉得是,相比而言就是比较中规中矩的递归方法
- 后两道题是对二叉搜索树概念的掌握和理解,在写的过程越来越对这种概念理解的清晰了,题目思路也顺畅了很多
- 希望接下来我可以真的自己分析题目,感觉现在的代码都是看了视频才会,离开视频可能就不会了,,,