112. 路径总和
解题思路:遍历出每条路径,使得总和为目标值。如果找到了,就是1.否则为0.
如果遍历到了叶节点,就计算是否达到了目标值;
如果没有遍历到叶节点,就继续往左右子树遍历。
python
def hasPathSum(root: TreeNode, targetSum: int) -> bool:
if not root:
# 当前节点为空,返回False
return False
# 更新目标和
targetSum -= root.val
# 如果当前节点是叶子节点,检查目标和是否为0
if not root.left and not root.right:
return targetSum == 0
# 递归检查左右子树
return hasPathSum(root.left, targetSum) or hasPathSum(root.right, targetSum)
113. 路径总和 II
上一题的进阶,要求记录每条成功路径的具体路径
也就是要新增一个结果list存储所有成功的路径列表,还有每条路径的path。
python
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def pathSum(root: TreeNode, targetSum: int) -> List[List[int]]:
def dfs(node, currentSum, path):
if not node:
return
currentSum += node.val
path.append(node.val)
# 检查是否是叶子节点且当前路径和等于目标和
if not node.left and not node.right and currentSum == targetSum:
# 注意这里需要添加path的副本
result.append(path[:])
# 递归遍历左右子树
dfs(node.left, currentSum, path)
dfs(node.right, currentSum, path)
# 回溯,从路径中移除当前节点
path.pop()
result = []
dfs(root, 0, [])
return result
ai的理解:
想象你在一个迷宫里寻找宝藏,这个迷宫就像是我们的二叉树,宝藏是位于叶子节点的目标和targetSum。你手里有一张纸(这就是我们的path列表),每当你向前走一步,就在纸上记下你的当前位置。当你到达一个死路(叶子节点)但没有找到宝藏时,你会退回到上一个岔路口,并在纸上擦掉最后的记录。
现在,我们按照这个思路来解释代码的执行过程: 开始探索:你从迷宫的入口(根节点)开始,手里的纸是空的。
记录每一步:每向前走一步,就在纸上记录下当前的位置(每深入一层递归,就把当前节点的值加到path列表中)。
检查是否找到宝藏:每当你到达一个死路(叶子节点),你检查一下手里的纸(当前路径)上记录的所有步骤加起来是否等于宝藏的位置(targetSum)。如果是,你就把这张纸的副本(一条成功的路径)留在宝藏箱里(加入到result列表中)。
回退到上一个岔路口:不管这条路是否成功,每当探索完一条路径后,你都会回到上一个岔路口准备探索另一条路。这时,你就会在纸上擦掉最后的记录(执行path.pop()),因为你要撤销最后的这一步,回到之前的状态。
继续探索:回到岔路口后,如果还有没走过的路,你就按照同样的方式继续探索,直到探索完所有可能的路径。
101. 对称二叉树
最先想到的是利用层序遍历的思想,比较每一层是否对称,但是一看就不行。
正确的思路:同时递归遍历左子树和右子树,比较镜像节点。如果所有节点都满足条件,则就是对称的。
python
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def isSymmetric(root: TreeNode) -> bool:
if not root:
return True
def isMirror(left: TreeNode, right: TreeNode) -> bool:
if not left and not right:
return True
if not left or not right or left.val != right.val:
return False
return isMirror(left.left, right.right) and isMirror(left.right, right.left)
return isMirror(root.left, root.right)
ai理解:
让我们一步一步梳理
isMirror
函数的逻辑,这个函数用于检查两个树节点是否是镜像对称的:
基本情况:
- 如果两个节点都为空 ,说明我们到达了树的末端,而且这一部分是对称的。因此,返回
True
。- 如果一个节点为空而另一个不为空 ,或者两个节点都不为空但值不相等 ,说明这一部分不对称。因此,返回
False
。递归逻辑:
- 如果两个节点都不为空,并且它们的值相等,我们继续检查这两个节点的子节点。
- 我们检查当前节点的左子节点与另一节点的右子节点是否对称(
left.left
和right.right
)。- 同时,我们也检查当前节点的右子节点与另一节点的左子节点是否对称(
left.right
和right.left
)。- 这个逻辑是基于对称树的性质:如果两个树是对称的,那么一棵树的左子树与另一棵树的右子树镜像对称,同时一棵树的右子树与另一棵树的左子树也镜像对称。
返回值:
- 我们通过逻辑与操作符(
and
)连接这两个递归调用的结果。只有当两个子树都是对称的(即left.left
和right.right
对称,且left.right
和right.left
对称),我们才认为整体是对称的,返回True
。- 如果任一对子树不对称,整体就不对称,返回
False
。通过这种方式,
isMirror
函数能够自顶向下递归地检查二叉树的每一层是否对称。这个过程中,每一次递归调用都是基于对称性的要求,逐步验证整棵树是否满足这一条件。