-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHashing.cpp
More file actions
304 lines (272 loc) · 10.1 KB
/
Copy pathHashing.cpp
File metadata and controls
304 lines (272 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
// Hashing is a technique to store and retrieve data in O(1) time. The need for hashing comes from searching in an array linearly in O(n) time. Hash function is like a library search (search where it should be).
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
// STL Contianers:
// set (ordered) - O(log n)
// unordered_set - O(1)
// map (ordered) - O(log n)
// unordered_map - O(1)
// set
set<int> st;
st.insert(5);
st.insert(2);
st.insert(3);
st.insert(5);
st[3]; // error
// Memory: 2 3 5
// stores key values only, ordered/ sorted, NO index, NO frequency, NO duplicate
// unordered_set
unordered_set<int> ust;
st.insert(5);
st.insert(2);
st.insert(3);
st.insert(5);
// Memory: 5 2 3 (random)
// stores key values only, NOT ordered/ sorted, NO index, NO frequency, NO duplicate
// map
map<string, int> marks;
marks["Name1"] = 92;
marks["Name2"] = 87;
// stores key value pairs, NO index, sorted, NO duplicate keys, duplicate values possible (updates to latest value)
// unordered_map
unordered_map<string, int> marks;
marks["Name1"] = 92;
marks["Name2"] = 87;
// pre-defined functions
mp.insert({key, value});
mp.find(key); if (mp.find(5) != mp.end()) {}
mp.count(key); if (mp.count(5)) {}
mp.erase(key);
mp.clear();
mp.size();
mp.empty(); // size check
mp.begin();
mp.end();
// iteration elements
for (auto p : mp) cout << p.first << " " << p.second;
// stores key value pairs, NO index, NOT sorted, NO duplicate keys, duplicate values possible (updates to latest value)
// frequency problems are stored as KEY-FREQ PAIRS
// counting frequency in array
unordered_map<int,int> freq;
for(int x : arr)
freq[x]++;
// EXISTENCE CHECKING
// Checking for Duplicates
unordered_set<int> st;
for (int x: arr){
if (st.count(x)) return true;
st.insert(x);
} return false;
// Number of Distinct Elements
unordered_set<int> st(arr.begin(), arr.end());
return st.size();
// Remove Duplicates
unordered_set<int> st(arr.begin(), arr.end());
vector<int> nums(st.begin(), st.end());
// Checking Missing Element
unordered_set<int> st(arr1.begin(), arr1.end());
for (int x: arr2){
if (!st.count(x)) {cout<<x; counter++;}
}
// FREQUENCY COUNTING
// finding frequency of each element
unordered_map<int, int> freq;
for(int x : arr) freq[x]++;
// finding majority element (more than 50%)
unordered_map<int, int> freq;
for (int x : arr){
freq[x]++;
if (freq[x] > arr.size()/2) return x;
}
// first unique character in a string
unordered_map<int, int> freq;
for(int x : arr) freq[x]++;
for (int i=0; i<s.size(); i++){
if (freq[s[i]] == 1) return s[i];
}
// verifying anagram
if (s.size() != t.size()) return false;
unordered_map<int, int> f1, f2;
for (int i : s) f1[i]++;
for (int i : t) f2[i]++;
for (int i : s) if (f1[i] != f2[i]) return false;
return true;
// top K frequent elements
// convert frequency to min. heap
// (OR) frequency + sort
unordered_map<char, int> freq;
for (char c : s) freq[c]++;
vector<pair<int, char>> v;
for (auto p : freq) v.push_back({p.second, p.first});
sort(v.rbegin(), v.rend());
// sort characters by frequency
// convert frequency to min. heap
// (OR) frequency + sort
unordered_map<char, int> freq;
for (char c : s) freq[c]++;
vector<pair<int, char>> v;
for (auto p : freq) v.push_back({p.second, p.first});
sort(v.rbegin(), v.rend());
// HASHMAPS + ARRAYS PATTERN
// Two Sum: a + b = target
unordered_map<int, int> mp; // nums is copied onto mp (only keys)
for (int x: nums){
complement = target - x;
if (mp.count(complement){ // no need to check nums
mp[complement]=x;
}
}
// Longest Consecutive Sequence
unordered_set<int> st(nums.begin(), nums.end());
int longest = 0;
for (int num : st) {
// Start only if num is the beginning of a sequence
if (!st.count(num - 1)) {
int curr = num;
int len = 1;
while (st.count(curr + 1)) { // Checks
curr++;
len++;
}
longest = max(longest, len);
}
}
return longest;
// Missing Number: Sum Method
int missingNumber(vector<int>& nums) {
int n = nums.size();
int expected = n * (n + 1) / 2;
int actual = accumulate(nums.begin(), nums.end(), 0);
return expected - actual;
}
// Missing Number: XOR Logic
int missingNumber(vector<int>& nums) {
int ans = nums.size();
for (int i = 0; i < nums.size(); i++)
ans ^= i ^ nums[i];
return ans;
}
// Continuous Subarray Sum Divisible By K
unordered_map<int, int> mp;
mp[0] = -1; // Handle subarrays starting at index 0
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
int rem = sum % k;
if (mp.count(rem)) {
if (i - mp[rem] >= 2)
return true;
} else {
mp[rem] = i; // Store first occurrence only
}
}
return false;
// Total Subarrays with sum equals K
unordered_map<int, int> mp;
mp[0] = 1; // indicates start and visited
int sum = 0, ans = 0; // current prefix sum and total number of subarrays
for (int x : nums) {
sum += x;
ans += mp[sum - k]; // current prefix sum (sum) - previous prefix sum = k; // If sum - k has appeared before, then every occurrence represents one valid subarray ending at the current index.
mp[sum]++; // store current prefix sum for future iterations
} return ans;
// Need Longest Subarray with equal number of 0's (-1) and 1's (+1): SUM=0
unordered_map<int,int> mp; // key: prefix sum | value: first index where this prefix sum occured
mp[0] = -1; // occurred before starting array
int sum = 0, ans = 0; // sum: longest prefix sum; ans: longest length found
for(int i=0;i<nums.size();i++){
sum += nums[i] ? 1 : -1;
if(mp.count(sum)) // Checks whether we've seen this prefix sum before
ans = max(ans, i - mp[sum]); // If the same prefix sum has appeared before, then the sum between those two indices is 0.
else
mp[sum] = i; // appearing for first time -> store it
}
return ans;
// Longest Subarray with sum = k
unordered_map<int,int> mp;
int sum = 0, ans = 0;
for(int i=0;i<nums.size();i++){
sum += nums[i];
if(sum == k)
ans = i + 1; // takes the length of longest subarray as it is
if(mp.count(sum-k))
ans = max(ans, i - mp[sum-k]); // if current prefix sum - previous prefix sum = k
if(!mp.count(sum))
mp[sum] = i; // if never encountered, store value
}
return ans;
// SLIDING WINDOW + HASHMAP
// Longest Substring without Repeating Characters
unordered_map<char,int> mp;
int l = 0, ans = 0; // r: right pointer; l: left pointer
for(int r = 0; r < s.size(); r++) {
mp[s[r]]++; // addition of frequency when visited by right pointer
while(mp[s[r]] > 1) // if frequency is more than 1 (duplicate exists) and keep moving left pointer until condition satisfied
mp[s[l++]]--; // first decreases freq. then l+1; we are reducing the frequency because the sliding window has moved and removed the duplicate
ans = max(ans, r - l + 1);
} return ans;
// Minimum Substring of s carrying all characters of t
unordered_map<char,int> mp;
for(char c : t) mp[c]++; // listing the frequencies of characters in t
int need = t.size(); // requirement for finding sub-array
int l = 0, start = 0, len = INT_MAX; // l: left pointer, r: right pointer, start: starting index of best answer, len: min. window
for(int r = 0; r < s.size(); r++) {
if(mp[s[r]]-- > 0) need--; // if in s we encounter a character requirement of t, then we reduce the frequency to mark as counted and reduce need (as noted)
while(need == 0) { // if need is complete
if(r - l + 1 < len) { // if the current window size is smaller than the latest window size
len = r - l + 1;
start = l; // update len and start
}
if(++mp[s[l++]] > 0) need++; // meaning of map values: positive (still need these many), zero (need satisfied), negative (extra copies present); we try to minimise the window here as much as possible; if something crucial is removed, it's frequency is added back
}
}
return len == INT_MAX ? "" : s.substr(start, len); // paste the result
// List all positions where anagrams of p are found in s (fixed size window)
vector<int> ans;
unordered_map<char,int> mp;
for(char c : p) mp[c]++; // listing characters and their frequencies
int need = p.size();
for(int l = 0, r = 0; r < s.size(); r++) { // keep moving until all characters are found (r increment)
if(mp[s[r]]-- > 0) need--; // if required char found, reduce freq and need
if(r - l + 1 > p.size()) { // if window is bigger than needed, move the left pointer
if(++mp[s[l++]] > 0) need++; // placing the character back into the needed; it won't add unnecccessary characters in because the map is designed from 'p'
}
if(need == 0) // whenever the conditions are satisfied
ans.push_back(l);
}
return ans;
// Return true if s1's permutation (any random rearrangement) is found in s2 (fixed window: exact same problem as above)
unordered_map<char,int> mp;
for(char c : s1) mp[c]++;
int need = s1.size();
for(int l = 0, r = 0; r < s2.size(); r++) {
if(mp[s2[r]]-- > 0) need--;
if(r - l + 1 > s1.size()) {
if(++mp[s2[l++]] > 0) need++;
}
if(need == 0)
return true;
}
return false;
// Total Number of Subarrays (non-continuous) with K distinct integers (variable size window): Exactly(K) = AtMost(K) - AtMost(K-1)
int atMostK(vector<int>& nums, int k) {
unordered_map<int,int> mp;
int l = 0, ans = 0;
for(int r = 0; r < nums.size(); r++) {
if(mp[nums[r]]++ == 0) // decrease the value of k distinct integers when found (freq == 0) and increase window size
k--;
while(k < 0) { // more than required distinct numbers; shrink from left
if(--mp[nums[l]] == 0) // identifies distinct element; if greater than zero: duplicate is counted; if =0: distinct element is noted
k++;
l++; // shrinks until need returns to required from exceeded state
}
ans += r - l + 1; // counts all valid sub-arrays possible ending at r(every possible right endpoint is considered exactly once: r is the counter variable): ABC -> ABC, BC, C
}
return ans;
}
int subarraysWithKDistinct(vector<int>& nums, int k) {
return atMostK(nums, k) - atMostK(nums, k - 1);
}
// can also be solved by permutations and combinations