diff --git a/Python3/78. Subsets.md b/Python3/78. Subsets.md new file mode 100644 index 0000000..77ccf40 --- /dev/null +++ b/Python3/78. Subsets.md @@ -0,0 +1,98 @@ +## Step 1. Initial Solution + +- 各長さごとに考える + - 長さ0から始めて、1文字追加して新しいサブセットを作る + - 重複しないように辞書に入れておく? + - 各サブセットをソートした状態にしておけば最後の数値で追加するべきか分かる + +```python +class Solution: + def subsets(self, nums: List[int]) -> List[List[int]]: + same_size_subsets = [[]] + subsets = [] + while same_size_subsets: + next_size_subsets = [] + for subset in same_size_subsets: + for num in nums: + if subset and subset[-1] >= num: + continue + next_size_subsets.append(subset + [num]) + subsets += same_size_subsets + same_size_subsets = next_size_subsets + return subsets +``` + +### Complexity Analysis + +- 時間計算量:O(N*2^N) + - サブセット数2^NそれぞれについてN回ループを回す +- 空間計算量:O(2^N) + +## Step 2. Alternatives + +- 最後のwhile文1回分は不要にしても良い + + ```python + subsets += same_size_subsets + if same_size_subsets[0] == len(nums): + break + same_size_subsets = next_size_subsets + ``` + +- 各数値をビットでON/OFFにするような方法 + - https://github.com/ryosuketc/leetcode_arai60/pull/40/files#diff-ae8f15f065c3c04147f5ac8ba1f58f5d00f6f93b7a3fd00e52aaac94d6a40e5cR1 + - 確かに一回イメージが出来れば分かりやすい + - ビット演算を気軽にやれるようになりたい +- 小さいサブセットと次に足しこむインデックスをスタックする方法 + - あまり直感的ではないかも + - https://github.com/ryosuketc/leetcode_arai60/pull/40/files#diff-a97f140bc1bbfbc44410359c2201142f4a5104bd0c3de0853d518f3f922ffa24R1-R12 +- for文だけでも書けるという話 + - https://github.com/olsen-blue/Arai60/pull/52/files#r2019033451 + - 確かによく考えるとこれでも行けるのか + - bitを動かしていくイメージに近いかも + - 0から始めて1を追加して10, 11を追加して100, 101, 110, 111を追加してみたいな + + ```python + **class Solution: + def subsets(self, nums: List[int]) -> List[List[int]]: + subsets = [[]] + for num in nums: + new_subsets = [subset + [num] for subset in subsets] + subsets += new_subsets + return subsets** + ``` + +- 再帰で書くと前の問題に近い構造に見える + - https://github.com/olsen-blue/Arai60/pull/52/files#diff-ddd8c09ee41837c8d5bde978403f850a0b08217fb8ec8eac6d0f2ae10e369d04R137 + +## Step 3. Final Solution + +- 再帰での実装を練習 +- List_A += List_Bを関数内関数で行うとエラー + - extendやappendなどの処理はエラーにならない + - 少し調べたが上手く理解できなかったので後で実装の違いを確認する + +```python +class Solution: + def subsets(self, nums: List[int]) -> List[List[int]]: + def add_subsets(index_to_add: int) -> None: + all_subsets.extend([subset + [nums[index_to_add]] + for subset in all_subsets]) + if index_to_add + 1 < len(nums): + add_subsets(index_to_add + 1) + all_subsets = [[]] + add_subsets(0) + return all_subsets +``` + +- 1回整理できてしまうとこれが一番シンプルに見える + - もしかすると5行目は少し情報過多か + +```python +class Solution: + def subsets(self, nums: List[int]) -> List[List[int]]: + all_subsets = [[]] + for num in nums: + all_subsets.extend([subset + [num] for subset in all_subsets]) + return all_subsets +```