diff --git a/next_permutation/phase1.py b/next_permutation/phase1.py new file mode 100644 index 0000000..38e3033 --- /dev/null +++ b/next_permutation/phase1.py @@ -0,0 +1,24 @@ +class Solution: + def nextPermutation(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + if len(nums) == 1: + return + + pivot_index = len(nums) - 2 # 比較の中心となるindexを定義 + while pivot_index > -1 and nums[pivot_index] >= nums[pivot_index+1]: + pivot_index -= 1 + + if pivot_index == -1: + nums.reverse() + return + + swap_index = len(nums) - 1 # swapに使うindexを定義 + while nums[swap_index] <= nums[pivot_index]: + swap_index -= 1 + + nums[swap_index], nums[pivot_index] = nums[pivot_index], nums[swap_index] + + nums[pivot_index+1:] = reversed(nums[pivot_index+1:]) + return diff --git a/next_permutation/phase2.py b/next_permutation/phase2.py new file mode 100644 index 0000000..5be6676 --- /dev/null +++ b/next_permutation/phase2.py @@ -0,0 +1,48 @@ +class Solution: + def nextPermutation(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + def _find_pivot_index(nums: List[int])->int: + # 比較の中心となるindexを定義 + # 末端から見ていって増加関係のないところを比較indexとする + pivot_index = len(nums) - 2 + while pivot_index > -1 and nums[pivot_index] >= nums[pivot_index+1]: + pivot_index -= 1 + return pivot_index + + def _find_swap_index(nums: List[int], pivot_index: int)->int: + # swapに使うindexを定義 + # swapする位置のindexを求める + swap_index = len(nums) - 1 + while nums[swap_index] <= nums[pivot_index]: + swap_index -= 1 + return swap_index + + if len(nums) == 1: + return + + pivot_index = _find_pivot_index(nums) + + if pivot_index == -1: + nums.reverse() + return + + swap_index = _find_swap_index(nums, pivot_index) + + nums[swap_index], nums[pivot_index] = nums[pivot_index], nums[swap_index] + + nums[pivot_index+1:] = reversed(nums[pivot_index+1:]) + return + +""" +None型を返すせいで, 正直PythonよりはC++とかの方が書きやすいと感じたが, とりあえずPythonで書く練習をした + +Reference: +https://github.com/shining-ai/leetcode/pull/58/files 解くことに夢中になりすぎて関数での分割を忘れていた。 +nums[pivot_index+1:] = reversed(nums[pivot_index+1:])よりもnums[left + 1 :] = sorted(nums[left + 1 :]) +の方が認知コストは低いなあと感じた。reversedで良いことは紙とペンで確かめられるけど, それをしなきゃいけない感じのコードなら確かに書くべきではないのかも + +https://github.com/hayashi-ay/leetcode/pull/67/files +markdownに書いてあるNext Permutationアルゴリズムの説明がわかりやすいと思いました。あとコメントにあった通り次から関数名は動詞から書き始めることを意識してみます。 +""" \ No newline at end of file diff --git a/next_permutation/phase3.py b/next_permutation/phase3.py new file mode 100644 index 0000000..d5722ad --- /dev/null +++ b/next_permutation/phase3.py @@ -0,0 +1,35 @@ +class Solution: + def nextPermutation(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + def _find_pivot_index(nums: List[int])->int: + # 比較の対象となる数のindexを見つける + pivot_index = len(nums) - 2 + while pivot_index > -1 and nums[pivot_index] >= nums[pivot_index+1]: + pivot_index -= 1 + return pivot_index + + def _find_swap_index(nums: List[int], pivot_index: int)->int: + # 後ろからnums[pivot_index]より大きい数を見つけてswapするindexを取り出す + swap_index = len(nums) - 1 + while nums[swap_index] <= nums[pivot_index]: + swap_index -= 1 + return swap_index + + if len(nums) == 1: + return + + pivot_index = _find_pivot_index(nums) + + if pivot_index == -1: + nums.reverse() + return + + swap_index = _find_swap_index(nums, pivot_index) + + nums[swap_index], nums[pivot_index] = nums[pivot_index], nums[swap_index] + + nums[pivot_index+1:] = sorted(nums[pivot_index+1:]) + + return nums \ No newline at end of file diff --git a/next_permutation/phase4.py b/next_permutation/phase4.py new file mode 100644 index 0000000..3232d5a --- /dev/null +++ b/next_permutation/phase4.py @@ -0,0 +1,35 @@ +class Solution: + def nextPermutation(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + def _find_first_not_sorted_index(nums: List[int])->int: + # 後ろから走査し, nums[index] >= nums[index+1]ではなくなる初めてのindexを取り出す + index = len(nums) - 2 + while index > -1 and nums[index] >= nums[index+1]: + index -= 1 + return index + + def _find_second_largest_index(nums: List[int], compare_index: int)->int: + # 後ろからnums[compare_index]より大きい数を見つけてswapするindexを取り出す + index = len(nums) - 1 + while nums[index] <= nums[compare_index]: + index -= 1 + return index + + if len(nums) == 1: + return + + left = _find_first_not_sorted_index(nums) + + if left == -1: + nums.reverse() + return + + right = _find_second_largest_index(nums, left) + + nums[right], nums[left] = nums[left], nums[right] + + nums[left+1:] = sorted(nums[left+1:]) + + return nums \ No newline at end of file diff --git a/next_permutation/phase5.py b/next_permutation/phase5.py new file mode 100644 index 0000000..38a1f21 --- /dev/null +++ b/next_permutation/phase5.py @@ -0,0 +1,27 @@ +class Solution: + def nextPermutation(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + def _find_first_not_sorted_index() -> int: + index = len(nums) - 2 + while index >= 0 and nums[index] >= nums[index+1]: + index -= 1 + return index + + def _rfind_bigger_than(compare_index: int) -> int: + index = len(nums) - 1 + while nums[index] <= nums[compare_index]: + index -= 1 + return index + + left = _find_first_not_sorted_index() + + if left == -1: + nums.reverse() + return + + right = _rfind_bigger_than(left) + nums[left], nums[right] = nums[right], nums[left] + nums[left+1:].reverse() + return \ No newline at end of file diff --git a/next_permutation/phase6.py b/next_permutation/phase6.py new file mode 100644 index 0000000..150f651 --- /dev/null +++ b/next_permutation/phase6.py @@ -0,0 +1,33 @@ +class Solution: + def nextPermutation(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + def _rfind_first_not_decreasing_index() -> int: + index = len(nums) - 2 + while index >= 0 and nums[index] >= nums[index+1]: + index -= 1 + return index + + def _rfind_bigger_than(compare_index: int) -> int: + index = len(nums) - 1 + while nums[index] <= nums[compare_index]: + index -= 1 + return index + + left = _rfind_first_not_decreasing_index() + + if left == -1: + nums.reverse() + return + + right = _rfind_bigger_than(left) + nums[left], nums[right] = nums[right], nums[left] + + swap_right = len(nums) - 1 + swap_left = left + 1 + while swap_left < swap_right: + nums[swap_right], nums[swap_left] = nums[swap_left], nums[swap_right] + swap_left += 1 + swap_right -= 1 + return \ No newline at end of file diff --git a/next_permutation/phase7.py b/next_permutation/phase7.py new file mode 100644 index 0000000..38b3b91 --- /dev/null +++ b/next_permutation/phase7.py @@ -0,0 +1,31 @@ +class Solution: + def nextPermutation(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + def _rfind_first_not_decreasing_index() -> int: + index = len(nums) - 2 + while index >= 0 and nums[index] >= nums[index+1]: + index -= 1 + return index + + def _rfind_bigger_than(compare_index: int) -> int: + index = len(nums) - 1 + while nums[index] <= nums[compare_index]: + index -= 1 + return index + + left = _rfind_first_not_decreasing_index() + if left == -1: + nums.reverse() + return + + right = _rfind_bigger_than(left) + nums[left], nums[right] = nums[right], nums[left] + swap_left = left + 1 + swap_right = len(nums) - 1 + # in-place reverse + while swap_left < swap_right: + nums[swap_left], nums[swap_right] = nums[swap_right], nums[swap_left] + swap_left += 1 + swap_right -= 1 \ No newline at end of file