Hashing
Concept
Hashing maps keys to indices for O(1) average-case lookup, insertion, and deletion. In C++, unordered_map and unordered_set use hash tables internally. The most common competitive programming use is frequency counting — counting how many times each element appears in O(n).
When to Use
- ▸Frequency counting (how many times does each element appear?)
- ▸Checking if an element exists in a set in O(1)
- ▸Two-sum problem (complement lookup)
- ▸Counting distinct elements
- ▸Grouping elements by some property
Intuition
A hash table is like a dictionary with instant lookup. Give it a key, it tells you the value immediately (on average). For frequency counting, walk through the array once and increment a counter for each element. For two-sum, store each number's index in a map, then for each number check if (target - number) exists. Both patterns turn O(n^2) brute force into O(n).
Complexity
Time
O(1) average per operation, O(n) worst case
Space
O(n)
Template Code
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
ios_base::sync_with_stdio(0), cin.tie(0);
// --- Frequency Counting ---
int n;
cin >> n;
vector<int> v(n);
for(int i = 0; i < n; i++) cin >> v[i];
unordered_map<int, int> cnt;
for(int x : v){
cnt[x]++;
}
for(auto &[key, val] : cnt){
cout << key << ": " << val << "\n";
}
// --- Check Existence with unordered_set ---
unordered_set<int> s(v.begin(), v.end());
int q;
cin >> q;
while(q--){
int x;
cin >> x;
if(s.count(x)) cout << "YES\n";
else cout << "NO\n";
}
// --- Two Sum (find pair with given sum) ---
// int target;
// cin >> target;
// unordered_map<int, int> seen;
// for(int i = 0; i < n; i++){
// int comp = target - v[i];
// if(seen.count(comp)){
// cout << seen[comp] << " " << i << "\n";
// break;
// }
// seen[v[i]] = i;
// }
// --- map vs unordered_map ---
// map<int, int> — sorted keys, O(log n) per op
// unordered_map<int, int> — unsorted, O(1) avg per op
// set<int> — sorted unique, O(log n) per op
// unordered_set<int> — unsorted unique, O(1) avg per op
return 0;
}
// Sample Input:
// 7
// 3 1 2 3 1 3 2
// 3
// 3
// 5
// 1
//
// Sample Output (frequency):
// 2: 2
// 1: 2
// 3: 3
// YES
// NO
// YES