diff --git a/78. Subsets/cascading.cpp b/78. Subsets/cascading.cpp new file mode 100644 index 0000000..b72c343 --- /dev/null +++ b/78. Subsets/cascading.cpp @@ -0,0 +1,22 @@ +class Solution { + public: + vector> subsets(vector& nums) { + vector> all_subsets; + all_subsets.push_back({}); + + for (int num : nums) { + vector> partial_subset; + for (auto prev_subset : all_subsets) { + // 一つ前の状態を取り出して、部分集合(現在のnum)を追加する + vector cloned = prev_subset; + cloned.push_back(num); + partial_subset.push_back(cloned); + } + // この周回で作った集合を次の周回に渡すための処理 + for (auto subset : partial_subset) { + all_subsets.push_back(subset); + } + } + return all_subsets; + } + }; diff --git a/78. Subsets/cascading_step2.cpp b/78. Subsets/cascading_step2.cpp new file mode 100644 index 0000000..89465fb --- /dev/null +++ b/78. Subsets/cascading_step2.cpp @@ -0,0 +1,20 @@ +class Solution { + public: + vector> subsets(vector& nums) { + vector> all_subsets; + all_subsets.push_back({}); + + for (int num : nums) { + vector> partial_subset; + for (const auto& prev_subset : all_subsets) { + vector cloned = prev_subset; + cloned.push_back(num); + partial_subset.emplace_back(cloned); + } + for (const auto& subset : partial_subset) { + all_subsets.emplace_back(subset); + } + } + return all_subsets; + } + }; diff --git a/78. Subsets/memo.md b/78. Subsets/memo.md new file mode 100644 index 0000000..41e1d45 --- /dev/null +++ b/78. Subsets/memo.md @@ -0,0 +1,46 @@ +## ステップ1 +Permutationの回答から変形したらいけそうだと思った。 +Permutationではforループで要素を順番に選びながら、再帰呼び代しで全順列を作った + +ここから派生させてsubsetを作る関数にsubsetのサイズを指定することでサイズごとの全subsetを回答に追加する +Permutaionとは異なり、順番違いの同じ要素を除外する必要がある。 +なんとか回答できたがGenerateSubsetに対する引数が多い=追うべきものが多すぎる + +## ステップ2 +変更点 step2.cpp +・含まれているのか含まれていないかのチェックを削除 + この確認をしなくてもインデックスで管理しているので、重複は発生しない + +・subset_sizeと部分subsetの大きさが同じだけというチェックを削除 + 再帰呼び出し回数に合わせたおきさになる為不要 + +Leetcodeの解説より +一つ前の状態に新しい部分集合を足していく方法 +cascating.cppに実装 +初期 => {} 追加 +nums = 1 => {1} 追加 +nums = 2 => {2} {1, 2} 追加 +nums = 3 => {3} {1, 3} {2, 3} {1, 2, 3} +こちらの方が自分的には理解しやすかった + +## ステップ3 +**3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** + +## 他の解法 +step1の直したコードに対して、includeの役割を追うのに時間がかかった +呼び出してから一連の処理を追って要約理解できたので、コメントがあってもいいかもです +https://github.com/nittoco/leetcode/pull/19/commits/964a4def0273bf53a4442f8b8908f6c4f99e022a + +バックトラッキングで解いている +>バックトラックは、要するに、その場所までが固定されたときに、残りをどうやって重複や漏れがないように、分類するかということです。 +https://github.com/goto-untrapped/Arai60/pull/39/commits/c8e8ee07bb84ff15a310415a6c5a551d626bd18e + +indexを使って、サイズを管理している +自分もstep1の時に行なっていたが、サイズの管理は再帰関数の呼び出し回数に吸収させたい +yieldを何か調べた。一時停止させてまた再開をすると処理を追うのが大変そう。。。 +あとC++にはなさそう +https://github.com/fhiyo/leetcode/pull/51/commits/201509ce3b67a697e84ea970c7e9e65b4b2aa00d + +https://github.com/Yoshiki-Iwasa/Arai60/pull/56/commits/79711318d8fe43048883ce60f3a35e9dffbcd0ac +## Discorなど + diff --git a/78. Subsets/step1.cpp b/78. Subsets/step1.cpp new file mode 100644 index 0000000..71e39cf --- /dev/null +++ b/78. Subsets/step1.cpp @@ -0,0 +1,31 @@ +class Solution { + public: + vector> subsets(vector& nums) { + vector> all_subsets; + vector partial_subset; + all_subsets.push_back({}); + + for (int i = 1; i <= nums.size(); i++) { + GenerateSubset(all_subsets, partial_subset, nums, i, 0); + } + return all_subsets; + } + + private: + void GenerateSubset(vector>& all_subsets, vector& partial_subset, + const vector& nums, int subset_size, int start_index) { + if (partial_subset.size() == subset_size) { + all_subsets.push_back(partial_subset); + return; + } + + for (int i = start_index; i < nums.size(); i++) { + if (find(partial_subset.begin(), partial_subset.end(), nums[i]) != partial_subset.end()) { + continue; + } + partial_subset.push_back(nums[i]); + GenerateSubset(all_subsets, partial_subset, nums,subset_size, i + 1); + partial_subset.pop_back(); + } + } + }; diff --git a/78. Subsets/step2.cpp b/78. Subsets/step2.cpp new file mode 100644 index 0000000..2e8daeb --- /dev/null +++ b/78. Subsets/step2.cpp @@ -0,0 +1,21 @@ +class Solution { + public: + vector> subsets(vector& nums) { + vector> all_subsets; + vector partial_subset = {}; + GenerateSubset(all_subsets, 0, partial_subset, nums); + return all_subsets; + } + + private: + void GenerateSubset(vector>& all_subsets, int start, + vector& partial_subset, const vector& nums) { + all_subsets.push_back(partial_subset); + + for (int i = start; i < nums.size(); i++) { + partial_subset.push_back(nums[i]); + GenerateSubset(all_subsets, i + 1, partial_subset, nums); + partial_subset.pop_back(); + } + } + }; diff --git a/78. Subsets/step3.cpp b/78. Subsets/step3.cpp new file mode 100644 index 0000000..f1b5c43 --- /dev/null +++ b/78. Subsets/step3.cpp @@ -0,0 +1,21 @@ +class Solution { + public: + vector> subsets(vector& nums) { + vector> all_subsets; + vector partial_subset = {}; + GenerateSubset(all_subsets, partial_subset, 0, nums); + return all_subsets; + } + + private: + void GenerateSubset(vector>& all_subsets, vector& partial_subset, + int start, const vector& nums) { + all_subsets.push_back(partial_subset); + + for (int i = start; i < nums.size(); i++) { + partial_subset.push_back(nums[i]); + GenerateSubset(all_subsets, partial_subset, i + 1, nums); + partial_subset.pop_back(); + } + } + }; diff --git a/78. Subsets/step4.cpp b/78. Subsets/step4.cpp new file mode 100644 index 0000000..37de754 --- /dev/null +++ b/78. Subsets/step4.cpp @@ -0,0 +1,22 @@ +class Solution { + public: + vector> subsets(vector& nums) { + vector> all_subsets; + vector subset_including_num = {}; + GenerateSubset(nums, 0, subset_including_num, all_subsets); + return all_subsets; + } + + private: + void GenerateSubset(const vector& nums, int start, vector& subset_including_num, + vector>& all_subsets + ) { + all_subsets.emplace_back(subset_including_num); + + for (int i = start; i < nums.size(); i++) { + subset_including_num.push_back(nums[i]); + GenerateSubset(nums, i + 1, subset_including_num, all_subsets); + subset_including_num.pop_back(); + } + } + };