From 39a4b1636e0c2c769917dfe0592505c44b5d1793 Mon Sep 17 00:00:00 2001 From: potrue <126231160+potrue@users.noreply.github.com> Date: Wed, 27 Aug 2025 18:17:39 +0900 Subject: [PATCH] 31. Next Permutation https://leetcode.com/problems/next-permutation/ --- 31/31.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 31/31.md diff --git a/31/31.md b/31/31.md new file mode 100644 index 0000000..bbd49cc --- /dev/null +++ b/31/31.md @@ -0,0 +1,79 @@ +## 何も見ずに解いてみる + +```cpp +class Solution { +public: + void nextPermutation(vector& nums) { + int i = nums.size() - 1; + while (i >= 1 && nums[i-1] >= nums[i]) { + --i; + } + sort(nums.begin() + i, nums.end()); + if (i == 0) return; + auto it = upper_bound(nums.begin() + i, nums.end(), nums[i-1]); + int value = *it; + nums.erase(it); + nums.insert(nums.begin() + i - 1, value); + sort(nums.begin() + i, nums.end()); + } +}; +``` + +上のコードを書いた後もうちょっといいやり方を思いついた。 + +```cpp +class Solution { +public: + void nextPermutation(vector& nums) { + int i = nums.size() - 1; + while (i >= 1 && nums[i] <= nums[i-1]) { + --i; + } + reverse(nums.begin() + i, nums.end()); + if (i == 0) return; + auto it = upper_bound(nums.begin() + i, nums.end(), nums[i-1]); + swap(nums[i-1], *it); + } +}; +``` + +というか、もしかしたら最初に書いたコードは問題文の +The replacement must be in place and use only constant extra memory. +という条件を満たさないかもしれない(sortにO(log(nums.length))のメモリを使うかも?) +https://stackoverflow.com/questions/68146330/what-is-the-space-complexity-of-stdsort-in-the-c-standard-template-library + +## 他の人のコードを見てみる + +https://github.com/tokuhirat/LeetCode/pull/58/files +https://github.com/ryosuketc/leetcode_arai60/pull/58/files +https://github.com/Ryotaro25/leetcode_first60/pull/63/files +https://github.com/usatie/leetcode/pull/2/files + +https://cpprefjp.github.io/reference/algorithm/next_permutation.html +https://en.cppreference.com/w/cpp/algorithm/next_permutation.html +cppのアルゴリズム関連のメソッドのドキュメントには参考実装が乗っているみたい。ありがたいですね。 + +リバースイテレーターというのがあるのか。 +https://cpprefjp.github.io/reference/iterator/reverse_iterator.html +https://en.cppreference.com/w/cpp/iterator/reverse_iterator.html + +何か用事があってドキュメントを見に行った時に、その用事と関係ないにしてもリンクが繋がっているところのうち気になったところを少し見てみるぐらいは習慣化したほうがいいかもと思った。 +std::vectorのドキュメントを見たときにrendとかrbeginというメソッドが存在すること自体は見ていたので、そういった機会に軽くは見ておくぐらいの癖をつけた方が知識の広がりが速くなる気がする。 +コンフォートゾーンを抜けだすというか、自分の見識を少しでも広げようとする態度というか、そういう感じ? +(なかなかやる気が出ないと難しいし、半分ぐらいの確率でよくわからずに退散する羽目になりますがToT) + +## 最終コード + +```cpp +class Solution { +public: + void nextPermutation(vector& nums) { + auto it = is_sorted_until(nums.rbegin(), nums.rend()); + if (it != nums.rend()) { + auto it_next = upper_bound(nums.rbegin(), it, *it); + iter_swap(it, it_next); + } + reverse(nums.rbegin(), it); + } +}; +```