From 7786ffdd0063ad04bf8a0994287a3f88afd55ade Mon Sep 17 00:00:00 2001 From: Exzrgs Date: Mon, 20 May 2024 19:44:28 +0900 Subject: [PATCH 1/2] temp --- arai60/combination-sum/step1.py | 35 +++++++++++++++++++++++++++++++++ arai60/combination-sum/step2.py | 25 +++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 arai60/combination-sum/step1.py create mode 100644 arai60/combination-sum/step2.py diff --git a/arai60/combination-sum/step1.py b/arai60/combination-sum/step1.py new file mode 100644 index 0000000..1037783 --- /dev/null +++ b/arai60/combination-sum/step1.py @@ -0,0 +1,35 @@ +""" +めちゃくちゃざっくり考えると、全体で候補は40! +が、実際はそうはならない。でもかなり大きくなる気がする +でも結局全通りは計算しないと解けないので、メタ読みだけど全探索はできるだろう。やるとしても枝狩り程度 +再帰とかでやることを考える。重複を含まないために、自分より大きいやつしか考えなくてよい + +20m + +メタ読みしてしまったのがよくないが、計算量の解析が難しい... +ざっくりした数で抑えて大丈夫なことを確認したい +何か良い方法あれば教えてください>< +""" + +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + combination_candidate = [] + combination_value_sum = 0 + target_combinations = [] + def count_target_combinations(index): + nonlocal combination_value_sum + for i in range(index, len(candidates)): + if combination_value_sum + candidates[i] > target: + continue + if combination_value_sum + candidates[i] == target: + target_combinations.append(list(combination_candidate) + [candidates[i]]) + continue + combination_candidate.append(candidates[i]) + combination_value_sum += candidates[i] + count_target_combinations(i) + combination_candidate.pop() + combination_value_sum -= candidates[i] + count_target_combinations(0) + return target_combinations + +# stackでも書いてみる diff --git a/arai60/combination-sum/step2.py b/arai60/combination-sum/step2.py new file mode 100644 index 0000000..b1aeb7d --- /dev/null +++ b/arai60/combination-sum/step2.py @@ -0,0 +1,25 @@ +""" +combination_value_sumは、引数にしたほうが良い +countじゃなくてgenerateのほうが適切 +再帰する前に判定するよりも、再帰してからtargetに等しいかなどを判定したほうが、配列に追加済みなので簡単 + +combination_value_sum、ちょっと名前が冗長な気がしつつ、短縮するアイデアがない +再帰の深さにも注意。sys.setrecursionlimitとか +""" + +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + combination = [] + target_combinations = [] + def generate_target_combinations(index, combination_value_sum): + if combination_value_sum == target: + target_combinations.append(list(combination)) + return + if combination_value_sum > target: + return + for i in range(index, len(candidates)): + combination.append(candidates[i]) + generate_target_combinations(i, combination_value_sum + candidates[i]) + combination.pop() + generate_target_combinations(0, 0) + return target_combinations From 231c9e67982a3def08a2de42ff842c244fb261e8 Mon Sep 17 00:00:00 2001 From: Exzrgs Date: Mon, 20 May 2024 22:37:30 +0900 Subject: [PATCH 2/2] complete --- arai60/combination-sum/step1.py | 16 ++++++++++++++++ arai60/combination-sum/step2.py | 8 ++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/arai60/combination-sum/step1.py b/arai60/combination-sum/step1.py index 1037783..7f19f12 100644 --- a/arai60/combination-sum/step1.py +++ b/arai60/combination-sum/step1.py @@ -33,3 +33,19 @@ def count_target_combinations(index): return target_combinations # stackでも書いてみる +# 実際再帰の深さによってどのようなデメリットがあるのかとかをちゃんと把握できていない気がする +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + target_combinations = [] + combination_stack = [([], 0, 0)] + while combination_stack: + combination, value_sum, current_index = combination_stack.pop() + if value_sum == target: + target_combinations.append(combination) + continue + if value_sum > target: + continue + + for i in range(current_index, len(candidates)): + combination_stack.append((combination + [candidates[i]], value_sum + candidates[i], i)) + return target_combinations diff --git a/arai60/combination-sum/step2.py b/arai60/combination-sum/step2.py index b1aeb7d..cad15d1 100644 --- a/arai60/combination-sum/step2.py +++ b/arai60/combination-sum/step2.py @@ -1,6 +1,6 @@ """ combination_value_sumは、引数にしたほうが良い -countじゃなくてgenerateのほうが適切 +countじゃなくてgenerateのほうが適切→makeのほうが適切かも? 再帰する前に判定するよりも、再帰してからtargetに等しいかなどを判定したほうが、配列に追加済みなので簡単 combination_value_sum、ちょっと名前が冗長な気がしつつ、短縮するアイデアがない @@ -11,7 +11,7 @@ class Solution: def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: combination = [] target_combinations = [] - def generate_target_combinations(index, combination_value_sum): + def make_target_combinations(index, combination_value_sum): if combination_value_sum == target: target_combinations.append(list(combination)) return @@ -19,7 +19,7 @@ def generate_target_combinations(index, combination_value_sum): return for i in range(index, len(candidates)): combination.append(candidates[i]) - generate_target_combinations(i, combination_value_sum + candidates[i]) + make_target_combinations(i, combination_value_sum + candidates[i]) combination.pop() - generate_target_combinations(0, 0) + make_target_combinations(0, 0) return target_combinations