diff --git a/46. Permutations.md b/46. Permutations.md new file mode 100644 index 0000000..486d44f --- /dev/null +++ b/46. Permutations.md @@ -0,0 +1,136 @@ +# 進め方 + +Step1 : 問題を解く。 + +Step2 : 他の人のPRを参照し、コメントする。 + +Step3 : 3回続けてエラーが出ないように書く。ドキュメントを参照する。 + +# 実践 + +## Step1 + +### 思考ログ + +う、意外とかけないかも。 + +nums.lengthが6個なので全部書ききれる可能性はある。(笑) + +全部生成して、setで間引くか。 + +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + stack = [] + for num in nums: + stack.append([num]) + for i in range(1, len(nums)): + next_stack = [] + while stack: + used = set(stack[-1]) + for num in nums: + possible = stack[-1][:] # コピーでないと動かない + if num in used: + continue + possible.append(num) + next_stack.append(possible) + used.add(num) + stack.pop() + stack = next_stack + return stack +``` + +コピーをせずにそのままやったらオブジェクトを共有していた。 + +浅いコピーでいけるのか。30分くらいかかってしまった。 + +### GPT + +a = [1, 2] +b = a[:] # 浅いコピー(外側だけ別物) + +b.append(3) # b の外側を変更 +print(a) # [1, 2] ← a は影響なし +print(b) # [1, 2, 3] + +- **外側**=入れ物(リスト自体)、**内側**=その要素。 +- 順列生成では外側だけ複製すれば目的を達成でき、内側は整数で安全。 +- だから **浅いコピーで十分** というわけです。 + +## Step2 + +### 同じ問題を解いた人のプルリクを見る + +バックトラック・バックトラッキングとは + +[https://ja.wikipedia.org/wiki/バックトラッキング](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%83%E3%82%AF%E3%83%88%E3%83%A9%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0) + +組み合わせをすべて見つける方法ということでしょうか。 + +https://www.cc.kyoto-su.ac.jp/~yamada/ap/backtrack.html + +すべての組み合わせを見つけるためのアルゴリズムということですね。 + +https://github.com/hroc135/leetcode/pull/47 + +- 片付けして分類するイメージ + - 分類、あんまりよくわからないなあ。 + - この問題だと、持っているカードを出していくイメージでした。 + +https://github.com/olsen-blue/Arai60/pull/51/files + +- なるほど、苦戦する場所っぽいですね。安心? +- 再起とスタックで。これ書いているうちにつかめるタイプの問題な気がする。 +- Cpython読めなかった。 + - https://github.com/python/cpython/blob/a31bbc951a9d74cd7b9092555c101e51a2b9482b/Modules/itertoolsmodule.c#L2820 + +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + def generate_permutation(creating_nums, rest_nums): + if not rest_nums: + print(creating_nums) + return [creating_nums] + result = [] + for i, num in enumerate(rest_nums): + making = creating_nums[:] + making.append(num) + result.extend(generate_permutation(making, rest_nums[:i] + rest_nums[i+1:])) + return result + + return generate_permutation([], nums) +``` + +上手な変数名を付けれないときは、理解できていないのかもしれない。 + +## Step3 + +### 3回連続で再現 + +10m, 7m,7mくらい + +あと何問か同じようなものがあるらしいので次に進む。 + +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + def permute_helper(takeover_nums, rest_nums): + assert rest_nums is not None + if not rest_nums: + return [takeover_nums] + result = [] + for i, num in enumerate(rest_nums): + handover_nums = takeover_nums[:] + handover_nums.append(num) + next_rest_nums = rest_nums[:i] + rest_nums[i+1:] + permutation = permute_helper(handover_nums, next_rest_nums) + result.extend(permutation) + return result + + return permute_helper([], nums) + +``` + +引き継ぎのイメージをそのまま変数名にしてみた。 + +意外と悪くないか。