Create 0031-next-permutation.md - #59
Conversation
| swap(i, i + 1) | ||
|
|
||
| index = len(nums) - 2 | ||
| previous_max = nums[index + 1] |
|
|
||
| index = len(nums) - 2 | ||
| previous_max = nums[index + 1] | ||
| while index >= 0 and nums[index] >= previous_max: |
There was a problem hiding this comment.
previous_max を定義して更新していくより、 nums[index + 1] と比較するほうがシンプルだと思いました。
There was a problem hiding this comment.
ありがとうございます。
その通りですね。
この実装は毎回昇順ソートを維持するように整えているので、
index = len(nums) - 2
while index >= 0 and nums[index] >= nums[-1]:
send_to_tail(index)
index -= 1こうなりますね。(まぁ非効率なんですが...)
|
|
||
| swap_target = bisect.bisect_right(nums, nums[pivot], lo=pivot + 1) | ||
| assert swap_target < n | ||
| swap(pivot, swap_target) |
There was a problem hiding this comment.
pivot と swap_target を swap してから逆順にする実装をよく見かけます。読み手が理解できるのであれば、どちらでも大丈夫だと思います。
There was a problem hiding this comment.
ありがとうございます。
そのまま書き換えるなら、下記のような感じでしょうか。
swap_target = (
bisect.bisect_left(
nums, -nums[pivot], lo=pivot + 1, key=lambda x: -x
)
- 1
)
assert swap_target < n
swap(pivot, swap_target)
reverse_in_section(pivot + 1, n - 1)ただこれは可読性が低く、ここは計算量的にボトルネックにならないので線形探索とし、
def find_bigger(target, start, stop, step=1):
for i in range(start, stop, step):
if nums[i] > target:
return i
return stop
swap_target = find_bigger(nums[pivot], n - 1, pivot, -1)
assert pivot < swap_target < n
swap(pivot, swap_target)
reverse_in_section(pivot + 1, n - 1)が良い気がしました。
| def swap(index1, index2): | ||
| nums[index1], nums[index2] = nums[index2], nums[index1] | ||
|
|
||
| def is_sorted_until(first, last, step=1): |
There was a problem hiding this comment.
関数内関数で、step=-1 以外で使われることがなさそうなので、逆順で見ることを前提とした関数とした方が読みやすいと思いました。
There was a problem hiding this comment.
ありがとうございます。
個人的には反対で、もしstep=-1を関数内にハードコードする場合関数名にstep=-1分の情報を追加する必要があると思います。それよりは、引数でfirst, last, stepを渡す方が可読性が高いと感じます。組み込み関数range()などで比較的馴染みのある引数セットであることが根拠の1つです。
| nums.reverse() | ||
| return | ||
|
|
||
| reverse_in_section(pivot + 1, n - 1) |
There was a problem hiding this comment.
reverse してから swap する場合はpivot=-1のケースをまとめて処理するのもありかなと思いました。
pivot = is_sorted_until(n - 1, 0, -1) - 1
reverse_in_section(pivot + 1, n - 1)
if pivot == -1:
return
この問題:https://leetcode.com/problems/next-permutation/
次の問題:https://leetcode.com/problems/string-to-integer-atoi/