Skip to content

Commit fc27d5e

Browse files
committed
feat: update solutions to lc problem: No.0437
No.0437.Path Sum III
1 parent 41c173b commit fc27d5e

File tree

6 files changed

+190
-240
lines changed

6 files changed

+190
-240
lines changed

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

+81-87
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,23 @@
4343

4444
<!-- 这里可写通用的实现逻辑 -->
4545

46-
在遍历的过程中,记录当前路径上的前缀和
46+
**方法一:哈希表 + 前缀和 + 递归**
47+
48+
我们可以运用前缀和的思想,对二叉树进行递归遍历,同时用哈希表 $cnt$ 统计从根节点到当前节点的路径上各个前缀和出现的次数。
49+
50+
我们设计一个递归函数 $dfs(node, s)$,表示当前遍历到的节点为 $node$,从根节点到当前节点的路径上的前缀和为 $s$。函数的返回值是统计以 $node$ 节点及其子树节点作为路径终点且路径和为 $targetSum$ 的路径数目。那么答案就是 $dfs(root, 0)$。
51+
52+
函数 $dfs(node, s)$ 的递归过程如下:
53+
54+
- 如果当前节点 $node$ 为空,则返回 $0$。
55+
- 计算从根节点到当前节点的路径上的前缀和 $s$。
56+
- 用 $cnt[s - targetSum]$ 表示以当前节点为路径终点且路径和为 $targetSum$ 的路径数目,其中 $cnt[s - targetSum]$ 即为 $cnt$ 中前缀和为 $s - targetSum$ 的个数。
57+
- 将前缀和 $s$ 的计数值加 $1$,即 $cnt[s] = cnt[s] + 1$。
58+
- 递归地遍历当前节点的左右子节点,即调用函数 $dfs(node.left, s)$ 和 $dfs(node.right, s)$,并将它们的返回值相加。
59+
- 在返回值计算完成以后,需要将当前节点的前缀和 $s$ 的计数值减 $1$,即执行 $cnt[s] = cnt[s] - 1$。
60+
- 最后返回答案。
61+
62+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。
4763

4864
<!-- tabs:start -->
4965

@@ -59,24 +75,19 @@
5975
# self.left = left
6076
# self.right = right
6177
class Solution:
62-
def pathSum(self, root: TreeNode, targetSum: int) -> int:
63-
preSum = defaultdict(int)
64-
preSum[0] = 1
65-
66-
def dfs(node: TreeNode, cur: int) -> int:
67-
if not node:
78+
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> int:
79+
def dfs(node, s):
80+
if node is None:
6881
return 0
69-
70-
cur += node.val
71-
ret = preSum[cur - targetSum]
72-
73-
preSum[cur] += 1
74-
ret += dfs(node.left, cur)
75-
ret += dfs(node.right, cur)
76-
preSum[cur] -= 1
77-
78-
return ret
79-
82+
s += node.val
83+
ans = cnt[s - targetSum]
84+
cnt[s] += 1
85+
ans += dfs(node.left, s)
86+
ans += dfs(node.right, s)
87+
cnt[s] -= 1
88+
return ans
89+
90+
cnt = Counter({0: 1})
8091
return dfs(root, 0)
8192
```
8293

@@ -101,68 +112,30 @@ class Solution:
101112
* }
102113
*/
103114
class Solution {
104-
105-
private final Map<Integer, Integer> preSum = new HashMap<>();
115+
private Map<Long, Integer> cnt = new HashMap<>();
116+
private int targetSum;
106117

107118
public int pathSum(TreeNode root, int targetSum) {
108-
preSum.put(0, 1);
109-
return dfs(root, 0, targetSum);
119+
cnt.put(0L, 1);
120+
this.targetSum = targetSum;
121+
return dfs(root, 0);
110122
}
111123

112-
private int dfs(TreeNode node, int cur, int targetSum) {
124+
private int dfs(TreeNode node, long s) {
113125
if (node == null) {
114126
return 0;
115127
}
116-
117-
cur += node.val;
118-
int ret = preSum.getOrDefault(cur - targetSum, 0);
119-
120-
preSum.merge(cur, 1, Integer::sum);
121-
ret += dfs(node.left, cur, targetSum);
122-
ret += dfs(node.right, cur, targetSum);
123-
preSum.merge(cur, -1, Integer::sum);
124-
125-
return ret;
128+
s += node.val;
129+
int ans = cnt.getOrDefault(s - targetSum, 0);
130+
cnt.merge(s, 1, Integer::sum);
131+
ans += dfs(node.left, s);
132+
ans += dfs(node.right, s);
133+
cnt.merge(s, -1, Integer::sum);
134+
return ans;
126135
}
127136
}
128137
```
129138

130-
### **Go**
131-
132-
```go
133-
/**
134-
* Definition for a binary tree node.
135-
* type TreeNode struct {
136-
* Val int
137-
* Left *TreeNode
138-
* Right *TreeNode
139-
* }
140-
*/
141-
func pathSum(root *TreeNode, targetSum int) int {
142-
preSum := make(map[int]int)
143-
preSum[0] = 1
144-
145-
var dfs func(*TreeNode, int) int
146-
dfs = func(node *TreeNode, cur int) int {
147-
if node == nil {
148-
return 0
149-
}
150-
151-
cur += node.Val
152-
ret := preSum[cur-targetSum]
153-
154-
preSum[cur]++
155-
ret += dfs(node.Left, cur)
156-
ret += dfs(node.Right, cur)
157-
preSum[cur]--
158-
159-
return ret
160-
}
161-
162-
return dfs(root, 0)
163-
}
164-
```
165-
166139
### **C++**
167140

168141
```cpp
@@ -180,30 +153,51 @@ func pathSum(root *TreeNode, targetSum int) int {
180153
class Solution {
181154
public:
182155
int pathSum(TreeNode* root, int targetSum) {
183-
unordered_map<int, int> preSum;
184-
preSum[0] = 1;
185-
186-
function<int(TreeNode*, int)> dfs = [&](TreeNode* node, int cur) {
187-
if (node == nullptr) {
188-
return 0;
189-
}
190-
191-
cur += node->val;
192-
int ret = preSum[cur - targetSum];
193-
194-
++preSum[cur];
195-
ret += dfs(node->left, cur);
196-
ret += dfs(node->right, cur);
197-
--preSum[cur];
198-
199-
return ret;
156+
unordered_map<long, int> cnt;
157+
cnt[0] = 1;
158+
function<int(TreeNode*, long)> dfs = [&](TreeNode* node, long s) -> int {
159+
if (!node) return 0;
160+
s += node->val;
161+
int ans = cnt[s - targetSum];
162+
++cnt[s];
163+
ans += dfs(node->left, s) + dfs(node->right, s);
164+
--cnt[s];
165+
return ans;
200166
};
201-
202167
return dfs(root, 0);
203168
}
204169
};
205170
```
206171
172+
### **Go**
173+
174+
```go
175+
/**
176+
* Definition for a binary tree node.
177+
* type TreeNode struct {
178+
* Val int
179+
* Left *TreeNode
180+
* Right *TreeNode
181+
* }
182+
*/
183+
func pathSum(root *TreeNode, targetSum int) int {
184+
cnt := map[int]int{0: 1}
185+
var dfs func(*TreeNode, int) int
186+
dfs = func(node *TreeNode, s int) int {
187+
if node == nil {
188+
return 0
189+
}
190+
s += node.Val
191+
ans := cnt[s-targetSum]
192+
cnt[s]++
193+
ans += dfs(node.Left, s) + dfs(node.Right, s)
194+
cnt[s]--
195+
return ans
196+
}
197+
return dfs(root, 0)
198+
}
199+
```
200+
207201
### **...**
208202

209203
```

0 commit comments

Comments
 (0)