Skip to content

Commit a74e8cf

Browse files
committed
init commit
0 parents  commit a74e8cf

File tree

8 files changed

+247
-0
lines changed

8 files changed

+247
-0
lines changed

.github/workflows/go.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: go
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v2
17+
- name: Setup Go
18+
uses: actions/setup-go@v2
19+
with:
20+
go-version: 1.16
21+
- name: Build
22+
run: go build -v ./...
23+
- name: Test
24+
run: go test -v -cover ./...
25+
- name: Benchmark
26+
run: go test -benchmem -run=none -bench ^BenchmarkTest$ sol/sol

.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work

.gitlab-ci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
stages:
2+
- test
3+
build and test:
4+
image: golang:1.16
5+
stage: test
6+
script:
7+
- go build -v ./...
8+
- go test -v -cover ./...
9+
- go test -benchmem -run=none -bench ^BenchmarkTest$ sol/sol

.husky/pre-commit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
go test -v -cover ./...

README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# golang_combination_sum
2+
3+
Given an array of **distinct** integers `candidates` and a target integer `target`, return *a list of all **unique combinations** of* `candidates` *where the chosen numbers sum to* `target`*.* You may return the combinations in **any order**.
4+
5+
The **same** number may be chosen from `candidates` an **unlimited number of times**. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
6+
7+
It is **guaranteed** that the number of unique combinations that sum up to `target` is less than `150` combinations for the given input.
8+
9+
## Examples
10+
11+
**Example 1:**
12+
13+
```
14+
Input: candidates = [2,3,6,7], target = 7
15+
Output: [[2,2,3],[7]]
16+
Explanation:
17+
2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
18+
7 is a candidate, and 7 = 7.
19+
These are the only two combinations.
20+
21+
```
22+
23+
**Example 2:**
24+
25+
```
26+
Input: candidates = [2,3,5], target = 8
27+
Output: [[2,2,2,2],[2,3,3],[3,5]]
28+
29+
```
30+
31+
**Example 3:**
32+
33+
```
34+
Input: candidates = [2], target = 1
35+
Output: []
36+
37+
```
38+
39+
**Constraints:**
40+
41+
- `1 <= candidates.length <= 30`
42+
- `1 <= candidates[i] <= 200`
43+
- All elements of `candidates` are **distinct**.
44+
- `1 <= target <= 500`
45+
46+
## 解析
47+
48+
給定一個整數陣列 nums 還有一個整數 target
49+
50+
要求要寫出一個演算法來找出和為 target 的所有 nums 內元素不重複組合
51+
52+
可以利用類似 PowerSet 個概念
53+
54+
分為選擇該數值或是不選該數值的 decision tree
55+
56+
每次先檢查當選了該數值還可以繼續則及續選
57+
58+
否則就往下一個數值檢查
59+
60+
概念圖如下
61+
62+
![](https://i.imgur.com/dtvXlz9.png)
63+
64+
## 程式碼
65+
```go
66+
package sol
67+
68+
func combinationSum(candidates []int, target int) [][]int {
69+
result := [][]int{}
70+
71+
var dfs func(i int, cur []int, total int)
72+
dfs = func(i int, cur []int, total int) {
73+
// break condition
74+
if total == target {
75+
temp := make([]int, len(cur))
76+
copy(temp, cur)
77+
result = append(result, temp)
78+
return
79+
}
80+
// prune not possible path
81+
if i >= len(candidates) || total > target {
82+
return
83+
}
84+
85+
// choose i
86+
cur = append(cur, candidates[i])
87+
dfs(i, cur, total+candidates[i])
88+
89+
// not choose i, next choose
90+
cur = cur[:len(cur)-1]
91+
dfs(i+1, cur, total)
92+
}
93+
dfs(0, []int{}, 0)
94+
return result
95+
}
96+
97+
```
98+
## 困難點
99+
100+
1. 理解如何做窮舉法
101+
2. 理解如何窮舉出不重複的方式
102+
3. 需要理解 golang slice 只是 array 的 reference, 要保存值只能透過 copy 方式
103+
104+
## Solve Point
105+
106+
- [x] Understand what problem to solve
107+
- [x] Analysis Complexity

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module sol
2+
3+
go 1.16

sol/solution.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package sol
2+
3+
func combinationSum(candidates []int, target int) [][]int {
4+
result := [][]int{}
5+
6+
var dfs func(i int, cur []int, total int)
7+
dfs = func(i int, cur []int, total int) {
8+
// break condition
9+
if total == target {
10+
temp := make([]int, len(cur))
11+
copy(temp, cur)
12+
result = append(result, temp)
13+
return
14+
}
15+
// prune not possible path
16+
if i >= len(candidates) || total > target {
17+
return
18+
}
19+
20+
// choose i
21+
cur = append(cur, candidates[i])
22+
dfs(i, cur, total+candidates[i])
23+
24+
// not choose i, next choose
25+
cur = cur[:len(cur)-1]
26+
dfs(i+1, cur, total)
27+
}
28+
dfs(0, []int{}, 0)
29+
return result
30+
}

sol/solution_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package sol
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
func BenchmarkTest(b *testing.B) {
9+
candidates := []int{2, 3, 6, 7}
10+
target := 7
11+
for idx := 0; idx < b.N; idx++ {
12+
combinationSum(candidates, target)
13+
}
14+
}
15+
16+
func Test_combinationSum(t *testing.T) {
17+
type args struct {
18+
candidates []int
19+
target int
20+
}
21+
tests := []struct {
22+
name string
23+
args args
24+
want [][]int
25+
}{
26+
{
27+
name: "candidates = [2,3,6,7], target = 7",
28+
args: args{candidates: []int{2, 3, 6, 7}, target: 7},
29+
want: [][]int{{2, 2, 3}, {7}},
30+
},
31+
{
32+
name: "candidates = [2,3,5], target = 8",
33+
args: args{candidates: []int{2, 3, 5}, target: 8},
34+
want: [][]int{{2, 2, 2, 2}, {2, 3, 3}, {3, 5}},
35+
},
36+
{
37+
name: "candidates = [2], target = 1",
38+
args: args{candidates: []int{2}, target: 1},
39+
want: [][]int{},
40+
},
41+
}
42+
for _, tt := range tests {
43+
t.Run(tt.name, func(t *testing.T) {
44+
if got := combinationSum(tt.args.candidates, tt.args.target); !reflect.DeepEqual(got, tt.want) {
45+
t.Errorf("combinationSum() = %v, want %v", got, tt.want)
46+
}
47+
})
48+
}
49+
}

0 commit comments

Comments
 (0)