From 65d15cc942bfa561d97710aaacdea13efaded6c6 Mon Sep 17 00:00:00 2001 From: rihib Date: Sun, 11 Aug 2024 17:54:02 +0900 Subject: [PATCH 1/2] pullrequests/combination_sum --- pullrequests/combination_sum/step1.go | 30 ++++++++++++++ pullrequests/combination_sum/step2.go | 56 +++++++++++++++++++++++++++ pullrequests/combination_sum/step3.go | 21 ++++++++++ 3 files changed, 107 insertions(+) create mode 100644 pullrequests/combination_sum/step1.go create mode 100644 pullrequests/combination_sum/step2.go create mode 100644 pullrequests/combination_sum/step3.go diff --git a/pullrequests/combination_sum/step1.go b/pullrequests/combination_sum/step1.go new file mode 100644 index 0000000..03e2ad5 --- /dev/null +++ b/pullrequests/combination_sum/step1.go @@ -0,0 +1,30 @@ +//lint:file-ignore U1000 Ignore all unused code +package template + +/* +時間:24分 +少し前にバックトラッキングの問題を解いたので、ある条件を満たす全ての組み合わせを求めるためにバックトラッキングを使って解きました。 +*/ +func combinationSum_step1(candidates []int, target int) [][]int { + var combinations [][]int + var stack []int + var findCombinations func(int, int) + findCombinations = func(curr int, sum int) { + if sum == target { + combination := make([]int, len(stack)) + copy(combination, stack) + combinations = append(combinations, combination) + return + } + if sum > target { + return + } + for i := curr; i < len(candidates); i++ { + stack = append(stack, candidates[i]) + findCombinations(i, sum+candidates[i]) + stack = stack[:len(stack)-1] + } + } + findCombinations(0, 0) + return combinations +} diff --git a/pullrequests/combination_sum/step2.go b/pullrequests/combination_sum/step2.go new file mode 100644 index 0000000..85acb26 --- /dev/null +++ b/pullrequests/combination_sum/step2.go @@ -0,0 +1,56 @@ +//lint:file-ignore U1000 Ignore all unused code +package template + +/* +Step1では再帰を使ってバックトラッキングを解いたので、スタックを使った方法も実装しました。 +また、Step1の実装のリファクタもしました。 +*/ +func combinationSum_backtracking_stack(candidates []int, target int) [][]int { + combinations := [][]int{} + type state struct { + combination []int + sum int + index int + } + stack := []state{{[]int{}, 0, 0}} + for len(stack) > 0 { + current := stack[len(stack)-1] + stack = stack[:len(stack)-1] + if current.sum == target { + combinations = append(combinations, append([]int{}, current.combination...)) + continue + } + for i := current.index; i < len(candidates); i++ { + newSum := current.sum + candidates[i] + if newSum > target { + continue + } + newCombination := append([]int{}, current.combination...) + newCombination = append(newCombination, candidates[i]) + stack = append(stack, state{newCombination, newSum, i}) + } + } + return combinations +} + +func combinationSum_backtracking_recursion(candidates []int, target int) [][]int { + var combinations [][]int + var stack []int + var generateCombinations func(int, int) + generateCombinations = func(currentIndex int, sum int) { + if sum == target { + combinations = append(combinations, append([]int{}, stack...)) + return + } + if sum > target { + return + } + for i := currentIndex; i < len(candidates); i++ { + stack = append(stack, candidates[i]) + generateCombinations(i, sum+candidates[i]) + stack = stack[:len(stack)-1] + } + } + generateCombinations(0, 0) + return combinations +} diff --git a/pullrequests/combination_sum/step3.go b/pullrequests/combination_sum/step3.go new file mode 100644 index 0000000..08a3b32 --- /dev/null +++ b/pullrequests/combination_sum/step3.go @@ -0,0 +1,21 @@ +//lint:file-ignore U1000 Ignore all unused code +package template + +/* +動的計画法を使った方法も実装しました。 +targetごとに組み合わせを求めると重複する組み合わせが生じてしまうので、candidateごとに組み合わせを求めるようにしました。 +*/ +func combinationSum_dp(candidates []int, target int) [][]int { + combinationsGroups := make([][][]int, target+1) + combinationsGroups[0] = [][]int{{}} + for _, candidate := range candidates { + for i := candidate; i <= target; i++ { + for _, combination := range combinationsGroups[i-candidate] { + newCombination := append([]int{}, combination...) + newCombination = append(newCombination, candidate) + combinationsGroups[i] = append(combinationsGroups[i], newCombination) + } + } + } + return combinationsGroups[target] +} From 3865ccc0abbd85e4c264f057ef5aa212a16b4e8a Mon Sep 17 00:00:00 2001 From: rihib Date: Mon, 23 Sep 2024 22:33:25 +0900 Subject: [PATCH 2/2] fix pullrequests/combination_sum --- pullrequests/combination_sum/step1.go | 2 +- pullrequests/combination_sum/step2.go | 4 +- pullrequests/combination_sum/step3.go | 2 +- pullrequests/combination_sum/step4.go | 56 +++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 pullrequests/combination_sum/step4.go diff --git a/pullrequests/combination_sum/step1.go b/pullrequests/combination_sum/step1.go index 03e2ad5..31819b8 100644 --- a/pullrequests/combination_sum/step1.go +++ b/pullrequests/combination_sum/step1.go @@ -5,7 +5,7 @@ package template 時間:24分 少し前にバックトラッキングの問題を解いたので、ある条件を満たす全ての組み合わせを求めるためにバックトラッキングを使って解きました。 */ -func combinationSum_step1(candidates []int, target int) [][]int { +func combinationSumStep1(candidates []int, target int) [][]int { var combinations [][]int var stack []int var findCombinations func(int, int) diff --git a/pullrequests/combination_sum/step2.go b/pullrequests/combination_sum/step2.go index 85acb26..28644ff 100644 --- a/pullrequests/combination_sum/step2.go +++ b/pullrequests/combination_sum/step2.go @@ -5,7 +5,7 @@ package template Step1では再帰を使ってバックトラッキングを解いたので、スタックを使った方法も実装しました。 また、Step1の実装のリファクタもしました。 */ -func combinationSum_backtracking_stack(candidates []int, target int) [][]int { +func combinationSumBacktrackingStack(candidates []int, target int) [][]int { combinations := [][]int{} type state struct { combination []int @@ -33,7 +33,7 @@ func combinationSum_backtracking_stack(candidates []int, target int) [][]int { return combinations } -func combinationSum_backtracking_recursion(candidates []int, target int) [][]int { +func combinationSumBacktrackingRecursion(candidates []int, target int) [][]int { var combinations [][]int var stack []int var generateCombinations func(int, int) diff --git a/pullrequests/combination_sum/step3.go b/pullrequests/combination_sum/step3.go index 08a3b32..13715f3 100644 --- a/pullrequests/combination_sum/step3.go +++ b/pullrequests/combination_sum/step3.go @@ -5,7 +5,7 @@ package template 動的計画法を使った方法も実装しました。 targetごとに組み合わせを求めると重複する組み合わせが生じてしまうので、candidateごとに組み合わせを求めるようにしました。 */ -func combinationSum_dp(candidates []int, target int) [][]int { +func combinationSumDP(candidates []int, target int) [][]int { combinationsGroups := make([][][]int, target+1) combinationsGroups[0] = [][]int{{}} for _, candidate := range candidates { diff --git a/pullrequests/combination_sum/step4.go b/pullrequests/combination_sum/step4.go new file mode 100644 index 0000000..43e04ef --- /dev/null +++ b/pullrequests/combination_sum/step4.go @@ -0,0 +1,56 @@ +//lint:file-ignore U1000 Ignore all unused code +package template + +/* +Step1では再帰を使ってバックトラッキングを解いたので、スタックを使った方法も実装しました。 +また、Step1の実装のリファクタもしました。 +*/ +func combinationSumBacktrackingStackStep4(candidates []int, target int) [][]int { + combinations := [][]int{} + type state struct { + combination []int + sum int + index int + } + stack := []state{{[]int{}, 0, 0}} + for len(stack) > 0 { + current := stack[len(stack)-1] + stack = stack[:len(stack)-1] + if current.sum == target { + combinations = append(combinations, current.combination) + continue + } + for i := current.index; i < len(candidates); i++ { + newSum := current.sum + candidates[i] + if newSum > target { + continue + } + newCombination := append([]int{}, current.combination...) + newCombination = append(newCombination, candidates[i]) + stack = append(stack, state{newCombination, newSum, i}) + } + } + return combinations +} + +func combinationSumBacktrackingRecursionStep4(candidates []int, target int) [][]int { + var combinations [][]int + var stack []int + var generateCombinations func(int, int) + generateCombinations = func(currentIndex int, sum int) { + if sum == target { + combinations = append(combinations, append([]int{}, stack...)) + return + } + if sum > target { + return + } + for i := currentIndex; i < len(candidates); i++ { + stack = append(stack, candidates[i]) + generateCombinations(i, sum+candidates[i]) + stack = stack[:len(stack)-1] + } + } + generateCombinations(0, 0) + return combinations +}