From e825f1faeb459a61c258641f49b3b40c64ff05dd Mon Sep 17 00:00:00 2001 From: potrue <126231160+potrue@users.noreply.github.com> Date: Wed, 20 Aug 2025 18:13:24 +0900 Subject: [PATCH] 39. Combination Sum https://leetcode.com/problems/combination-sum/description/ --- 39/39.md | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 39/39.md diff --git a/39/39.md b/39/39.md new file mode 100644 index 0000000..72221c2 --- /dev/null +++ b/39/39.md @@ -0,0 +1,112 @@ +## 何も見ずに解いてみる + +```cpp +class Solution { +public: + vector> combinationSum(vector& candidates, int target) { + vector> result; + vector initial_combination; + combinationSumHelper(candidates, initial_combination, target, result); + return result; + } +private: + void combinationSumHelper(vector& candidates, vector combination, int target, vector>& result) { + if (target == 0) { + result.emplace_back(combination); + return; + } + if (candidates.empty()) { + return; + } + int num = candidates.back(); + candidates.pop_back(); + while (target >= 0) { + combinationSumHelper(candidates, combination, target, result); + combination.emplace_back(num); + target -= num; + } + candidates.emplace_back(num); + } +}; +``` + +## 他の人のコードを見てみる + +https://github.com/tokuhirat/LeetCode/pull/52/files +https://github.com/ryosuketc/leetcode_arai60/pull/41/files +https://github.com/Ryotaro25/leetcode_first60/pull/56/files + +最初に書いたコードはcombinationが値渡しであったことで結構時間がかかっていたようです。 +以下のようにするだけでleetcode上の実行時間が20msぐらいから1msぐらいになりました。 + +```cpp +class Solution { +public: + vector> combinationSum(vector& candidates, int target) { + vector> result; + vector combination; + combinationSumHelper(candidates, combination, target, result); + return result; + } +private: + void combinationSumHelper(vector& candidates, vector& combination, int target, vector>& result) { + if (target == 0) { + result.emplace_back(combination); + return; + } + if (candidates.empty()) { + return; + } + int num = candidates.back(); + candidates.pop_back(); + while (target >= 0) { + combinationSumHelper(candidates, combination, target, result); + combination.emplace_back(num); + target -= num; + } + candidates.emplace_back(num); + while (!combination.empty() && combination.back() == num) { + combination.pop_back(); + } + } +}; +``` + +大きい数字から見ていったほうが若干高速ではありそうですが、出力の形がきれいじゃなくなってしまいますね。 + +## 最終コード + +```cpp +class Solution { +public: + vector> combinationSum(vector& candidates, int target) { + vector> result; + vector initial_combination; + combinationSumHelper(candidates, initial_combination, 0, target, result); + return result; + } +private: + void combinationSumHelper( + const vector& candidates, + vector& combination, + int processed_until, + int target, + vector>& result + ) { + if (target < 0) { + return; + } + if (target == 0) { + result.emplace_back(combination); + return; + } + for (int i = processed_until; i < candidates.size(); ++i) { + combination.emplace_back(candidates[i]); + combinationSumHelper(candidates, combination, i, target - candidates[i], result); + combination.pop_back(); + } + } +}; +``` + +最後のiという変数名にはもう少し意味を持たせたいと思ったのですが、あまり簡潔な変数名が思いつかず・・・