HASHING › IMPLEMENTARY PROBLEMS
Open — the attempt gate is not wired up yet
This editorial is meant to unlock after you have run the problem at least once, with the worked solution behind one further deliberate click. That needs per-learner unlock state nothing stores today, so for now the whole article is open.
Try it yourself first →The first answer asks you to inspect every index of nums1 and ask one question: does this value appear at least once in nums2? The second answer asks the same question in the opposite direction. The value can appear many times in the array being counted, and every such index contributes separately.
A set stores whether a value appears, without storing how many times it appears. That is exactly the information each membership question needs. Build one set for each array, then scan nums1 against nums2's set and nums2 against nums1's set. The sets answer presence; the scans preserve duplicate occurrences.
| MEASURE | BOUND | WHY |
|---|---|---|
| Time | Expected O(n + m), worst-case O(nm) | Building the two sets processes n + m inserted values, and the two scans perform n + m membership checks. With expected constant-time hashing, no array is rescanned for an individual element. If every lookup is forced into long collision chains, a lookup can cost linear time, making the worst case O(nm). |
| Space | Expected O(n + m) extra, worst-case O(n + m) | The two sets keep at most n and m distinct values combined; the returned two-element vector is required output and is excluded. The extra space is largest when the arrays contain as many distinct values as possible, although the value range here caps each set at 100 entries. |
#include <unordered_set>
#include <vector>
using namespace std;
class Solution {
public:
vector<int> findIntersectionValues(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> set1(nums1.begin(), nums1.end());
unordered_set<int> set2(nums2.begin(), nums2.end());
int answer1 = 0;
int answer2 = 0;
for (int x : nums1) {
if (set2.count(x)) {
answer1++;
}
}
for (int x : nums2) {
if (set1.count(x)) {
answer2++;
}
}
return {answer1, answer2};
}
};The important distinction is between constructing a set and performing the count. The set removes duplicate information because it only answers whether a value exists. The range-based loops deliberately read the original arrays, not the sets, so a value repeated three times contributes three times when it is present in the other array.
Because every value is between 1 and 100, you can replace each hash set with a boolean presence table indexed by the value. This is a different arrangement, not a better asymptotic time bound: it keeps the same O(n + m) scans, uses O(1) extra space under this fixed constraint, and avoids hash overhead. If the allowed value range grows to U, the tables require O(U) space and should be sized or replaced accordingly.
#include <vector>
using namespace std;
class Solution {
public:
vector<int> findIntersectionValues(vector<int>& nums1, vector<int>& nums2) {
vector<bool> presentInFirst(101, false);
vector<bool> presentInSecond(101, false);
for (int x : nums1) {
presentInFirst[x] = true;
}
for (int x : nums2) {
presentInSecond[x] = true;
}
int answer1 = 0;
int answer2 = 0;
for (int x : nums1) {
if (presentInSecond[x]) {
answer1++;
}
}
for (int x : nums2) {
if (presentInFirst[x]) {
answer2++;
}
}
return {answer1, answer2};
}
};