diff --git a/4.hash-map/intersection-of-two-arrays/memo.md b/4.hash-map/intersection-of-two-arrays/memo.md new file mode 100644 index 0000000..dd15296 --- /dev/null +++ b/4.hash-map/intersection-of-two-arrays/memo.md @@ -0,0 +1,32 @@ +## step1 +- `map` でもいいが value を使わないので `std::set` か `std::unordered_set` を採用する。 + +- `std::set` と `std::unordered_set` のどちらを使う考える。 + - `std::unordered_set` はハッシュテーブルなので整数徐算が遅いCPUアーキテクチャ (ARMなど) では遅くなる可能性がある。数回比較する (`std::set` を使う) 方が早い可能性がある。 + - https://chromium.googlesource.com/chromium/src/+/master/base/containers/README.md#std_unordered_map-and-std_unordered_set + - `std::unordered_set`も C++11 からリハッシュできるようだが、最悪の場合で 計算量に`std::unordered_set::size` の二乗かかるので、(確率に依るが) あまり使いたくない。 + - https://cpprefjp.github.io/reference/unordered_set/unordered_set/rehash.html + - `std::set` の方が良いと考える。 + +## step2 +- 他のコードを見る + +- 以下の初期化方法が C++17 からあった。 +```cpp +std::unordered_set unique_nums1(nums1.begin(), nums1.end()); +``` + - これなら `seen_in_nums1` より `unique_nums1` の方が自然。 + +- C++03 から `std::set_intersection` がある。 + - `std::unordered_set` だと Wrong Answer になる。 + - ソートしていない場合は未定義動作とある。(つまり何が起きても構わない。) + - https://en.cppreference.com/w/cpp/algorithm/set_intersection#:~:text=range%2C%20preserving%20order.-,1),-If + +- C++03 からの `std::back_inserter` をOutputIterator で使う。 + - https://en.cppreference.com/w/cpp/iterator/back_inserter + - つまり `*(back_inserter(vec)) = value;` で `vec.push_back(value);` になる。 +- 今回と関係ないが、他の書き込みを想定したイテレータを初めて知る。 + - https://stackoverflow.com/questions/19907677/whats-the-difference-between-iterator-and-back-insert-iterator#:~:text=see%20the%20following-,(adaptor)%20iterators,-%3A + +## step3 +- 補完無しで2分弱ほどで実装する。 diff --git a/4.hash-map/intersection-of-two-arrays/step1.cpp b/4.hash-map/intersection-of-two-arrays/step1.cpp new file mode 100644 index 0000000..bb2bb64 --- /dev/null +++ b/4.hash-map/intersection-of-two-arrays/step1.cpp @@ -0,0 +1,23 @@ +#include + +class Solution { +public: + std::vector intersection(std::vector& nums1, std::vector& nums2) { + std::set seen_in_nums1; + std::set seen_in_nums2; + for (int num : nums1) { + seen_in_nums1.insert(num); + } + std::vector intersected_nums; + for (int num : nums2) { + if (seen_in_nums2.contains(num)) { + continue; + } + if (seen_in_nums1.contains(num)) { + intersected_nums.push_back(num); + seen_in_nums2.insert(num); + } + } + return intersected_nums; + } +}; diff --git a/4.hash-map/intersection-of-two-arrays/step2.cpp b/4.hash-map/intersection-of-two-arrays/step2.cpp new file mode 100644 index 0000000..1281434 --- /dev/null +++ b/4.hash-map/intersection-of-two-arrays/step2.cpp @@ -0,0 +1,12 @@ +#include + +class Solution { +public: + std::vector intersection(std::vector& nums1, std::vector& nums2) { + std::set unique_nums1(nums1.begin(), nums1.end()); + std::set unique_nums2(nums2.begin(), nums2.end()); + std::vector intersected_nums; + std::set_intersection(unique_nums1.begin(), unique_nums1.end(), unique_nums2.begin(), unique_nums2.end(), back_inserter(intersected_nums)); + return intersected_nums; + } +}; diff --git a/4.hash-map/intersection-of-two-arrays/step3.cpp b/4.hash-map/intersection-of-two-arrays/step3.cpp new file mode 100644 index 0000000..aba20e4 --- /dev/null +++ b/4.hash-map/intersection-of-two-arrays/step3.cpp @@ -0,0 +1,12 @@ +#include + +class Solution { +public: + std::vector intersection(std::vector& nums1, std::vector& nums2) { + std::set unique_nums1 = std::set(nums1.begin(), nums1.end()); + std::set unique_nums2 = std::set(nums2.begin(), nums2.end()); + std::vector intersected_nums; + std::set_intersection(unique_nums1.begin(), unique_nums1.end(), unique_nums2.begin(), unique_nums2.end(), std::back_inserter(intersected_nums)); + return intersected_nums; + } +};