From 1b84457fe595b305e29b63fb7f82ec66e5924388 Mon Sep 17 00:00:00 2001 From: mt2324 <63892273+mt2324@users.noreply.github.com> Date: Tue, 23 Jun 2026 15:50:48 +0900 Subject: [PATCH] Create 46. Permutaions.md Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order. Example 1: Input: nums = [1,2,3] Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] Example 2: Input: nums = [0,1] Output: [[0,1],[1,0]] Example 3: Input: nums = [1] Output: [[1]] Constraints: 1 <= nums.length <= 6 -10 <= nums[i] <= 10 All the integers of nums are unique. --- 46. Permutaions/46. Permutaions.md | 140 +++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 46. Permutaions/46. Permutaions.md diff --git a/46. Permutaions/46. Permutaions.md b/46. Permutaions/46. Permutaions.md new file mode 100644 index 0000000..9822f65 --- /dev/null +++ b/46. Permutaions/46. Permutaions.md @@ -0,0 +1,140 @@ +## STEP 0 +Back Trackingがよくわかってなかったので解説とか見ながら書いた。 +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + res = [] + def backtrack(used, current_list): + if len(current_list) == len(nums): + res.append(list(current_list)) + return + for num in nums: + if num not in used: + current_list.append(num) + used.add(num) + backtrack(used, current_list) + current_list.pop() + used.remove(num) + + backtrack(set(),[]) + return res +``` + +## STEP 1 +忘れた頃に解き直したら要素の検索の速さに気を配るのを忘れている。 +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + res = [] + length = len(nums) + def generate_permutation(permutation): + if len(permutation) == length: + res.append(list(permutation)) + for num in nums: + if num in permutation: + continue + permutation.append(num) + generate_permutation(permutation) + permutation.pop() + generate_permutation([]) + return res +``` + + +## STEP 2 +変数の名前をちょっと見直した。 +他の人のコードを見ると存在確認したいものが静的な場合特にused = [False] * len(nums)使うと良さそう。動的に増える場合でもsetだと拡張する時にリハッシュするのに時間かかるから変化の程度によっては動的でもused = [False] * len(nums)としてもあんまり変わんないかもしれない。要素がuniqueでなければsetは使えないし。 + +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + all_permutations = [] + length = len(nums) + def generate_permutation(permutation, used_indices): + if len(permutation) == length: + all_permutations.append(list(permutation)) + return + for i, num in enumerate(nums): + if used_indices[i]: + continue + permutation.append(num) + used_indices[i] = True + generate_permutation(permutation, used_indices) + permutation.pop() + used_indices[i] = False + generate_permutation([], [False] * length) + return all_permutations +``` + +手動でスタックを使うバージョンも書いてみた。 +再帰で書いても結局中身ではコールスタックに積んでるからアルゴリズム的は一緒なんだけど、スタック領域を圧迫せずヒープで済ませられるからメモリの制限が大きそうな時はこっちの方がいいな。 + +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + all_permutations = [] + length = len(nums) + state_stack = [([], [False] * length)] + while state_stack: + permutation_so_far, used_indices = state_stack.pop() + if len(permutation_so_far) == length: + all_permutations.append(permutation_so_far) + continue + for index, num in enumerate(nums): + if used_indices[index]: + continue + new_used_indices = used_indices.copy() + new_used_indices[index] = True + new_permutation = [*permutation_so_far, num] + state_stack.append((new_permutation, new_used_indices)) + return all_permutations +``` + + +## STEP3 +再帰と手動スタックバージョンをそれぞれ3回ずつ書いた。`new_permutation = permutation_so_far + [num]` にするか `new_permutation = [*permutation, num]` で選択肢があるが後者がモダンらしいし書いたことなかったのでそれで練習してみた。 + +再帰 +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + all_permutations = [] + length = len(nums) + def generate_permutation(permutation_so_far: List[int], used_indices: List[bool]) -> None: + if len(permutation_so_far) == length: + all_permutations.append(list(permutation_so_far)) + return + for index, num in enumerate(nums): + if used_indices[index]: + continue + permutation_so_far.append(num) + used_indices[index] = True + generate_permutation(permutation_so_far, used_indices) + permutation_so_far.pop() + used_indices[index] = False + generate_permutation([], [False] * length) + return all_permutations +``` + +手動stack +上のコードを練習している途中で `used_indices = [False] * len(nums)` はもはやbitmaskでいいのではと思ったので変えてみた。配列の方が可読性は高いし、要素数が少ない時しか使えない手だけど。 +```python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + all_permutations = [] + size = len(nums) + GOAL_MASK = (1 << size) - 1 + used_mask = 0 + status_stack = [([], 0)] + while status_stack: + permutation_so_far, used_mask = status_stack.pop() + if used_mask == GOAL_MASK: + all_permutations.append(permutation_so_far) + continue + for index, num in enumerate(nums): + if used_mask & (1 << index): + continue + new_permutation = [*permutation_so_far, num] + status_stack.append((new_permutation, used_mask | (1 << index))) + return all_permutations +```