From 510b832a4bef37a67cbd6749b945d135aca35f03 Mon Sep 17 00:00:00 2001 From: Ryotaro Kurita Date: Wed, 12 Mar 2025 22:22:11 +0900 Subject: [PATCH] finish --- 39.CombinationSum/loop.cpp | 33 ++++++++++++++++++++++++++++ 39.CombinationSum/memo.md | 44 +++++++++++++++++++++++++++++++++++++ 39.CombinationSum/step1.cpp | 30 +++++++++++++++++++++++++ 39.CombinationSum/step2.cpp | 27 +++++++++++++++++++++++ 39.CombinationSum/step3.cpp | 27 +++++++++++++++++++++++ 5 files changed, 161 insertions(+) create mode 100644 39.CombinationSum/loop.cpp create mode 100644 39.CombinationSum/memo.md create mode 100644 39.CombinationSum/step1.cpp create mode 100644 39.CombinationSum/step2.cpp create mode 100644 39.CombinationSum/step3.cpp diff --git a/39.CombinationSum/loop.cpp b/39.CombinationSum/loop.cpp new file mode 100644 index 0000000..cd9b9f8 --- /dev/null +++ b/39.CombinationSum/loop.cpp @@ -0,0 +1,33 @@ +class Solution { + public: + vector> combinationSum(vector& candidates, int target) { + vector> all_combinations; + stack combination_state; + + combination_state.push({{}, target, 0}); + + while (!combination_state.empty()) { + auto [partial_combination, remain, start] = combination_state.top(); + combination_state.pop(); + + if (remain == 0) { + all_combinations.push_back(partial_combination); + continue; + } + if (remain < 0) continue; + for (int i = start; i < candidates.size(); i++) { + vector added_combination = partial_combination; + added_combination.push_back(candidates[i]); + combination_state.push({added_combination, remain - candidates[i], i}); + } + } + return all_combinations; + } + + private: + struct CombinationAndTargetAndIndex { + vector combination; + int remain; + int index; + }; +}; diff --git a/39.CombinationSum/memo.md b/39.CombinationSum/memo.md new file mode 100644 index 0000000..73dbd3a --- /dev/null +++ b/39.CombinationSum/memo.md @@ -0,0 +1,44 @@ +## ステップ1 +再帰呼び出しごとに、数字を増やしていきその合計がtargetかどうかを確認する +数字の重複OKなので、再帰呼び出し時のindexで少し詰まった + +引数が多いきもするが前2問のような考え方で解けた + +## ステップ2 +・targetの数字から引いていって、残りが0か0を下回るのかで処理するように変更 + こうすればtargetとsumを引数に渡していたのをremainだけに減らすことが可能 + 参考 leetcodeの回答 +・変数名変更 + all_candidates => all_combinations + partial_candidate => partial_combination + 候補って確かに曖昧でした。 +・現時点でも合計がtarget以上なのかどうかを再帰呼び出しする前に移動 + remainに対して candidates[i] が大きすぎたら、それ以降の候補は試す必要がない + +・loop.cppを追加 +tuppleを使うよりstructを用いた +CombinationAndTargetAndIndexの中に部分組み合わせと残りの数字とインデックスを保持。 +構造名がすごく微妙 + + stackの変数名も微妙 + +## ステップ3 +**3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** + +## 他の解法 +>問題文や関数にあるものを命名に使うといい感じになる +ループで解いている。再帰の方法を形で覚えてしまっているので、再帰からループへの変換をしたら良さそう +https://github.com/nittoco/leetcode/pull/25 + +>変化のある方を比較演算子の左側に置く方がわかりやすい +リーダブルコードを読み直そう +https://github.com/Mike0121/LeetCode/pull/1/commits/b2f5e21e45fc088fb86bdc1f66cb3f6cd4611027 + +DPを使って解くことも可能 +>先にcandidatesをsortしておけば、total+candidates[i] > target となったときにi以降の要素を見る必要はないのでサボれる。 +なるほど再帰呼び出しの前に、targetと比較することで少し枝かりができるのですね。 +https://github.com/fhiyo/leetcode/pull/52 +https://github.com/Yoshiki-Iwasa/Arai60/pull/57 + +## Discorなど + diff --git a/39.CombinationSum/step1.cpp b/39.CombinationSum/step1.cpp new file mode 100644 index 0000000..2a00da5 --- /dev/null +++ b/39.CombinationSum/step1.cpp @@ -0,0 +1,30 @@ +class Solution { + public: + vector> combinationSum(vector& candidates, int target) { + vector> all_candidates; + vector partial_candidate; + GenerateCombinationToTarget(all_candidates, partial_candidate, candidates, target, 0, 0); + return all_candidates; + } + + private: + void GenerateCombinationToTarget(vector>& all_candidates, vector& partial_candidate, + const vector& candidates, int target, int start, int sum) { + if (sum == target) { + all_candidates.push_back(partial_candidate); + return; + } + if (sum > target) { + return; + } + for (int i = start; i < candidates.size(); i++) { + partial_candidate.push_back(candidates[i]); + int partial_sum = 0; + for (int num : partial_candidate) { + partial_sum += num; + } + GenerateCombinationToTarget(all_candidates, partial_candidate, candidates, target, i, partial_sum); + partial_candidate.pop_back(); + } + } + }; diff --git a/39.CombinationSum/step2.cpp b/39.CombinationSum/step2.cpp new file mode 100644 index 0000000..95c5d9a --- /dev/null +++ b/39.CombinationSum/step2.cpp @@ -0,0 +1,27 @@ +class Solution { + public: + vector> combinationSum(vector& candidates, int target) { + vector> all_combinations; + vector partial_combination; + sort(candidates.begin(), candidates.end()); + GenerateCombinationToTarget(all_combinations, partial_combination, candidates, target, 0); + return all_combinations; + } + + private: + void GenerateCombinationToTarget(vector>& all_combinations, vector& partial_combination, + const vector& candidates, int remain, int start) { + if (remain == 0) { + all_combinations.push_back(partial_combination); + return; + } + for (int i = start; i < candidates.size(); i++) { + if (candidates[i] > remain) { + break; + } + partial_combination.push_back(candidates[i]); + GenerateCombinationToTarget(all_combinations, partial_combination, candidates, remain - candidates[i], i); + partial_combination.pop_back(); + } + } + }; diff --git a/39.CombinationSum/step3.cpp b/39.CombinationSum/step3.cpp new file mode 100644 index 0000000..95c5d9a --- /dev/null +++ b/39.CombinationSum/step3.cpp @@ -0,0 +1,27 @@ +class Solution { + public: + vector> combinationSum(vector& candidates, int target) { + vector> all_combinations; + vector partial_combination; + sort(candidates.begin(), candidates.end()); + GenerateCombinationToTarget(all_combinations, partial_combination, candidates, target, 0); + return all_combinations; + } + + private: + void GenerateCombinationToTarget(vector>& all_combinations, vector& partial_combination, + const vector& candidates, int remain, int start) { + if (remain == 0) { + all_combinations.push_back(partial_combination); + return; + } + for (int i = start; i < candidates.size(); i++) { + if (candidates[i] > remain) { + break; + } + partial_combination.push_back(candidates[i]); + GenerateCombinationToTarget(all_combinations, partial_combination, candidates, remain - candidates[i], i); + partial_combination.pop_back(); + } + } + };