写在前边的话
二叉树训练的第五天啦,理论基础见下边第一天链接,今天也要加油呀!
654.最大二叉树
题目链接
题目难度
中等
看到题目的第一想法
有了昨天的训练,看到题目就想到了昨天二叉树构造的递归算法,不同的是这道题目给的是一组数组,而中节点的确定是数组中的最大值,但是实现的算法逻辑是一样的。
python
# 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 not nums:
return None
root_val = max(nums)
root = TreeNode(root_val)
root_index = nums.index(root_val)
left_nums = nums[:root_index]
right_nums = nums[root_index+1:]
root.left = self.constructMaximumBinaryTree(left_nums)
root.right = self.constructMaximumBinaryTree(right_nums)
return root
看完代码随想录之后的总结
文章讲解
视频讲解
解题思路
1. 递归法:前序遍历
2. 递归三步曲:
入参:要分隔的数组,返回值:根节点。
终止条件:分隔出来的数组为空了说明已经到叶子节点了,return None。
单次递归逻辑:1)确认数组中最大值作为当前中节点 2)确认数组中最大值下标作为分隔点 3)以最大值分隔数组为左右两部分 4)递归:分隔出的左右数组分别作为左右子树进行递归操作。
代码编写
python
同第一想法
java
617.合并二叉树
题目链接
题目难度
简单
看到题目的第一想法
看到题目的第一想法是想到用递归了,整体思路是有的,但是终止条件没有处理好,想到的是节点为空了就返回空,处理的不好,导致后边的单次递归逻辑处理比较麻烦,要去考虑左右子节点情况,最终也没处理好。
看完代码随想录之后的总结
文章讲解
视频讲解
解题思路
1. 递归法:递归顺序前中后都可以
2. 递归三步曲:1)入参:要合并的二叉树;返回值:合并二叉树的根节点。2)终止条件:一个二叉树为空则返回另一个。3)单次递归逻辑:合并当前两个节点作为新的节点,递归遍历左右子树。
代码编写
python
# 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 not root1:
return root2
if not root2:
return root1
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
java
700.二叉搜索树中的搜索
题目链接
题目难度
简单
看到题目的第一想法
看到题目的第一想法是使用层序遍历,使用队列实现。
python
# 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 not root:
return None
queue = collections.deque([root])
while queue:
n = len(queue)
for i in range(n):
node = queue.popleft()
if node.val == val:
return node
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return None
不足:其实这样的写法是没有利用到二叉搜索树的有序性,我写的时候也意识到了这一点,可是没想好怎么去利用这个特性。
二叉搜索树性质:若左子树非空,则左子树的所有节点值均小于根节点值;若右子树非空,右子树中所有节点的值均大于根节点的值;左右子树也均具有这种性质。
注意:是所有节点。
看完代码随想录之后的总结
文章讲解
视频讲解
解题思路
1. 递归法:遍历顺序按照二叉树的有序性来进行有方向的遍历。
递归三部曲:1)入参:根节点和目标值;返回值:目标子树。2)终止条件:若节点为空或者找到了目标节点则返回当前节点。3)单次递归逻辑:如果目标值小于当前节点的值,则向左子树遍历,如果目标值大于当前节点的值,则向右子树遍历。
2. 迭代法:在迭代过程中也要应用到二叉搜索树的顺序性进行有方向的遍历。
代码编写
python
# 递归法
# 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 not root or root.val == val:
return root
res = None
if val < root.val:
res = self.searchBST(root.left, val)
if val > root.val:
res = self.searchBST(root.right, val)
return res
#*******************************************************************************
# 迭代法
# 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 val < root.val:
root = root.left
elif val > root.val:
root = root.right
else:
return root
return None
java
98.验证二叉搜索树
题目链接
题目难度
中等
看到题目的第一想法
看到第一题目的第一想法就是使用递归法进行遍历,但是却进入一个误区,想着是指判断当前节点的左节点小于当前节点,当前节点的右节点大于右节点,而忽略了二叉搜索树真正的顺序性(见上一题)。
看完代码随想录之后的总结
文章讲解
视频讲解
解题思路
1. 递归中序遍历,利用中序递增的性质,节点值保存在数组中,检查数组是不是递增的。
2. 递归中序遍历,前一个节点的值大于当前节点值,初始化pre节点为None。
代码编写
python
# 将递归中序遍历二叉树转化成数组,利用中序数组升序性质
# 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:
res = []
def dsf(root):
if not root:
return
dsf(root.left)
res.append(root.val)
dsf(root.right)
dsf(root)
for i in range(1, len(res)):
if res[i] <= res[i-1]:
return False
return True
# ***********************************************************
# 递归+双指针(初始化pre为None)
# 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 not root:
return True
left_res = self.isValidBST(root.left) # 左
# 中
if self.pre and self.pre.val >= root.val:
return False
self.pre = root
right_res = self.isValidBST(root.right) # 右
return left_res and right_res
java
今日总结
今天大部分的题目都是和二叉搜索树相关的题目,要明确:1)二叉搜索树的性质,是左子树的节点值均小于根节点的值,右子树所有节点的值均大于根节点的值,左右子树也同样满足这个性质。2)根据二叉搜索树的性质利用中序遍历的话,保存在数组中,数组是升序的。因此在解决二叉树验证题目的时候一是可以利用数组的这个性质,二是可以使用双指针在中序遍历的过程中来进行递归判断。总的来说就是二叉搜索题目要用到其顺序性,另外二叉搜索树一般用到是中序遍历。