-
Notifications
You must be signed in to change notification settings - Fork 0
31. Next Permutation #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| ## 何も見ずに解いてみる | ||
|
|
||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| void nextPermutation(vector<int>& 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<int>& 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); | ||
| } | ||
| }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 添字とイテレータが混ざっているのが気になりました。混ぜて書いても良いものなのでしょうか?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. upper_boundがindexでなくイテレーターを返すのでこうなってしまいました。(見返してみるとiをイテレーターにすべきだと感じました) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. C++は書かないのですがスタイル的には揃っていた方が自然かな、という程度でコメントしました。 ちなみに、イテレーターの引き算するとインデックスが求められたと思います。わざわざこのように書く必要はなさそうですが、ご参考までです。 auto j = upper_bound(nums.begin() + i, nums.end(), nums[i-1]) - nums.begin();
swap(nums[i-1], nums[j]);
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. あ、確かにそうしてしまう手もありますね。こちらを使ってもいいかもしれません。 |
||
| ``` | ||
|
|
||
| というか、もしかしたら最初に書いたコードは問題文の | ||
| The replacement must be in place and use only constant extra memory. | ||
| という条件を満たさないかもしれない(sortにO(log(nums.length))のメモリを使うかも?) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 仕様では空間計算量は規定されていないようです。 |
||
| 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<int>& nums) { | ||
| auto it = is_sorted_until(nums.rbegin(), nums.rend()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. イテレータであることはこの場合重要ではなく、とあるindexを指していることがわかるような変数名だと良いなと思いました。left や pivot でしょうか。it_next も同様です。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 実は最初itとit_nextをpivotとnextにしていたんですが、結局このような名前にしたところで実際のプログラムを見ないとどんな要素を指すイテレーターになっているかわからないだろうなという気がしてきて、だったらいっそのこと(autoで受けてしまっているのもあるし)型の情報を入れた方が読みやすいかなと思いこうしてみました。難しいところですが、、、 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. この関数、Python で解いたとき以前別の方から C++ だとこういうのありますね、という指摘を受けたんですが便利ですね。 |
||
| if (it != nums.rend()) { | ||
| auto it_next = upper_bound(nums.rbegin(), it, *it); | ||
| iter_swap(it, it_next); | ||
| } | ||
| reverse(nums.rbegin(), it); | ||
| } | ||
| }; | ||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
二項演算子の両側にはスペースを空けることが多いと思います。
参考までにスタイルガイドへのリンクを貼ります。
https://google.github.io/styleguide/cppguide.html#Horizontal_Whitespace
上記のスタイルガイドは唯一絶対のルールではなく、複数あるスタイルガイドの一つに過ぎないということを念頭に置くことをお勧めします。また、所属するチームにより何が良いとされているかは変わります。自分の中で良い書き方の基準を持ちつつ、チームの平均的な書き方で書くことをお勧めいたします。