112、路径总和(有无)
思路一:DFS
如果为叶子节点且总和为target,返回True,否则递归接着遍历
简洁写法:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if not root: return False
if not root.left and not root.right:
return sum == root.val
return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val)
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root==null) return false;
if(root.left==null && root.right==null) return root.val==targetSum;
return hasPathSum(root.left,targetSum-root.val)
|| hasPathSum(root.right,targetSum-root.val);
}
}
思路二:BFS
BFS 使用 队列 保存遍历每个节点以及到这个节点的路径和(path),如果该节点恰好是叶子节点,并且 路径和 正好等于 sum,返回true,否则不断把树上的节点压入队列循环判断。
模板:
while queue 不空:
cur = queue.pop()
if cur 有效且未被访问过:
进行处理
for 节点 in cur 的所有相邻节点:
if 该节点有效:
queue.push(该节点)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def hasPathSum(self, root: TreeNode, sum: int) -> bool:
if not root:
return False
que = collections.deque()
que.append((root, root.val))
while que:
node, path = que.popleft()
if not node.left and not node.right and path == sum:
return True
if node.left:
que.append((node.left, path + node.left.val))
if node.right:
que.append((node.right, path + node.right.val))
return False
113、路径总和2(枚举)
思路一:DFS
# 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 pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:
res=[]
path=[]
def dfs(root,targetSum,plus):
if not root :
return
plus+=root.val
path.append(root.val)
if root.left is None and root.right is None and plus==targetSum:
res.append(path[:])
dfs(root.left,targetSum,plus)
dfs(root.right,targetSum,plus)
path.pop()
dfs(root,targetSum,0)
return res
细节:append(path[:])而不是append(path)
a = [1, 2, 3, 4]
c = list()
# 直接把a的地址加在后面
# c.append(a) # c [[1, 2, 3, 4] ]
# a.append(5) # a [1, 2, 3, 4, 5]
# c.append(a) # c [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
# 只加a的内容
c.append(a[:]) # c [[1, 2, 3, 4] ]
a.append(5) # a [1, 2, 3, 4, 5]
c.append(a[:]) # c[[1, 2, 3, 4], [1, 2, 3, 4, 5]]
print(c)
把path放在传递参数里互不干扰的写法(效率会低一些):
res 变量从头到尾只有同一个,但是每次调用 dfs() 函数的时候 path 变量都是不同的。Python 中,path + [root.val] 会生成一个新的列表,因此所有的递归函数的里面的 path 操作不会互相干扰。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
res = []
self.dfs(root, sum, res, [])
return res
def dfs(self, root, sum, res, path):
if not root: # 空节点,不做处理
return
if not root.left and not root.right: # 叶子节点
if sum == root.val: # 剩余的「路径和」恰好等于叶子节点值
res.append(path + [root.val]) # 把该路径放入结果中
self.dfs(root.left, sum - root.val, res, path + [root.val]) # 左子树
self.dfs(root.right, sum - root.val, res, path + [root.val]) # 右子树
最方便写法:
class Solution:
def pathSum(self , root , sum ):
# write code here
res=[]
path=[]
def dfs(root,target):
if not root:
return
path.append(root.val)#要先加入,不然没得pop
if not root.left and not root.right and target==root.val:
res.append(path[:])
dfs(root.left,target-root.val)
dfs(root.right,target-root.val)
path.pop()
dfs(root,sum)
return res
class Solution {
List<List<Integer>>res=new ArrayList<>();
List<Integer>path=new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
dfs(root,targetSum);
return res;
}
public void dfs(TreeNode root, int targetSum){
if(root==null) return;
path.add(root.val);
if(root.left==null && root.right==null && root.val==targetSum){
res.add(new ArrayList(path));
// path.remove(path.size()-1);//这两行必须同时使用!!
// return;
}
dfs(root.left,targetSum-root.val);
dfs(root.right,targetSum-root.val);
path.remove(path.size()-1);
}
}
思路二:BFS
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
res = []
que = deque()
que.append((root, [], 0)) # 将要处理的节点,路径,路径和
while que:
node, path, pathSum = que.popleft()
if not node: # 如果是空节点,不处理
continue
if not node.left and not node.right: # 如果是叶子节点
if node.val + pathSum == sum: # 加上叶子节点后,路径和等于sum
res.append(path + [node.val]) # 保存路径
# 处理左子树
que.append((node.left, path + [node.val], pathSum + node.val))
# 处理右子树
que.append((node.right, path + [node.val], pathSum + node.val))
return res
437. 路径总和 3(双重dfs)
思路:双重递归,第一重遍历每个节点,第二重以每个节点为root向下遍历寻找targetsum
class Solution:
def pathSum(self, root: TreeNode, targetSum: int) -> int:
self.res=0
def dfs1(root,targetSum):
if not root:return
targetSum-=root.val
if targetSum==0:self.res+=1
dfs1(root.left,targetSum)
dfs1(root.right,targetSum)
def dfs2(root,targetSum):
if not root: return
dfs1(root,targetSum)
dfs2(root.left,targetSum)
dfs2(root.right,targetSum)
dfs2(root,targetSum)
return self.res
class Solution {
int res;
public int pathSum(TreeNode root, int targetSum) {
if(root==null) return 0;
dfs(root,targetSum);
pathSum(root.left,targetSum);
pathSum(root.right,targetSum);
return res;
}
public void dfs(TreeNode root, int targetSum){
if(root==null) return;
if(targetSum==root.val) res++;
dfs(root.left,targetSum-root.val);
dfs(root.right,targetSum-root.val);
}
}