Skip to content

Commit 24c20c3

Browse files
committed
feat: add solutions to lcof2 problem: No.082
lcof2 No.082.Combination Sum II
1 parent 9241d53 commit 24c20c3

File tree

13 files changed

+379
-79
lines changed

13 files changed

+379
-79
lines changed

lcof2/剑指 Offer II 049. 从根节点到叶节点的路径数字之和/README.md

+14-16
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,9 @@ public:
149149
}
150150

151151
int dfs(TreeNode *root, int presum) {
152-
if (root == nullptr)
153-
return 0;
152+
if (!root) return 0;
154153
int s = presum * 10 + root->val;
155-
if (root->left == nullptr && root->right == nullptr)
156-
return s;
154+
if (!root->left && !root->right) return s;
157155
return dfs(root->left, s) + dfs(root->right, s);
158156
}
159157
};
@@ -171,17 +169,17 @@ public:
171169
* }
172170
*/
173171
func sumNumbers(root *TreeNode) int {
174-
return dfs(root, 0)
175-
}
176-
177-
func dfs(root *TreeNode, presum int) int {
178-
if root == nil {
179-
return 0
180-
}
181-
s := presum*10 + root.Val
182-
if root.Left == nil && root.Right == nil {
183-
return s
184-
}
185-
return dfs(root.Left, s) + dfs(root.Right, s)
172+
var dfs func(root *TreeNode, presum int) int
173+
dfs = func(root *TreeNode, presum int) int {
174+
if root == nil {
175+
return 0
176+
}
177+
presum = presum * 10 + root.Val
178+
if root.Left == nil && root.Right == nil {
179+
return presum
180+
}
181+
return dfs(root.Left, presum) + dfs(root.Right, presum)
182+
}
183+
return dfs(root, 0)
186184
}
187185
```

lcof2/剑指 Offer II 049. 从根节点到叶节点的路径数字之和/Solution.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@ class Solution {
1616
}
1717

1818
int dfs(TreeNode *root, int presum) {
19-
if (root == nullptr)
20-
return 0;
19+
if (!root) return 0;
2120
int s = presum * 10 + root->val;
22-
if (root->left == nullptr && root->right == nullptr)
23-
return s;
21+
if (!root->left && !root->right) return s;
2422
return dfs(root->left, s) + dfs(root->right, s);
2523
}
2624
};

lcof2/剑指 Offer II 049. 从根节点到叶节点的路径数字之和/Solution.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
* }
88
*/
99
func sumNumbers(root *TreeNode) int {
10-
return dfs(root, 0)
11-
}
12-
13-
func dfs(root *TreeNode, presum int) int {
14-
if root == nil {
15-
return 0
16-
}
17-
s := presum*10 + root.Val
18-
if root.Left == nil && root.Right == nil {
19-
return s
10+
var dfs func(root *TreeNode, presum int) int
11+
dfs = func(root *TreeNode, presum int) int {
12+
if root == nil {
13+
return 0
14+
}
15+
presum = presum*10 + root.Val
16+
if root.Left == nil && root.Right == nil {
17+
return presum
18+
}
19+
return dfs(root.Left, presum) + dfs(root.Right, presum)
2020
}
21-
return dfs(root.Left, s) + dfs(root.Right, s)
21+
return dfs(root, 0)
2222
}

lcof2/剑指 Offer II 082. 含有重复元素集合的组合/README.md

+129-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@
4848

4949
## 解法
5050

51+
DFS 回溯法。需要先对 candidates 数组进行排序。
52+
53+
去重技巧:
54+
55+
```python
56+
if i > u and candidates[i] == candidates[i - 1]:
57+
continue
58+
```
59+
5160
<!-- 这里可写通用的实现逻辑 -->
5261

5362
<!-- tabs:start -->
@@ -57,15 +66,134 @@
5766
<!-- 这里可写当前语言的特殊实现逻辑 -->
5867

5968
```python
60-
69+
class Solution:
70+
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
71+
def dfs(u, s, t):
72+
if s > target:
73+
return
74+
if s == target:
75+
ans.append(t[:])
76+
return
77+
for i in range(u, len(candidates)):
78+
if i > u and candidates[i] == candidates[i - 1]:
79+
continue
80+
t.append(candidates[i])
81+
dfs(i + 1, s + candidates[i], t)
82+
t.pop()
83+
84+
ans = []
85+
candidates.sort()
86+
dfs(0, 0, [])
87+
return ans
6188
```
6289

6390
### **Java**
6491

6592
<!-- 这里可写当前语言的特殊实现逻辑 -->
6693

6794
```java
95+
class Solution {
96+
private List<List<Integer>> ans;
97+
private int[] candidates;
98+
private int target;
99+
100+
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
101+
ans = new ArrayList<>();
102+
Arrays.sort(candidates);
103+
this.target = target;
104+
this.candidates = candidates;
105+
dfs(0, 0, new ArrayList<>());
106+
return ans;
107+
}
108+
109+
private void dfs(int u, int s, List<Integer> t) {
110+
if (s > target) {
111+
return;
112+
}
113+
if (s == target) {
114+
ans.add(new ArrayList<>(t));
115+
return;
116+
}
117+
for (int i = u; i < candidates.length; ++i) {
118+
if (i > u && candidates[i] == candidates[i - 1]) {
119+
continue;
120+
}
121+
t.add(candidates[i]);
122+
dfs(i + 1, s + candidates[i], t);
123+
t.remove(t.size() - 1);
124+
}
125+
}
126+
}
127+
```
128+
129+
### **C++**
130+
131+
```cpp
132+
class Solution {
133+
public:
134+
vector<int> candidates;
135+
vector<vector<int>> ans;
136+
vector<int> t;
137+
int target;
138+
139+
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
140+
sort(candidates.begin(), candidates.end());
141+
this->candidates = candidates;
142+
this->target = target;
143+
vector<int> t;
144+
dfs(0, 0, t);
145+
return ans;
146+
}
147+
148+
void dfs(int u, int s, vector<int>& t) {
149+
if (s > target) return;
150+
if (s == target)
151+
{
152+
ans.push_back(t);
153+
return;
154+
}
155+
for (int i = u; i < candidates.size(); ++i)
156+
{
157+
if (i > u && candidates[i] == candidates[i - 1]) continue;
158+
t.push_back(candidates[i]);
159+
dfs(i + 1, s + candidates[i], t);
160+
t.pop_back();
161+
}
162+
}
163+
};
164+
```
68165
166+
### **Go**
167+
168+
```go
169+
func combinationSum2(candidates []int, target int) [][]int {
170+
var ans [][]int
171+
var t []int
172+
sort.Ints(candidates)
173+
var dfs func(u, s int, t []int)
174+
dfs = func(u, s int, t []int) {
175+
if s > target {
176+
return
177+
}
178+
if s == target {
179+
cp := make([]int, len(t))
180+
copy(cp, t)
181+
ans = append(ans, cp)
182+
return
183+
}
184+
for i := u; i < len(candidates); i++ {
185+
if i > u && candidates[i] == candidates[i-1] {
186+
continue
187+
}
188+
t = append(t, candidates[i])
189+
dfs(i+1, s+candidates[i], t)
190+
t = t[:len(t)-1]
191+
}
192+
}
193+
194+
dfs(0, 0, t)
195+
return ans
196+
}
69197
```
70198

71199
### **...**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class Solution {
2+
public:
3+
vector<int> candidates;
4+
vector<vector<int>> ans;
5+
vector<int> t;
6+
int target;
7+
8+
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
9+
sort(candidates.begin(), candidates.end());
10+
this->candidates = candidates;
11+
this->target = target;
12+
vector<int> t;
13+
dfs(0, 0, t);
14+
return ans;
15+
}
16+
17+
void dfs(int u, int s, vector<int>& t) {
18+
if (s > target) return;
19+
if (s == target)
20+
{
21+
ans.push_back(t);
22+
return;
23+
}
24+
for (int i = u; i < candidates.size(); ++i)
25+
{
26+
if (i > u && candidates[i] == candidates[i - 1]) continue;
27+
t.push_back(candidates[i]);
28+
dfs(i + 1, s + candidates[i], t);
29+
t.pop_back();
30+
}
31+
}
32+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
public class Solution
6+
{
7+
public IList<IList<int>> CombinationSum2(int[] candidates, int target)
8+
{
9+
var dict = new SortedDictionary<int, int>(candidates.GroupBy(c => c).ToDictionary(g => g.Key, g => g.Count()));
10+
var paths = new List<Tuple<int, int>>[target + 1];
11+
paths[0] = new List<Tuple<int, int>>();
12+
foreach (var pair in dict)
13+
{
14+
for (var j = target; j >= 0; --j)
15+
{
16+
for (var k = 1; k <= pair.Value && j - pair.Key * k >= 0; ++k)
17+
{
18+
if (paths[j - pair.Key * k] != null)
19+
{
20+
if (paths[j] == null)
21+
{
22+
paths[j] = new List<Tuple<int, int>>();
23+
}
24+
paths[j].Add(Tuple.Create(pair.Key, k));
25+
}
26+
}
27+
}
28+
}
29+
30+
var results = new List<IList<int>>();
31+
if (paths[target] != null) GenerateResults(results, new Stack<int>(), paths, target, paths[target].Count - 1);
32+
return results;
33+
}
34+
35+
private void GenerateResults(IList<IList<int>> results, Stack<int> result, List<Tuple<int, int>>[] paths, int remaining,
36+
int maxIndex)
37+
{
38+
if (remaining == 0)
39+
{
40+
results.Add(new List<int>(result));
41+
return;
42+
}
43+
for (var i = maxIndex; i >= 0; --i)
44+
{
45+
var path = paths[remaining][i];
46+
for (var j = 0; j < path.Item2; ++j)
47+
{
48+
result.Push(path.Item1);
49+
}
50+
var nextMaxIndex = paths[remaining - path.Item1 * path.Item2].BinarySearch(Tuple.Create(path.Item1, int.MinValue), Comparer.Instance);
51+
nextMaxIndex = ~nextMaxIndex - 1;
52+
GenerateResults(results, result, paths, remaining - path.Item1 * path.Item2, nextMaxIndex);
53+
for (var j = 0; j < path.Item2; ++j)
54+
{
55+
result.Pop();
56+
}
57+
}
58+
}
59+
}
60+
61+
class Comparer : IComparer<Tuple<int, int>>
62+
{
63+
public int Compare(Tuple<int, int> x, Tuple<int, int> y)
64+
{
65+
if (x.Item1 < y.Item1) return -1;
66+
if (x.Item1 > y.Item1) return 1;
67+
return x.Item2.CompareTo(y.Item2);
68+
}
69+
70+
public static Comparer Instance = new Comparer();
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
func combinationSum2(candidates []int, target int) [][]int {
2+
var ans [][]int
3+
var t []int
4+
sort.Ints(candidates)
5+
var dfs func(u, s int, t []int)
6+
dfs = func(u, s int, t []int) {
7+
if s > target {
8+
return
9+
}
10+
if s == target {
11+
cp := make([]int, len(t))
12+
copy(cp, t)
13+
ans = append(ans, cp)
14+
return
15+
}
16+
for i := u; i < len(candidates); i++ {
17+
if i > u && candidates[i] == candidates[i-1] {
18+
continue
19+
}
20+
t = append(t, candidates[i])
21+
dfs(i+1, s+candidates[i], t)
22+
t = t[:len(t)-1]
23+
}
24+
}
25+
26+
dfs(0, 0, t)
27+
return ans
28+
}

0 commit comments

Comments
 (0)