Skip to content

Commit c0ba25c

Browse files
authored
Merge pull request #15 from rihib/combination_sum
Combination Sum
2 parents f9d3a8c + 70732a7 commit c0ba25c

File tree

4 files changed

+163
-0
lines changed

4 files changed

+163
-0
lines changed

pullrequests/combination_sum/step1.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//lint:file-ignore U1000 Ignore all unused code
2+
package template
3+
4+
/*
5+
時間:24分
6+
少し前にバックトラッキングの問題を解いたので、ある条件を満たす全ての組み合わせを求めるためにバックトラッキングを使って解きました。
7+
*/
8+
func combinationSumStep1(candidates []int, target int) [][]int {
9+
var combinations [][]int
10+
var stack []int
11+
var findCombinations func(int, int)
12+
findCombinations = func(curr int, sum int) {
13+
if sum == target {
14+
combination := make([]int, len(stack))
15+
copy(combination, stack)
16+
combinations = append(combinations, combination)
17+
return
18+
}
19+
if sum > target {
20+
return
21+
}
22+
for i := curr; i < len(candidates); i++ {
23+
stack = append(stack, candidates[i])
24+
findCombinations(i, sum+candidates[i])
25+
stack = stack[:len(stack)-1]
26+
}
27+
}
28+
findCombinations(0, 0)
29+
return combinations
30+
}

pullrequests/combination_sum/step2.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//lint:file-ignore U1000 Ignore all unused code
2+
package template
3+
4+
/*
5+
Step1では再帰を使ってバックトラッキングを解いたので、スタックを使った方法も実装しました。
6+
また、Step1の実装のリファクタもしました。
7+
*/
8+
func combinationSumBacktrackingStack(candidates []int, target int) [][]int {
9+
combinations := [][]int{}
10+
type state struct {
11+
combination []int
12+
sum int
13+
index int
14+
}
15+
stack := []state{{[]int{}, 0, 0}}
16+
for len(stack) > 0 {
17+
current := stack[len(stack)-1]
18+
stack = stack[:len(stack)-1]
19+
if current.sum == target {
20+
combinations = append(combinations, append([]int{}, current.combination...))
21+
continue
22+
}
23+
for i := current.index; i < len(candidates); i++ {
24+
newSum := current.sum + candidates[i]
25+
if newSum > target {
26+
continue
27+
}
28+
newCombination := append([]int{}, current.combination...)
29+
newCombination = append(newCombination, candidates[i])
30+
stack = append(stack, state{newCombination, newSum, i})
31+
}
32+
}
33+
return combinations
34+
}
35+
36+
func combinationSumBacktrackingRecursion(candidates []int, target int) [][]int {
37+
var combinations [][]int
38+
var stack []int
39+
var generateCombinations func(int, int)
40+
generateCombinations = func(currentIndex int, sum int) {
41+
if sum == target {
42+
combinations = append(combinations, append([]int{}, stack...))
43+
return
44+
}
45+
if sum > target {
46+
return
47+
}
48+
for i := currentIndex; i < len(candidates); i++ {
49+
stack = append(stack, candidates[i])
50+
generateCombinations(i, sum+candidates[i])
51+
stack = stack[:len(stack)-1]
52+
}
53+
}
54+
generateCombinations(0, 0)
55+
return combinations
56+
}

pullrequests/combination_sum/step3.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//lint:file-ignore U1000 Ignore all unused code
2+
package template
3+
4+
/*
5+
動的計画法を使った方法も実装しました。
6+
targetごとに組み合わせを求めると重複する組み合わせが生じてしまうので、candidateごとに組み合わせを求めるようにしました。
7+
*/
8+
func combinationSumDP(candidates []int, target int) [][]int {
9+
combinationsGroups := make([][][]int, target+1)
10+
combinationsGroups[0] = [][]int{{}}
11+
for _, candidate := range candidates {
12+
for i := candidate; i <= target; i++ {
13+
for _, combination := range combinationsGroups[i-candidate] {
14+
newCombination := append([]int{}, combination...)
15+
newCombination = append(newCombination, candidate)
16+
combinationsGroups[i] = append(combinationsGroups[i], newCombination)
17+
}
18+
}
19+
}
20+
return combinationsGroups[target]
21+
}

pullrequests/combination_sum/step4.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//lint:file-ignore U1000 Ignore all unused code
2+
package template
3+
4+
/*
5+
Step1では再帰を使ってバックトラッキングを解いたので、スタックを使った方法も実装しました。
6+
また、Step1の実装のリファクタもしました。
7+
*/
8+
func combinationSumBacktrackingStackStep4(candidates []int, target int) [][]int {
9+
combinations := [][]int{}
10+
type state struct {
11+
combination []int
12+
sum int
13+
index int
14+
}
15+
stack := []state{{[]int{}, 0, 0}}
16+
for len(stack) > 0 {
17+
current := stack[len(stack)-1]
18+
stack = stack[:len(stack)-1]
19+
if current.sum == target {
20+
combinations = append(combinations, current.combination)
21+
continue
22+
}
23+
for i := current.index; i < len(candidates); i++ {
24+
newSum := current.sum + candidates[i]
25+
if newSum > target {
26+
continue
27+
}
28+
newCombination := append([]int{}, current.combination...)
29+
newCombination = append(newCombination, candidates[i])
30+
stack = append(stack, state{newCombination, newSum, i})
31+
}
32+
}
33+
return combinations
34+
}
35+
36+
func combinationSumBacktrackingRecursionStep4(candidates []int, target int) [][]int {
37+
var combinations [][]int
38+
var stack []int
39+
var generateCombinations func(int, int)
40+
generateCombinations = func(currentIndex int, sum int) {
41+
if sum == target {
42+
combinations = append(combinations, append([]int{}, stack...))
43+
return
44+
}
45+
if sum > target {
46+
return
47+
}
48+
for i := currentIndex; i < len(candidates); i++ {
49+
stack = append(stack, candidates[i])
50+
generateCombinations(i, sum+candidates[i])
51+
stack = stack[:len(stack)-1]
52+
}
53+
}
54+
generateCombinations(0, 0)
55+
return combinations
56+
}

0 commit comments

Comments
 (0)