112&113&437. Path Sum I &II&III
112.Path Sum
Given the root
of a binary tree and an integer targetSum
, return true
if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum
.
A leaf is a node with no children.
Example 1:
Input: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
Output: true
Explanation: The root-to-leaf path with the target sum is shown.
My Solutions:
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
if (root.left == null && root.right == null) return targetSum == root.val;
return (hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val));
}
113.Path Sum II
Given the root
of a binary tree and an integer targetSum
, return all root-to-leaf paths where the sum of the node values in the path equals targetSum
. Each path should be returned as a list of the node values, not node references.
A root-to-leaf path is a path starting from the root and ending at any leaf node. A leaf is a node with no children.
Example 1:
Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
Output: [[5,4,11,2],[5,8,4,5]]
Explanation: There are two paths whose sum equals targetSum:
5 + 4 + 11 + 2 = 22
5 + 8 + 4 + 5 = 22
My Solutions:
和112类似,但是需要记录path。因此在dfs的时候,需要带上list,存入走过的路径的节点。
dfs/recursive:注意在dfs一个root的两边之后,需要删除list里最后一个节点。这是因为list里记录了走过的每一个节点,但是如果一个节点并不是最后加到最终结果里面去的路径,需要把沿路的节点删除掉。
public class Solution {
//recursive
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> res = new ArrayList();
if (root == null) return res;
dfs(root, sum, res, new ArrayList<Integer>());
return res;
}
private void dfs(TreeNode root, int target, List<List<Integer>> res, List<Integer> list) {
if (root == null) return;
list.add(root.val); // 记录路上的节点
// 代表走到了叶子节点,并且路径的值等于目标值
if (root.left == null && root.right == null && root.val == target) res.add(new ArrayList(list));
dfs(root.left, target - root.val, res, list);
dfs(root.right, target - root.val, res, list);
list.remove(list.size() - 1); // 注意这里删除了list里最后一个节点
}
}
也可以用bfs/iteratvie 的方法
//iterative
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
Stack<TreeNode> stack = new Stack<TreeNode>();
int SUM = 0;
TreeNode cur = root, pre = null;
while (cur != null || !stack.isEmpty()){
while(cur != null){
stack.push(cur);
path.add(cur.val);
SUM += cur.val;
cur = cur.left; // 先往左边走到底
}
cur = stack.peek();
if (cur.right != null && cur.right != pre){ // 往右边走到底
cur = cur.right;
continue;
}
// 代表走到了叶子节点,并且路径的值等于目标值
if (cur.left == null && cur.right == null && SUM == sum)
res.add(new ArrayList<Integer>(path));
pre = cur;
stack.pop();
// 这里和recursive的思路一样,因为这个节点不在路径上,需要删掉
path.remove(path.size() - 1);
SUM -= cur.val;
cur = null;
}
return res;
437.Path Sum III
Given the root
of a binary tree and an integer targetSum
, return the number of paths where the sum of the values along the path equals targetSum
.
The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes).
Example 1:
Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
Output: 3
Explanation: The paths that sum to 8 are shown.
My Solutions:
这道题不再需要从root出发,也不用一定要到叶子节点,只要路上有满足要求的路径,就算作满足条件的路径。所以一颗以root为根的树,其路径和等于sum的路径个数可由以下三部分组成:
1.路径以root 开头;2.路径不以root开头
2.1左子树中等于sum的路径个数
2.2右子树中等于sum的路径个数
方法1:
public int pathSum(TreeNode root, int sum) {
if (root == null) return 0;
Map<Long, Integer> map = new HashMap<>();
// 用map储存 <prefix sum> --> <frequency>
map.put((long)0, 1);
return helper(root, (long)0, sum, map);
}
private int helper(TreeNode node, long total, int sum, Map<Long, Integer> map) {
if (node == null) return 0;
// update the prefix sum by adding the current node's value
total += node.val;
// get the number of valid path, ended by current node
int pathSumToCurrentNode = map.getOrDefault((long)total - sum, 0);
// update the map with current total
map.put((long)total, map.getOrDefault((long)total, 0) + 1);
int res = pathSumToCurrentNode
+ helper(node.left, total, sum, map)
+ helper(node.right, total, sum, map) ;
// restore the map
map.put((long)total, map.get(total) - 1);
return res;
}
方法2: (2023年无法通过test,因为数字太大)
[1000000000,1000000000,null,294967296,null,1000000000,null,1000000000,null,1000000000]
0
Space: O(n) due to recursion.
Time: O(n^2) in the worst case (no branching); O(nlogn) in the best case (balanced tree).
public int pathSum(TreeNode root, int sum) {
if (root == null) return 0;
return helper(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum);
}
private int helper(TreeNode node, int sum) {
if (node == null) return 0;
int res = 0;
if (node.val == sum) res++;
res += helper(node.left, sum - node.val) + helper(node.right, sum - node.val);
return res;
}
Last updated