Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 17849a8

Browse files
feat: add solutions to lc problems: No.0437 (doocs#4325)
No.0437.Path Sum III
1 parent 1b30a34 commit 17849a8

File tree

6 files changed

+401
-18
lines changed

6 files changed

+401
-18
lines changed

‎solution/0400-0499/0437.Path Sum III/README.md‎

Lines changed: 136 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,18 @@ tags:
5959

6060
### 方法一:哈希表 + 前缀和 + 递归
6161

62-
我们可以运用前缀和的思想,对二叉树进行递归遍历,同时用哈希表 $cnt$ 统计从根节点到当前节点的路径上各个前缀和出现的次数。
62+
我们可以运用前缀和的思想,对二叉树进行递归遍历,同时用哈希表 $\textit{cnt}$ 统计从根节点到当前节点的路径上各个前缀和出现的次数。
6363

64-
我们设计一个递归函数 $dfs(node, s),ドル表示当前遍历到的节点为 $node,ドル从根节点到当前节点的路径上的前缀和为 $s$。函数的返回值是统计以 $node$ 节点及其子树节点作为路径终点且路径和为 $targetSum$ 的路径数目。那么答案就是 $dfs(root, 0)$。
64+
我们设计一个递归函数 $\textit{dfs(node, s)},ドル表示当前遍历到的节点为 $\textit{node},ドル从根节点到当前节点的路径上的前缀和为 $s$。函数的返回值是统计以 $\textit{node}$ 节点及其子树节点作为路径终点且路径和为 $\textit{targetSum}$ 的路径数目。那么答案就是 $\textit{dfs(root, 0)}$。
6565

66-
函数 $dfs(node, s)$ 的递归过程如下:
66+
函数 $\textit{dfs(node, s)}$ 的递归过程如下:
6767

68-
- 如果当前节点 $node$ 为空,则返回 0ドル$。
68+
- 如果当前节点 $\textit{node}$ 为空,则返回 0ドル$。
6969
- 计算从根节点到当前节点的路径上的前缀和 $s$。
70-
- 用 $cnt[s - targetSum]$ 表示以当前节点为路径终点且路径和为 $targetSum$ 的路径数目,其中 $cnt[s - targetSum]$ 即为 $cnt$ 中前缀和为 $s - targetSum$ 的个数。
71-
- 将前缀和 $s$ 的计数值加 1ドル,ドル即 $cnt[s] = cnt[s] + 1$。
72-
- 递归地遍历当前节点的左右子节点,即调用函数 $dfs(node.left, s)$ 和 $dfs(node.right, s),ドル并将它们的返回值相加。
73-
- 在返回值计算完成以后,需要将当前节点的前缀和 $s$ 的计数值减 1ドル,ドル即执行 $cnt[s] = cnt[s] - 1$。
70+
- 用 $\textit{cnt}[s - \textit{targetSum}]$ 表示以当前节点为路径终点且路径和为 $\textit{targetSum}$ 的路径数目,其中 $\textit{cnt}[s - \textit{targetSum}]$ 即为 $\textit{cnt}$ 中前缀和为 $s - \textit{targetSum}$ 的个数。
71+
- 将前缀和 $s$ 的计数值加 1ドル,ドル即 $\textit{cnt}[s] = \textit{cnt}[s] + 1$。
72+
- 递归地遍历当前节点的左右子节点,即调用函数 $\textit{dfs(node.left, s)}$ 和 $\textit{dfs(node.right, s)},ドル并将它们的返回值相加。
73+
- 在返回值计算完成以后,需要将当前节点的前缀和 $s$ 的计数值减 1ドル,ドル即执行 $\textit{cnt}[s] = \textit{cnt}[s] - 1$。
7474
- 最后返回答案。
7575

7676
时间复杂度 $O(n),ドル空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。
@@ -163,10 +163,12 @@ class Solution {
163163
class Solution {
164164
public:
165165
int pathSum(TreeNode* root, int targetSum) {
166-
unordered_map<long, int> cnt;
166+
unordered_map<long long, int> cnt;
167167
cnt[0] = 1;
168-
function<int(TreeNode*, long)> dfs = [&](TreeNode* node, long s) -> int {
169-
if (!node) return 0;
168+
auto dfs = [&](this auto&& dfs, TreeNode* node, long long s) -> int {
169+
if (!node) {
170+
return 0;
171+
}
170172
s += node->val;
171173
int ans = cnt[s - targetSum];
172174
++cnt[s];
@@ -244,6 +246,129 @@ function pathSum(root: TreeNode | null, targetSum: number): number {
244246
}
245247
```
246248

249+
#### Rust
250+
251+
```rust
252+
// Definition for a binary tree node.
253+
// #[derive(Debug, PartialEq, Eq)]
254+
// pub struct TreeNode {
255+
// pub val: i32,
256+
// pub left: Option<Rc<RefCell<TreeNode>>>,
257+
// pub right: Option<Rc<RefCell<TreeNode>>>,
258+
// }
259+
//
260+
// impl TreeNode {
261+
// #[inline]
262+
// pub fn new(val: i32) -> Self {
263+
// TreeNode {
264+
// val,
265+
// left: None,
266+
// right: None
267+
// }
268+
// }
269+
// }
270+
use std::rc::Rc;
271+
use std::cell::RefCell;
272+
use std::collections::HashMap;
273+
274+
impl Solution {
275+
pub fn path_sum(root: Option<Rc<RefCell<TreeNode>>>, target_sum: i32) -> i32 {
276+
let mut cnt = HashMap::new();
277+
cnt.insert(0, 1);
278+
279+
fn dfs(node: Option<Rc<RefCell<TreeNode>>>, s: i64, target: i64, cnt: &mut HashMap<i64, i32>) -> i32 {
280+
if let Some(n) = node {
281+
let n = n.borrow();
282+
let s = s + n.val as i64;
283+
let ans = cnt.get(&(s - target)).copied().unwrap_or(0);
284+
*cnt.entry(s).or_insert(0) += 1;
285+
let ans = ans + dfs(n.left.clone(), s, target, cnt) + dfs(n.right.clone(), s, target, cnt);
286+
*cnt.get_mut(&s).unwrap() -= 1;
287+
ans
288+
} else {
289+
0
290+
}
291+
}
292+
293+
dfs(root, 0, target_sum as i64, &mut cnt)
294+
}
295+
}
296+
```
297+
298+
#### JavaScript
299+
300+
```js
301+
/**
302+
* Definition for a binary tree node.
303+
* function TreeNode(val, left, right) {
304+
* this.val = (val===undefined ? 0 : val)
305+
* this.left = (left===undefined ? null : left)
306+
* this.right = (right===undefined ? null : right)
307+
* }
308+
*/
309+
/**
310+
* @param {TreeNode} root
311+
* @param {number} targetSum
312+
* @return {number}
313+
*/
314+
var pathSum = function (root, targetSum) {
315+
const cnt = new Map();
316+
const dfs = (node, s) => {
317+
if (!node) {
318+
return 0;
319+
}
320+
s += node.val;
321+
let ans = cnt.get(s - targetSum) || 0;
322+
cnt.set(s, (cnt.get(s) || 0) + 1);
323+
ans += dfs(node.left, s);
324+
ans += dfs(node.right, s);
325+
cnt.set(s, cnt.get(s) - 1);
326+
return ans;
327+
};
328+
cnt.set(0, 1);
329+
return dfs(root, 0);
330+
};
331+
```
332+
333+
#### C#
334+
335+
```cs
336+
/**
337+
* Definition for a binary tree node.
338+
* public class TreeNode {
339+
* public int val;
340+
* public TreeNode left;
341+
* public TreeNode right;
342+
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
343+
* this.val = val;
344+
* this.left = left;
345+
* this.right = right;
346+
* }
347+
* }
348+
*/
349+
public class Solution {
350+
public int PathSum(TreeNode root, int targetSum) {
351+
Dictionary<long, int> cnt = new Dictionary<long, int>();
352+
353+
int Dfs(TreeNode node, long s) {
354+
if (node == null) {
355+
return 0;
356+
}
357+
s += node.val;
358+
int ans = cnt.GetValueOrDefault(s - targetSum, 0);
359+
cnt[s] = cnt.GetValueOrDefault(s, 0) + 1;
360+
ans += Dfs(node.left, s);
361+
ans += Dfs(node.right, s);
362+
cnt[s]--;
363+
return ans;
364+
}
365+
366+
cnt[0] = 1;
367+
return Dfs(root, 0);
368+
}
369+
}
370+
```
371+
247372
<!-- tabs:end -->
248373

249374
<!-- solution:end -->

‎solution/0400-0499/0437.Path Sum III/README_EN.md‎

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,23 @@ tags:
5353

5454
<!-- solution:start -->
5555

56-
### Solution 1
56+
### Solution 1: Hash Table + Prefix Sum + Recursion
57+
58+
We can use the idea of prefix sums to recursively traverse the binary tree while using a hash table $\textit{cnt}$ to count the occurrences of each prefix sum along the path from the root to the current node.
59+
60+
We design a recursive function $\textit{dfs(node, s)},ドル where $\textit{node}$ represents the current node being traversed, and $s$ represents the prefix sum along the path from the root to the current node. The return value of the function is the number of paths ending at $\textit{node}$ or its subtree nodes with a sum equal to $\textit{targetSum}$. The final answer is $\textit{dfs(root, 0)}$.
61+
62+
The recursive process of $\textit{dfs(node, s)}$ is as follows:
63+
64+
- If the current node $\textit{node}$ is null, return 0ドル$.
65+
- Calculate the prefix sum $s$ along the path from the root to the current node.
66+
- Use $\textit{cnt}[s - \textit{targetSum}]$ to represent the number of paths ending at the current node with a sum equal to $\textit{targetSum}$. Here, $\textit{cnt}[s - \textit{targetSum}]$ is the count of prefix sums equal to $s - \textit{targetSum}$ in $\textit{cnt}$.
67+
- Increment the count of the prefix sum $s$ by 1ドル,ドル i.e., $\textit{cnt}[s] = \textit{cnt}[s] + 1$.
68+
- Recursively traverse the left and right child nodes of the current node by calling $\textit{dfs(node.left, s)}$ and $\textit{dfs(node.right, s)},ドル and add their return values.
69+
- After the return value is calculated, decrement the count of the prefix sum $s$ by 1ドル,ドル i.e., $\textit{cnt}[s] = \textit{cnt}[s] - 1$.
70+
- Finally, return the result.
71+
72+
The time complexity is $O(n),ドル and the space complexity is $O(n),ドル where $n$ is the number of nodes in the binary tree.
5773

5874
<!-- tabs:start -->
5975

@@ -143,10 +159,12 @@ class Solution {
143159
class Solution {
144160
public:
145161
int pathSum(TreeNode* root, int targetSum) {
146-
unordered_map<long, int> cnt;
162+
unordered_map<long long, int> cnt;
147163
cnt[0] = 1;
148-
function<int(TreeNode*, long)> dfs = [&](TreeNode* node, long s) -> int {
149-
if (!node) return 0;
164+
auto dfs = [&](this auto&& dfs, TreeNode* node, long long s) -> int {
165+
if (!node) {
166+
return 0;
167+
}
150168
s += node->val;
151169
int ans = cnt[s - targetSum];
152170
++cnt[s];
@@ -224,6 +242,129 @@ function pathSum(root: TreeNode | null, targetSum: number): number {
224242
}
225243
```
226244

245+
#### Rust
246+
247+
```rust
248+
// Definition for a binary tree node.
249+
// #[derive(Debug, PartialEq, Eq)]
250+
// pub struct TreeNode {
251+
// pub val: i32,
252+
// pub left: Option<Rc<RefCell<TreeNode>>>,
253+
// pub right: Option<Rc<RefCell<TreeNode>>>,
254+
// }
255+
//
256+
// impl TreeNode {
257+
// #[inline]
258+
// pub fn new(val: i32) -> Self {
259+
// TreeNode {
260+
// val,
261+
// left: None,
262+
// right: None
263+
// }
264+
// }
265+
// }
266+
use std::rc::Rc;
267+
use std::cell::RefCell;
268+
use std::collections::HashMap;
269+
270+
impl Solution {
271+
pub fn path_sum(root: Option<Rc<RefCell<TreeNode>>>, target_sum: i32) -> i32 {
272+
let mut cnt = HashMap::new();
273+
cnt.insert(0, 1);
274+
275+
fn dfs(node: Option<Rc<RefCell<TreeNode>>>, s: i64, target: i64, cnt: &mut HashMap<i64, i32>) -> i32 {
276+
if let Some(n) = node {
277+
let n = n.borrow();
278+
let s = s + n.val as i64;
279+
let ans = cnt.get(&(s - target)).copied().unwrap_or(0);
280+
*cnt.entry(s).or_insert(0) += 1;
281+
let ans = ans + dfs(n.left.clone(), s, target, cnt) + dfs(n.right.clone(), s, target, cnt);
282+
*cnt.get_mut(&s).unwrap() -= 1;
283+
ans
284+
} else {
285+
0
286+
}
287+
}
288+
289+
dfs(root, 0, target_sum as i64, &mut cnt)
290+
}
291+
}
292+
```
293+
294+
#### JavaScript
295+
296+
```js
297+
/**
298+
* Definition for a binary tree node.
299+
* function TreeNode(val, left, right) {
300+
* this.val = (val===undefined ? 0 : val)
301+
* this.left = (left===undefined ? null : left)
302+
* this.right = (right===undefined ? null : right)
303+
* }
304+
*/
305+
/**
306+
* @param {TreeNode} root
307+
* @param {number} targetSum
308+
* @return {number}
309+
*/
310+
var pathSum = function (root, targetSum) {
311+
const cnt = new Map();
312+
const dfs = (node, s) => {
313+
if (!node) {
314+
return 0;
315+
}
316+
s += node.val;
317+
let ans = cnt.get(s - targetSum) || 0;
318+
cnt.set(s, (cnt.get(s) || 0) + 1);
319+
ans += dfs(node.left, s);
320+
ans += dfs(node.right, s);
321+
cnt.set(s, cnt.get(s) - 1);
322+
return ans;
323+
};
324+
cnt.set(0, 1);
325+
return dfs(root, 0);
326+
};
327+
```
328+
329+
#### C#
330+
331+
```cs
332+
/**
333+
* Definition for a binary tree node.
334+
* public class TreeNode {
335+
* public int val;
336+
* public TreeNode left;
337+
* public TreeNode right;
338+
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
339+
* this.val = val;
340+
* this.left = left;
341+
* this.right = right;
342+
* }
343+
* }
344+
*/
345+
public class Solution {
346+
public int PathSum(TreeNode root, int targetSum) {
347+
Dictionary<long, int> cnt = new Dictionary<long, int>();
348+
349+
int Dfs(TreeNode node, long s) {
350+
if (node == null) {
351+
return 0;
352+
}
353+
s += node.val;
354+
int ans = cnt.GetValueOrDefault(s - targetSum, 0);
355+
cnt[s] = cnt.GetValueOrDefault(s, 0) + 1;
356+
ans += Dfs(node.left, s);
357+
ans += Dfs(node.right, s);
358+
cnt[s]--;
359+
return ans;
360+
}
361+
362+
cnt[0] = 1;
363+
return Dfs(root, 0);
364+
}
365+
}
366+
```
367+
227368
<!-- tabs:end -->
228369

229370
<!-- solution:end -->

‎solution/0400-0499/0437.Path Sum III/Solution.cpp‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
class Solution {
1313
public:
1414
int pathSum(TreeNode* root, int targetSum) {
15-
unordered_map<long, int> cnt;
15+
unordered_map<longlong, int> cnt;
1616
cnt[0] = 1;
17-
function<int(TreeNode*, long)> dfs = [&](TreeNode* node, long s) -> int {
18-
if (!node) return 0;
17+
auto dfs = [&](this auto&& dfs, TreeNode* node, long long s) -> int {
18+
if (!node) {
19+
return 0;
20+
}
1921
s += node->val;
2022
int ans = cnt[s - targetSum];
2123
++cnt[s];
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* public class TreeNode {
4+
* public int val;
5+
* public TreeNode left;
6+
* public TreeNode right;
7+
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
8+
* this.val = val;
9+
* this.left = left;
10+
* this.right = right;
11+
* }
12+
* }
13+
*/
14+
public class Solution {
15+
public int PathSum(TreeNode root, int targetSum) {
16+
Dictionary<long, int> cnt = new Dictionary<long, int>();
17+
18+
int Dfs(TreeNode node, long s) {
19+
if (node == null) {
20+
return 0;
21+
}
22+
s += node.val;
23+
int ans = cnt.GetValueOrDefault(s - targetSum, 0);
24+
cnt[s] = cnt.GetValueOrDefault(s, 0) + 1;
25+
ans += Dfs(node.left, s);
26+
ans += Dfs(node.right, s);
27+
cnt[s]--;
28+
return ans;
29+
}
30+
31+
cnt[0] = 1;
32+
return Dfs(root, 0);
33+
}
34+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /