-
Notifications
You must be signed in to change notification settings - Fork 0
46. Permutations #50
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?
46. Permutations #50
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,94 @@ | ||
| ## 何も見ずに解いてみる | ||
|
|
||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> permute(vector<int>& nums) { | ||
| vector<vector<int>> result; | ||
| if (nums.size() == 0) { | ||
| result.push_back({}); | ||
| } | ||
| for (int i = 0; i < nums.size(); ++i) { | ||
| vector<int> nums_copy = nums; | ||
| nums_copy.erase(nums_copy.begin() + i); | ||
| for (auto& vec : permute(nums_copy)) { | ||
| vec.insert(vec.begin(), nums[i]); | ||
| result.push_back(vec); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| ## 他の人のコードを見てみる | ||
|
|
||
| https://github.com/tokuhirat/LeetCode/pull/50/files | ||
| https://github.com/ryosuketc/leetcode_arai60/pull/39/files | ||
| https://github.com/Ryotaro25/leetcode_first60/pull/54/files | ||
|
|
||
| swapを使って書いたコードは、下のコードを | ||
|
|
||
| - sub_permutationをnumsのdecided_untilより前として管理する | ||
| - unused_numsをnumsのdecided_until以降として管理する | ||
|
|
||
| ことでより早くしたカッコイイバージョンだと捉えられる気がしますね。 | ||
| Geminiによるとメモリ上で違う位置にあるsub_permutationとunused_numsをいちいち反復横跳びしなくてよくなっているという点でも高速化に貢献しているらしいです。(真偽のほどは検証していません・・・) | ||
|
|
||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> permute(vector<int>& nums) { | ||
| vector<vector<int>> result; | ||
| vector<int> initial_vector = {}; | ||
| unordered_set<int> nums_set(nums.begin(), nums.end()); | ||
| permuteHelper(result, initial_vector, nums_set); | ||
| return result; | ||
| } | ||
| private: | ||
| void permuteHelper(vector<vector<int>>& result, vector<int>& sub_permutation, unordered_set<int>& unused_nums) { | ||
| if (unused_nums.empty()) { | ||
| result.emplace_back(sub_permutation); | ||
| return; | ||
| } | ||
| // unused_numsでそのまま回すとfor文の最中にいじってるのが原因でエラー吐くのでコピーして回します | ||
| unordered_set<int> unused_nums_copy(unused_nums.begin(), unused_nums.end()); | ||
| for (int num : unused_nums_copy) { | ||
| unused_nums.erase(num); | ||
| sub_permutation.emplace_back(num); | ||
| permuteHelper(result, sub_permutation, unused_nums); | ||
| sub_permutation.pop_back(); | ||
| unused_nums.insert(num); | ||
| } | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| resultにpush_backとかemplace_backするとき順列をコピーしてから入れなくて大丈夫なのかと思ったんですが、オブジェクトそのものではなくてコンストラクタの引数として渡されてそれをもとに新しい要素が作られるという挙動なのでいらないみたいです。pythonのlist.appendとは違いますね。 | ||
|
|
||
| ## 最終コード | ||
|
|
||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> permute(vector<int>& nums) { | ||
| vector<vector<int>> result; | ||
| permuteHelper(result, nums, 0); | ||
| return result; | ||
| } | ||
| void permuteHelper(vector<vector<int>>& result, vector<int>& nums, int decided_until) { | ||
|
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. private でも問題ないでしょうか。 results は出力なので引数の最後にした方が良いかもしれません。
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. privateで良いと思います。入れるのを忘れてしまっていました。 |
||
| if (decided_until == nums.size()) { | ||
| result.emplace_back(nums); | ||
| return; | ||
| } | ||
| for (int i = decided_until; i < nums.size(); ++i) { | ||
| swap(nums[decided_until], nums[i]); | ||
| permuteHelper(result, nums, decided_until + 1); | ||
| swap(nums[decided_until], nums[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. decided_until は swap_index のように感じました。ここまで決めたんだという意味は落ちてしまいますが、、、 |
||
| } | ||
| } | ||
| }; | ||
|
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. たしかに、その視点はありませんでした。setを使った解法は動かないように思います。 |
||
| ``` | ||
|
|
||
| そういえばこれnums参照渡しで渡されてるので(最終的に戻ってくるときは元の状態で戻ってきますが)関数が走ってるとき中身の要素がめっちゃswapされることになると思うんですが、大丈夫なんでしょうか。 | ||
| numsが変化したときにそれを何らかの方法で検出して何か操作を行う、みたいな仕組みが組まれてると怪しいかもしれません。コピーしたほうが安心ですかね? | ||
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.
細かいですが、
private忘れでしょうか。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.
あ、失念していました。