Two Stamp Albums
Autumn Tournament (2020)
Submission name: albums.cpp
Problem summary
Two stamp albums contain distinct stamp numbers within each album. Find the numbers appearing in both albums and list them in increasing order.
Input
n and m; n numbers from the first album; m numbers from the second.
Output
The intersection size k, then its k numbers in increasing order on the next line.
Constraints
1 ≤ n,m ≤ 100000; stamp numbers are between 1 and 10^9.
Worked example
Original statement sample.
Input
5 6 2 10 5 13 4 6 2 13 3 10 1
Output
3 2 10 13
Solution analysis
- Sort both albums. Keep indices i and j pointing at the smallest not-yet-processed number in each sorted list.
- If the numbers match, save the common value and advance both pointers. Otherwise advance the pointer with the smaller number: that value cannot occur later in the other sorted list, whose current and future values are already larger.
- The sample sorts to [2,4,5,10,13] and [1,2,3,6,10,13]. The matching values encountered by the scan are 2,10,13. They are already in increasing order, so no final sorting is necessary.
Why it works
Each pointer advance either records an equality or safely discards a value too small to match any remaining value. The scan therefore finds every common stamp exactly once.
Watch out. The input lists are not sorted initially. Print zero and an empty second line when there are no shared stamps. Uniqueness is guaranteed within each album.
Commented C++17 solution
An independently written complete program with standard headers.
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,m;
cin>>n>>m;
vector<int>first(n),second(m),common;
for(int&value:first){
cin>>value;
}
for(int&value:second){
cin>>value;
}
sort(first.begin(),first.end());
sort(second.begin(),second.end());
int i=0,j=0;
// Discard only the smaller value; sorted order makes it impossible to match later.
while(i<n&&j<m){
if(first[i]==second[j]){
common.push_back(first[i]);
i++;
j++;
}
else if(first[i]<second[j]){
i++;
}
else{
j++;
}
}
cout<<common.size()<<'\n';
for(int index=0;index<static_cast<int>(common.size());index++){
if(index>0){
cout<<' ';
}
cout<<common[index];
}
cout<<'\n';
}