# 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, targetSum):
res = []
def dfs(node, path, curr_sum):
if not node:
return
path.append(node.val)
curr_sum += node.val
if not node.left and not node.right and curr_sum == targetSum:
res.append(list(path))
else:
dfs(node.left, path, curr_sum)
dfs(node.right, path, curr_sum)
path.pop()
dfs(root, [], 0)
return res
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int>> res;
vector<int> path;
dfs(root, targetSum, 0, path, res);
return res;
}
void dfs(TreeNode* node, int targetSum, int curr_sum, vector<int>& path, vector<vector<int>>& res) {
if (!node) return;
path.push_back(node->val);
curr_sum += node->val;
if (!node->left && !node->right && curr_sum == targetSum) {
res.push_back(path);
} else {
dfs(node->left, targetSum, curr_sum, path, res);
dfs(node->right, targetSum, curr_sum, path, res);
}
path.pop_back();
}
};
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
dfs(root, targetSum, 0, path, res);
return res;
}
private void dfs(TreeNode node, int targetSum, int currSum, List<Integer> path, List<List<Integer>> res) {
if (node == null) return;
path.add(node.val);
currSum += node.val;
if (node.left == null && node.right == null && currSum == targetSum) {
res.add(new ArrayList<>(path));
} else {
dfs(node.left, targetSum, currSum, path, res);
dfs(node.right, targetSum, currSum, path, res);
}
path.remove(path.size() - 1);
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {number} targetSum
* @return {number[][]}
*/
var pathSum = function(root, targetSum) {
const res = [];
function dfs(node, path, currSum) {
if (!node) return;
path.push(node.val);
currSum += node.val;
if (!node.left && !node.right && currSum === targetSum) {
res.push([...path]);
} else {
dfs(node.left, path, currSum);
dfs(node.right, path, currSum);
}
path.pop();
}
dfs(root, [], 0);
return res;
};
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 represented as a list of node values. A root-to-leaf path is a path starting at the root node and ending at any leaf node (a node with no children).
Constraints:
Node.val
≤ 1000targetSum
≤ 1000
To solve this problem, we need to find all paths from the root to any leaf such that the sum of the node values along the path equals targetSum
.
The most straightforward approach would be to try every possible path from the root to each leaf, keeping track of the sum as we traverse. If the sum matches targetSum
at a leaf, we record that path.
However, this brute-force approach can be optimized by:
targetSum
.We'll use a recursive Depth-First Search (DFS) algorithm for this problem. Here's how we approach it step by step:
targetSum
, record a copy of the current path.
This approach is efficient because:
targetSum
.Example: Suppose the binary tree is:
5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1
And targetSum = 22
.
Let's trace the algorithm:
The final result is two paths:
Brute-force Approach:
N
nodes, there could be up to O(2^H)
paths, where H
is the height of the tree.
O(H)
long, so total time is O(N)
since every node is visited once per path.
O(H)
for the recursion stack and the current path, plus O(K*H)
for storing K
valid paths.
O(N)
.
O(H)
for the recursion stack and path, where H
is the height of the tree.
O(K*H)
if there are K
valid paths.
The Path Sum II problem is elegantly solved using recursive DFS and backtracking. By keeping track of the current path and sum, we efficiently explore all root-to-leaf paths. The solution is both intuitive and optimal, leveraging the tree structure and recursion to avoid unnecessary work. Key insights include using backtracking to manage path state and only recording paths that meet the exact criteria at leaf nodes.