-
Notifications
You must be signed in to change notification settings - Fork 0
349 intersection of two arrays #2
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?
Conversation
int i = 0; | ||
int j = 0; |
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.
1文字命名は、やるならスコープが数行のときだけにした方が良いと思います。
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.
ありがとうございます。ここで宣言するなら、index1, index2とかですかね?
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.
そうですね。
私もindex1, index2で良いと思います。
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.
私は、個人的には i, j 許容派ですが、たしかにループちょっと長いですね。
nums1, nums2 の添字として使われていることが
while (i < nums1.size() && j < nums2.size()) {
この行で確定していて、このループの範囲内でしか使われていないので個人的にはあまり違和感がないのだと思います。
index1, index2 もいいんですが、長い変数名の1文字の差は見分けにくいんですよね。
i1, i2 でも私は許容です。
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.
要するに、わりと趣味の範囲です。
|
||
- 解法2 | ||
`set_intersection`というものがある</br>https://cpprefjp.github.io/reference/algorithm/set_intersection.html</br> | ||
他の方が使っていた`back_inserter`が全然知らない概念のものだったので理解が難しかった</br> |
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.
こちらは最終的に理解できましたか?
もしできていなければ、私でよければ説明します。
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.
説明お願いします!
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://en.cppreference.com/w/cpp/algorithm/set_intersection
今回は std::set_intersection
の OutputIt
(最後の引数) に std::back_inserter
を渡したかったのですね。
OutputIt
と std::back_inserter
に分けて説明します。
OutputIt
イテレータとは「コンテナ内での要素の位置を指すもの」です。(ポインタに近いです。)
そして、OutputIt
とは「操作の結果を格納する先のイテレータ」です。
(厳密には、出力イテレータという「参照への代入とインクリメントだけできるイテレータ」です。)
例えば以下のような処理が走ると、「 unique_nums1
と unique_nums2
で一致する要素見つけた!その要素を『格納先のイテレータ』に代入しよう」的なことが起こります。
std::set_intersection(
unique_nums1.begin(), unique_nums1.end(),
unique_nums2.begin(), unique_nums2.end(),
格納先のイテレータ
);
std::back_inserter
back_inserter()
は「引数のコンテナに push_back()
した場合に追加される要素のイテレータ」を返します。
(つまり、引数のコンテナの新たな末尾を指すイテレータを返します。)
このイテレータに値が代入されると、コンテナの push_back()
が呼び出され、イテレータは最新の末尾を指すように調整されます。
結論
まとめると、std::set_intersection
の OutputIt
に std::back_inserter
を渡すことで、 操作結果が引数のコンテナの末尾に順に追加されます。
以下の処理が走ると「 unique_nums1
と unique_nums2
で一致する要素見つけた!その要素を intersected_nums
の末尾に追加しよう」的なことが起こります。
std::set_intersection(
unique_nums1.begin(), unique_nums1.end(),
unique_nums2.begin(), unique_nums2.end(),
std::back_inserter(intersected_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.
ありがとうございます!
set_intersection
を呼んだ時のback_inserter
の動きがイメージできました。
@@ -0,0 +1,155 @@ | |||
# Step 1 | |||
|
|||
- nums1をunordered_setに登録して重複をなくしていく |
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.
set と unordered_set のどちらを使うかについては、以下のドキュメントを一読されることをお勧めいたします。
https://chromium.googlesource.com/chromium/src/+/HEAD/base/containers/README.md
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.
ありがとうございます。
元々は挿入、検索、削除の操作においてsetはO(logN)でunordered_setはO(1)だから後者を使おう、という程度で認識していました。
パフォーマンス面においてunordered_setの方が大幅に優れているということはなく、メモリのオーバーヘッドもあるため、基本的にはsetやmapを使った方がいい、と理解しました。
ただ提示いただいたドキュメントは難しく感じ、きちんと理解できたとは思えませんでした。
その一つの理由としては赤黒木やハッシュテーブルの実装方法への理解がちゃんとできていないからだと思ったので、勉強してみようと思います。
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.
こういうのを読むのは最終ゴールなので、このコースが終わったときに読めるようになっているようにしたい、そのためにはどうしたらいいのかくらいの感覚で、解いていけばいいと思います。
public: | ||
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { | ||
unordered_set<int> unique_nums1(nums1.begin(), nums1.end()); | ||
vector<int> intersected_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.
ここでのintersectは自動詞ではないですか?
https://dictionary.cambridge.org/dictionary/english/intersect
[ I ] mathematics specialized
If sets (= groups of things with particular characteristics) intersect, they have some of the same members:
# step 3 | ||
nums1のサイズをN, nums2のサイズをKとするとき | ||
- 時間計算量: O(N + K) | ||
- 空間計算量: O(N + K) |
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.
空間計算量は、より小さく抑えられますか?
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.
そもそもstep3のやり方だと空間計算量はO(N)かもしれないです(unique_nums1のサイズに比例するので)
もっと小さく抑えるならば、step2の解法3のやり方で、nums1とnums2をソートした上で一つずつ比較していくやり方であればO(1)になると思いました。(step2の解法3の計算量の見積もりがそもそも間違っていた(?))
``` | ||
|
||
# step 3 | ||
nums1のサイズをN, nums2のサイズをKとするとき |
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.
普通はMとNとかアルファベット上で連続する文字を使いませんか?
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.
確かに、片方がNならもう片方はMが自然だと他の方のコードを見て感じました
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { | ||
int exist_nums2[1001] = {}; | ||
vector<int> ans; | ||
unordered_set<int> nums1_set; |
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.
好みの問題かもですがsetの変数に_set
という接尾辞は不要かなと思います。
num1_set
だと、変数の用途が読み取れないので、用途に合わせた名前付けをするとわかりやすくなります。
public: | ||
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { | ||
int exist_nums2[1001] = {}; | ||
vector<int> ans; |
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.
この変数は最後のfor文まで未使用で、宣言と利用までの距離が長いです。
距離が長いということは、その変数の存在をしばらく覚えていないといけなくて、記憶リソースを圧迫します。
利用の直前で宣言すると記憶を圧迫せずにすんでコードを読む際の負荷が減ります。
README.md
Outdated
127. <span style="color:red">Word Ladder</span> |
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.
コードとは関係なく、PRの差分という観点ですが、不要なdiffが入り込んでしまっているようなので、この手の差分は消せるとよさそうです。
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.
READMEに関する差分は意図しないものだったのでgithub上で修正して消したいと思ったのですが、そもそもなんで差分として表示されているのかも分かりません。
こういう場合の対処法を教えていただきたいです。
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.
git checkoutで特定ファイルを特定時点まで戻すとか、git resetで丸ごとコミット履歴を巻き戻したりするといけそうですね。
|
||
## 解法3 | ||
nums1のサイズをN, nums2のサイズをKとするとき</br> | ||
- 時間計算量: O(min(N, K) + Nlog(N) + Klong(K)) |
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.
全部の流れを書き出したい意図でこう書いているのなら不要な指摘ですが、
N < N log(N), K < K log(K)なので、時間計算量はO(N log(N) + K log(K))でいいかと思います。
This reverts commit a3e8568.
https://leetcode.com/problems/intersection-of-two-arrays/description/