├── .gitignore ├── Algorithm └── LeetCode │ ├── Array.md │ ├── Bash.md │ ├── Binary-Search-Tree.md │ ├── BinarySearch.md │ ├── Bit-manipulation.md │ ├── DFS-BFS.md │ ├── DP.md │ ├── Deque.md │ ├── Design.md │ ├── Divide-and-Conquer.md │ ├── Graph.md │ ├── Greedy.md │ ├── Hash-Table.md │ ├── Heap.md │ ├── LinkedList.md │ ├── Math.md │ ├── Stack.md │ ├── String.md │ ├── Tree.md │ ├── Trie.md │ ├── Union-Find.md │ └── high-frequency.md ├── C++ └── Basic-Notes.md ├── Design-Pattern ├── Facade.md └── IoC-DI.md ├── LICENSE ├── OA ├── Linkedin_OA.md └── Twitter_OA.md ├── README.md └── Web-Dev ├── Frontend ├── CSS-basic.md ├── Daily-CSS-study-notes.md ├── Frontend-Knowledge-Notes.md └── Some-CSS-notes.md └── Web-Security └── csrf-attack.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /Algorithm/LeetCode/Bash.md: -------------------------------------------------------------------------------- 1 | ## 1. LeetCode 192 [Word Frequency](https://leetcode.com/problems/word-frequency/) 2 | 3 | **tr -s**: truncate the string with target string, but only remaining one instance (e.g. multiple whitespaces) 4 | 5 | **sort**: To make the same string successive so that `uniq` could count the same string fully and correctly. 6 | 7 | **uniq -c**: uniq is used to filter out the repeated lines which are successive, -c means counting 8 | 9 | **sort -r**: -r means sorting in descending order 10 | 11 | **awk '{ print $2, $1 }'**: To format the output, see [here](http://linux.cn/article-3945-1.html). 12 | 13 | ```bash 14 | # Read from the file words.txt and output the word frequency list to stdout. 15 | cat words.txt | tr -s ' ' '\n' | sort | uniq -c | sort -r | awk '{ print $2, $1 }' 16 | ``` 17 | 18 | [solution](https://leetcode.com/problems/word-frequency/discuss/55443/My-simple-solution-(one-line-with-pipe)) 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 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Binary-Search-Tree.md: -------------------------------------------------------------------------------- 1 | # Binary Search Tree 2 | 3 | ## set & map (in C++) 4 | 5 | [set-reference](http://www.cplusplus.com/reference/set/set/) 6 | 7 | [map-reference](http://www.cplusplus.com/reference/map/map/) 8 | 9 | 10 | 11 | ## 1. LeetCode 729 [My Calendar I](https://leetcode.com/problems/my-calendar-i/) 12 | 13 | ### (1) Brute Force 14 | 15 | ### Intuition 16 | 17 | Store all the booking event in a vector of pairs; 18 | 19 | When a new event comes, check every existing events for overlap 20 | 21 | ```c++ 22 | // Time Complexity: O(n^2) (for n booking) 23 | // Space Complexity: O(n) 24 | 25 | class MyCalendar { 26 | public: 27 | MyCalendar() { 28 | 29 | } 30 | 31 | // O(n) 32 | bool book(int start, int end) { 33 | for (auto &p : events) { 34 | if (max(p.first, start) < min(p.second, end)) return false; 35 | } 36 | events.push_back({start, end}); 37 | return true; 38 | } 39 | 40 | private: 41 | vector> events; 42 | }; 43 | 44 | /** 45 | * Your MyCalendar object will be instantiated and called as such: 46 | * MyCalendar obj = new MyCalendar(); 47 | * bool param_1 = obj.book(start,end); 48 | */ 49 | ``` 50 | 51 | 52 | 53 | ### (2) Binary Search Tree (set / map) 54 | 55 | Keep the intervals sorted. 56 | 57 | Everytime a new event comes, check the interval started right after and right before the new event. 58 | 59 | If there is overlap, then return false. 60 | 61 | **TreeMap:** 62 | 63 | ```c++ 64 | // Time Complexity: O(nlogn) (for n booking) 65 | // Space Complexity: O(n) 66 | 67 | class MyCalendar { 68 | public: 69 | MyCalendar() { 70 | 71 | } 72 | 73 | // O(logn) 74 | bool book(int start, int end) { 75 | // the first element in the container whose key is not considered 76 | // to go before k (i.e., either it is equivalent or goes after). 77 | auto it = events.lower_bound(start); 78 | if (it != events.end() && it->first < end) return false; 79 | if (it != events.begin() && (--it)->second > start) return false; 80 | events[start] = end; 81 | return true; 82 | } 83 | 84 | private: 85 | map events; 86 | }; 87 | 88 | /** 89 | * Your MyCalendar object will be instantiated and called as such: 90 | * MyCalendar obj = new MyCalendar(); 91 | * bool param_1 = obj.book(start,end); 92 | */ 93 | ``` 94 | 95 | **TreeSet:** 96 | 97 | ```c++ 98 | class MyCalendar { 99 | public: 100 | MyCalendar() { 101 | 102 | } 103 | 104 | bool book(int start, int end) { 105 | auto it = events.lower_bound({start, end}); 106 | if (it != events.end() && it->first < end) return false; 107 | if (it != events.begin() && (--it)->second > start) return false; 108 | events.insert({start, end}); 109 | return true; 110 | } 111 | 112 | private: 113 | set> events; 114 | }; 115 | 116 | /** 117 | * Your MyCalendar object will be instantiated and called as such: 118 | * MyCalendar obj = new MyCalendar(); 119 | * bool param_1 = obj.book(start,end); 120 | */ 121 | ``` 122 | 123 | 124 | 125 | ## 2. LeetCode 731 [My Calendar II](https://leetcode.com/problems/my-calendar-ii/) 126 | 127 | ### (1) Brute Force 128 | 129 | Reuse the class in MyCalendar (leetcode 729), use it as the overlap records; 130 | 131 | Everytime a new event comes, find all the overlapped intervals, and check whether there are two among them overlap. 132 | 133 | ```c++ 134 | class MyCalendar { 135 | public: 136 | MyCalendar() {} 137 | 138 | // O(logn) 139 | bool book(int start, int end) { 140 | auto it = events.lower_bound({start, end}); 141 | if (it != events.end() && it->first < end) return false; 142 | if (it != events.begin() && (--it)->second > start) return false; 143 | events.insert({start, end}); 144 | return true; 145 | } 146 | 147 | private: 148 | set> events; 149 | }; 150 | 151 | class MyCalendarTwo { 152 | public: 153 | MyCalendarTwo() {} 154 | 155 | // O(nlogn) 156 | bool book(int start, int end) { 157 | MyCalendar overlaps; 158 | for (auto &p : events) { 159 | if (max(p.first, start) < min(p.second, end)) { 160 | // overlap exists 161 | pair overlap = {max(p.first, start), min(p.second, end)}; 162 | // check whether this overlap interval is overlapped with other intervals in overlaps 163 | if (!overlaps.book(overlap.first, overlap.second)) return false; 164 | } 165 | } 166 | events.push_back({start, end}); 167 | return true; 168 | } 169 | 170 | private: 171 | vector> events; 172 | }; 173 | 174 | /** 175 | * Your MyCalendarTwo object will be instantiated and called as such: 176 | * MyCalendarTwo obj = new MyCalendarTwo(); 177 | * bool param_1 = obj.book(start,end); 178 | */ 179 | ``` 180 | 181 | 182 | 183 | ### (2) Binary Search Tree (Boundary Count) 184 | 185 | The idea is very simple. First step, add the interval into map. Second step, check if there exists triple book in the map. 186 | 187 | For first step, it increments entrance by 1, and decrements exit by 1. 188 | For second step, it traverses from leftmost to rightmost, by the sorting property of map. The `booked` keeps track of the number of overlapped intervals. 189 | 190 | For example, when an index `i` does not belong to any interval, booked should be 0. When `i` belong to one interval, booked should be equal to this interval's `map[start]`value (i.e. 1), and when `i` continues moving rightward, booked will be become zero after `i` is out of the interval. When `i` belongs to `k` intervals, booked should be equal to `k`, as there were `k` `start`'s before `i`. 191 | 192 | Entrance-Increment-Exit-Decrement is a typical way to solve interval problem. Another typical way is using binary search for a sorted interval array. 193 | 194 | ```c++ 195 | class MyCalendarTwo { 196 | public: 197 | MyCalendarTwo() { 198 | 199 | } 200 | 201 | // O(n) 202 | bool book(int start, int end) { 203 | boundaries[start]++; 204 | boundaries[end]--; 205 | int booked = 0; 206 | 207 | for (auto &p : boundaries) { 208 | booked += p.second; 209 | if (booked > 2) { 210 | boundaries[start]--; 211 | boundaries[end]++; 212 | return false; 213 | } 214 | } 215 | 216 | return true; 217 | } 218 | 219 | private: 220 | map boundaries; 221 | }; 222 | 223 | /** 224 | * Your MyCalendarTwo object will be instantiated and called as such: 225 | * MyCalendarTwo obj = new MyCalendarTwo(); 226 | * bool param_1 = obj.book(start,end); 227 | */ 228 | ``` 229 | 230 | [solution](https://leetcode.com/problems/my-calendar-ii/discuss/109522/Simplified-winner's-solution) 231 | 232 | 233 | 234 | ## 3. LeetCode 732 [My Calendar III](https://leetcode.com/problems/my-calendar-iii/) 235 | 236 | Idea is the same as 731 (2) 237 | 238 | ```c++ 239 | class MyCalendarThree { 240 | public: 241 | MyCalendarThree() {} 242 | 243 | int book(int start, int end) { 244 | boundaries[start]++; 245 | boundaries[end]--; 246 | 247 | int booked = 0; 248 | int max_overlap = 1; 249 | 250 | for (auto &p : boundaries) { 251 | booked += p.second; 252 | max_overlap = max(booked, max_overlap); 253 | } 254 | 255 | return max_overlap; 256 | } 257 | 258 | private: 259 | map boundaries; 260 | }; 261 | 262 | /** 263 | * Your MyCalendarThree object will be instantiated and called as such: 264 | * MyCalendarThree obj = new MyCalendarThree(); 265 | * int param_1 = obj.book(start,end); 266 | */ 267 | ``` 268 | 269 | 270 | 271 | ## 4. LeetCode 683 [K Empty Slots](https://leetcode.com/problems/k-empty-slots/) 272 | 273 | ```c++ 274 | class Solution { 275 | public: 276 | int kEmptySlots(vector& flowers, int k) { 277 | int n = flowers.size(); 278 | if (k > n-2) return -1; 279 | set ts; 280 | ts.insert(0); 281 | ts.insert(n+1); 282 | 283 | for (int i=0; i& position, vector& speed) { 313 | map> mp; 314 | int n = position.size(); 315 | for (int i=0; i cur_lowest) { 323 | cur_lowest = p.second; 324 | ans++; 325 | } 326 | } 327 | 328 | return ans; 329 | } 330 | }; 331 | ``` 332 | 333 | [solution](https://leetcode.com/problems/car-fleet/discuss/139850/C%2B%2BJavaPython-Straight-Forward) 334 | 335 | 336 | 337 | ## 6. LeetCode 846 [Hand of Straights](https://leetcode.com/problems/hand-of-straights/) 338 | 339 | ```c++ 340 | class Solution { 341 | public: 342 | bool isNStraightHand(vector& hand, int W) { 343 | if (hand.size() % W != 0) return false; 344 | 345 | map cards; 346 | 347 | for (auto card : hand) { 348 | cards[card]++; 349 | } 350 | 351 | for (auto it = cards.begin(); it != cards.end(); ) { 352 | if (it->second == 0) { 353 | it++; 354 | continue; 355 | } 356 | 357 | it->second--; 358 | 359 | for (int i=1; ifirst + i; 361 | 362 | if (cards.find(next) == cards.end() || cards[next] == 0) { 363 | return false; 364 | } 365 | cards[next]--; 366 | } 367 | } 368 | 369 | return true; 370 | } 371 | }; 372 | ``` 373 | 374 | [solution](https://leetcode.com/problems/hand-of-straights/discuss/135598/C%2B%2BJavaPython-O(MlogM)-Complexity) 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Bit-manipulation.md: -------------------------------------------------------------------------------- 1 | [Bit-Manipulation-Summary](https://leetcode.com/problems/sum-of-two-integers/discuss/84278/A-summary%3A-how-to-use-bit-manipulation-to-solve-problems-easily-and-efficiently) 2 | 3 | 4 | 5 | ## 1. LeetCode 136 [Single Number](https://leetcode.com/problems/single-number/) 6 | 7 | ```c++ 8 | class Solution { 9 | public: 10 | int singleNumber(vector& nums) { 11 | int size = nums.size(); 12 | int result = 0; 13 | for(int i=0; i& nums) { 29 | int size = nums.size(); 30 | int a = 0, b = 0; 31 | for(int i=0; i singleNumber(vector& nums) { 48 | int size = nums.size(); 49 | int a = 0; 50 | for(int i=0; i result = {0, 0}; 57 | for(int i=0; i>= 1; 81 | } 82 | return cnt; 83 | } 84 | }; 85 | ``` 86 | 87 | 88 | 89 | ## 5. LeetCode 78 [Subsets](https://leetcode.com/problems/subsets/) 90 | 91 | ```c++ 92 | class Solution { 93 | public: 94 | vector> subsets(vector& nums) { 95 | int n = (int)nums.size(); 96 | int m = (int)pow(2,n); 97 | vector> subs(m, vector()); 98 | for(int i=0,q=1; i> 16) | (n << 16); 119 | n = ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8); 120 | n = ((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4); 121 | n = ((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2); 122 | n = ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1); 123 | return n; 124 | } 125 | }; 126 | ``` 127 | 128 | 129 | 130 | ## 7. LeetCode 338 [Counting Bits](https://leetcode.com/problems/counting-bits/) 131 | 132 | ```c++ 133 | class Solution { 134 | public: 135 | vector countBits(int num) { 136 | vector dp(num+1, 0); 137 | int offset = 1; 138 | for (int i=1; i<=num; i++) { 139 | if (i == offset * 2) { 140 | offset *= 2; 141 | } 142 | dp[i] = dp[i-offset] + 1; 143 | } 144 | return dp; 145 | } 146 | }; 147 | ``` 148 | 149 | 150 | 151 | ## 8. LeetCode 401 [Binary Watch](https://leetcode.com/problems/binary-watch/) 152 | 153 | ```c++ 154 | class Solution { 155 | public: 156 | vector readBinaryWatch(int num) { 157 | vector result; 158 | for(int h = 0; h < 12; h++) { 159 | for(int m = 0; m < 60; m++) { 160 | if(bitset<10>(h << 6 | m).count() == num) { 161 | result.emplace_back(to_string(h) + (m < 10 ? ":0" : ":") + to_string(m)); 162 | } 163 | } 164 | } 165 | return result; 166 | } 167 | }; 168 | ``` 169 | 170 | 171 | 172 | ## 9. LeetCode 461 [Hamming Distance](https://leetcode.com/problems/hamming-distance/) 173 | 174 | ```c++ 175 | // solution 1 176 | class Solution { 177 | public: 178 | int hammingDistance(int x, int y) { 179 | int cnt = 0; 180 | while(x > 0 || y > 0) { 181 | (x & 1) != (y & 1) ? cnt++ : 0; 182 | x >>= 1; 183 | y >>= 1; 184 | } 185 | return cnt; 186 | } 187 | }; 188 | 189 | // solution 2 190 | class Solution { 191 | public: 192 | int hammingDistance(int x, int y) { 193 | int cnt = 0; 194 | int z = x ^ y; 195 | while(z > 0) { 196 | (z & 1) ? cnt++ : 0; 197 | z >>= 1; 198 | } 199 | return cnt; 200 | } 201 | }; 202 | ``` 203 | 204 | 205 | 206 | ## 10. LeetCode 477 [Total Hamming Distance](https://leetcode.com/problems/total-hamming-distance/) 207 | 208 | ```c++ 209 | class Solution { 210 | public: 211 | int hammingDistance(int x, int y) { 212 | int cnt = 0; 213 | int z = x ^ y; 214 | while(z > 0) { 215 | (z & 1) ? cnt++ : 0; 216 | z >>= 1; 217 | } 218 | return cnt; 219 | /* 220 | while(x > 0 || y > 0) { 221 | (x & 1) != (y & 1) ? cnt++ : 0; 222 | x >>= 1; 223 | y >>= 1; 224 | } 225 | return cnt;*/ 226 | } 227 | }; 228 | ``` 229 | 230 | 231 | 232 | ## 11. LeetCode 693 [Binary Number with Alternating Bits](https://leetcode.com/problems/binary-number-with-alternating-bits/) 233 | 234 | ```c++ 235 | class Solution { 236 | public: 237 | bool hasAlternatingBits(int n) { 238 | vector v; 239 | while(n) { 240 | v.push_back(n % 2); 241 | n >>= 1; 242 | } 243 | for(int i=0; i m) ? (rangeBitwiseAnd(m/2, n/2) << 1) : m; 260 | } 261 | }; 262 | ``` 263 | 264 | 265 | 266 | ## 13. LeetCode 371 [Sum of Two Integers](https://leetcode.com/problems/sum-of-two-integers/) 267 | 268 | ```c++ 269 | class Solution { 270 | public: 271 | int getSum(unsigned int a, unsigned int b) { 272 | int sum = a; 273 | 274 | while (b != 0) { 275 | sum = a ^ b; //calculate sum of a and b without thinking the carry 276 | b = (a & b) << 1; //calculate the carry 277 | a = sum; //add sum(without carry) and carry 278 | } 279 | 280 | return sum; 281 | } 282 | }; 283 | 284 | // recursion 285 | class Solution { 286 | public: 287 | int getSum(unsigned int a, unsigned int b) { 288 | return b == 0 ? a : getSum(a ^ b, (a & b) << 1); 289 | } 290 | }; 291 | ``` 292 | 293 | 294 | 295 | ## 14. LeetCode 389 [Find the Difference](https://leetcode.com/problems/find-the-difference/) 296 | 297 | ```c++ 298 | class Solution { 299 | public: 300 | char findTheDifference(string s, string t) { 301 | int bits = 0; 302 | 303 | for (char &c : s) { 304 | bits ^= c; 305 | } 306 | 307 | for (char &c : t) { 308 | bits ^= c; 309 | } 310 | 311 | return bits; 312 | } 313 | }; 314 | ``` 315 | 316 | 317 | 318 | ## 15. LeetCode 405 [Convert a Number to Hexadecimal](https://leetcode.com/problems/convert-a-number-to-hexadecimal/) 319 | 320 | ```c++ 321 | class Solution { 322 | public: 323 | string toHex(int num) { 324 | char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 325 | string hex = ""; 326 | 327 | unsigned int n = num; 328 | while (n) { 329 | hex = digits[n & 0xf] + hex; 330 | n >>= 4; 331 | } 332 | return hex.empty() ? "0" : hex; 333 | } 334 | }; 335 | 336 | class Solution { 337 | public: 338 | string toHex(int num) { 339 | int count = 0; 340 | if(!num) return "0"; 341 | string result; 342 | while (num && count < 8) { 343 | int temp = num & 15; 344 | if (temp < 10) result.push_back('0' + temp); 345 | else result.push_back('a' + temp - 10); 346 | num = num >> 4; 347 | count++; 348 | } 349 | reverse(result.begin(), result.end()); 350 | return result; 351 | } 352 | }; 353 | ``` 354 | 355 | 356 | 357 | ## 16. LeetCode 476 [Number Complement](https://leetcode.com/problems/number-complement/) 358 | 359 | ```c++ 360 | class Solution { 361 | public: 362 | int findComplement(int num) { 363 | unsigned int mask = ~0; 364 | while (num & mask) mask <<= 1; 365 | return ~mask & ~num; 366 | } 367 | }; 368 | ``` 369 | 370 | 371 | 372 | ## 17. LeetCode 500 [Keyboard Row](https://leetcode.com/problems/keyboard-row/) 373 | 374 | ```c++ 375 | class Solution { 376 | public: 377 | vector findWords(vector& words) { 378 | vector dict(26); 379 | vector rows = {"QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM"}; 380 | for (int i = 0; i < rows.size(); i++) { 381 | for (auto &c : rows[i]) dict[c-'A'] = 1 << i; 382 | } 383 | 384 | vector res; 385 | for (auto w : words) { 386 | int r = 7; 387 | for (char c : w) { 388 | r &= dict[toupper(c)-'A']; 389 | if (r == 0) break; 390 | } 391 | if (r) res.push_back(w); 392 | } 393 | return res; 394 | } 395 | }; 396 | ``` 397 | 398 | 399 | 400 | ## 18. LeetCode 898 [Bitwise ORs of Subarrays](https://leetcode.com/problems/bitwise-ors-of-subarrays/) 401 | 402 | ### Bruteforce + hashset 403 | 404 | ```c++ 405 | class Solution { 406 | public: 407 | int subarrayBitwiseORs(vector& A) { 408 | unordered_set res, cur; 409 | cur.insert(0); 410 | 411 | for (int a : A) { 412 | unordered_set cur2; 413 | for (int b : cur) { 414 | cur2.insert(a | b); 415 | } 416 | cur2.insert(a); 417 | swap(cur, cur2); 418 | 419 | for (int x : cur) { 420 | res.insert(x); 421 | } 422 | } 423 | 424 | return res.size(); 425 | } 426 | }; 427 | ``` 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Deque.md: -------------------------------------------------------------------------------- 1 | ## 1. LeetCode 239 [Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/) 2 | 3 | ## *Data Structure* 4 | 5 | ### - deque 6 | 7 | [cplusplus-reference](http://www.cplusplus.com/reference/deque/deque/?kw=deque) 8 | 9 | ```c++ 10 | // constructor 11 | deque dq; 12 | {1, 3, 5, 6, 8, 11} 13 | [front, ..., back] 14 | 15 | // Iterators: 16 | dq.begin(); 17 | dq.end(); 18 | dq.rbegin(); 19 | dq.rend(); 20 | 21 | // Capacity: 22 | dq.size(); 23 | dq.empty(); 24 | 25 | // Element access: 26 | operator[]; 27 | dq.at(i); 28 | dq.back(); 29 | dq.front(); 30 | 31 | // Modifiers: 32 | dq.push_back(); // add element at th end 33 | dq.push_front(); // add element at the beginning 34 | dq.pop_back(); // delete last element 35 | dq.pop_front(); // delete first element 36 | 37 | ``` 38 | 39 | 40 | 41 | ### (1) Deque Solution 42 | 43 | ```c++ 44 | // Time Complexity: O(n) (n = length of nums) 45 | // every number is inserted and deleted once at most, so the time complexity is O(2n)=>O(n) 46 | // Space Complexity: O(k) 47 | 48 | class Solution { 49 | public: 50 | vector maxSlidingWindow(vector& nums, int k) { 51 | int n = nums.size(); 52 | deque dq; 53 | vector res; 54 | 55 | for (int i=0; i= k-1) res.push_back(nums[dq.front()]); 64 | } 65 | return res; 66 | } 67 | }; 68 | ``` 69 | 70 | 71 | 72 | ### (2) Two Pass + Window (Greedy?) 73 | 74 | ```c++ 75 | class Solution { 76 | public: 77 | vector maxSlidingWindow(vector& nums, int k) { 78 | if (nums.empty()) return {}; 79 | int n = nums.size(); 80 | vector max_left(n); 81 | vector max_right(n); 82 | 83 | // initialization 84 | max_left[0] = nums[0]; 85 | max_right[n-1] = nums[n-1]; 86 | 87 | for (int i=1; i sliding_max(n-k+1); 95 | for (int i=0, j=0; i + k <= n; i++) { 96 | sliding_max[j++] = max(max_right[i], max_left[i+k-1]); 97 | } 98 | 99 | return sliding_max; 100 | } 101 | }; 102 | ``` 103 | 104 | [solution](https://leetcode.com/problems/sliding-window-maximum/discuss/65881/O(n)-solution-in-Java-with-two-simple-pass-in-the-array) 105 | 106 | 107 | 108 | ## 2. LeetCode 862 [Shortest Subarray with Sum at Least K](https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/) 109 | 110 | ```c++ 111 | // Time Complexity: O(n) 112 | // Space Complexity: O(n) 113 | 114 | class Solution { 115 | public: 116 | int shortestSubarray(vector& A, int K) { 117 | int n = A.size(); 118 | int res = n + 1; 119 | vector ps(n+1); 120 | 121 | for (int i=0; i dq; 126 | for (int i=0; i= K)) { 128 | res = min(res, i - dq.front()); 129 | dq.pop_front(); 130 | } 131 | 132 | while (!dq.empty() && ps[i] <= ps[dq.back()]) { 133 | dq.pop_back(); 134 | } 135 | 136 | dq.push_back(i); 137 | } 138 | 139 | return res <= n ? res : -1; 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 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Design.md: -------------------------------------------------------------------------------- 1 | # Data Structure Design 2 | 3 | ## 1. LeetCode 251 [Flatten 2D Vector](https://leetcode.com/problems/flatten-2d-vector/) 4 | 5 | ### (1) Using C++ iterators 6 | 7 | ```c++ 8 | class Vector2D { 9 | private: 10 | vector>::iterator i, iEnd; 11 | int j = 0; 12 | 13 | public: 14 | Vector2D(vector>& vec2d) { 15 | i = vec2d.begin(); 16 | iEnd = vec2d.end(); 17 | } 18 | 19 | int next() { 20 | hasNext(); // It's used when user keep calling next() without hasNext() 21 | return (*i)[j++]; 22 | } 23 | 24 | bool hasNext() { 25 | while (i != iEnd && j == (*i).size()) { 26 | i++; 27 | j = 0; 28 | } 29 | return i != iEnd; 30 | } 31 | }; 32 | 33 | /** 34 | * Your Vector2D object will be instantiated and called as such: 35 | * Vector2D i(vec2d); 36 | * while (i.hasNext()) cout << i.next(); 37 | */ 38 | ``` 39 | 40 | [solution](https://leetcode.com/problems/flatten-2d-vector/discuss/67652/7-9-lines-added-Java-and-C%2B%2B-O(1)-space.) 41 | 42 | [Spliterators](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/Spliterators.java#l679) 43 | 44 | 45 | 46 | ### (2) Using a vector 47 | 48 | ```c++ 49 | class Vector2D { 50 | vector vec; 51 | int i; 52 | int j; 53 | public: 54 | Vector2D(vector>& vec2d) { 55 | for(i = 0; i < vec2d.size(); i++){ 56 | for(j = 0; j < vec2d[i].size();j++){ 57 | vec.push_back(vec2d[i][j]); 58 | } 59 | } 60 | i = 0; 61 | } 62 | 63 | int next() { 64 | int res = vec[i++]; 65 | return res; 66 | } 67 | 68 | bool hasNext() { 69 | return i < vec.size(); 70 | } 71 | }; 72 | 73 | /** 74 | * Your Vector2D object will be instantiated and called as such: 75 | * Vector2D i(vec2d); 76 | * while (i.hasNext()) cout << i.next(); 77 | */ 78 | ``` 79 | 80 | 81 | 82 | ## 2. LeetCode 933 [Number of Recent Calls](https://leetcode.com/problems/number-of-recent-calls/) 83 | 84 | ### (1) Deque 85 | 86 | ```c++ 87 | class RecentCounter { 88 | public: 89 | RecentCounter() { 90 | 91 | } 92 | 93 | int ping(int t) { 94 | while (!dq.empty()) { 95 | int min = dq.back(); 96 | if (t - min > 3000) { 97 | dq.pop_back(); 98 | } else { 99 | break; 100 | } 101 | } 102 | dq.push_front(t); 103 | return dq.size(); 104 | } 105 | private: 106 | deque dq; 107 | }; 108 | 109 | /** 110 | * Your RecentCounter object will be instantiated and called as such: 111 | * RecentCounter* obj = new RecentCounter(); 112 | * int param_1 = obj->ping(t); 113 | */ 114 | ``` 115 | 116 | 117 | 118 | ### (2) vector + two pointers 119 | 120 | ```c++ 121 | class RecentCounter { 122 | // max capicity should >= 3000 + 1 123 | // however, due to the implementation of ping(), 124 | // it's possible that there are 3002 elements in the queue 125 | // so the min size of queue is 3002 126 | static const int POOL_SIZE = 3002; 127 | int pings[POOL_SIZE]; 128 | int st; 129 | int ed; 130 | int size; 131 | 132 | public: 133 | RecentCounter() { 134 | st = 0; 135 | ed = 0; 136 | size = 0; 137 | } 138 | 139 | int ping(int t) { 140 | pings[ed++] = t; 141 | ed %= POOL_SIZE; 142 | size ++; 143 | 144 | while (pings[st] < t - 3000) { 145 | st = (++st) % POOL_SIZE; 146 | size --; 147 | } 148 | return size; 149 | } 150 | }; 151 | ``` 152 | 153 | 154 | 155 | ### (3) Queue 156 | 157 | ```c++ 158 | class RecentCounter { 159 | public: 160 | RecentCounter() { 161 | 162 | } 163 | 164 | int ping(int t) { 165 | q.push(t); 166 | while (q.front() < t - 3000) { 167 | q.pop(); 168 | } 169 | return q.size(); 170 | } 171 | 172 | private: 173 | queue q; 174 | }; 175 | 176 | /** 177 | * Your RecentCounter object will be instantiated and called as such: 178 | * RecentCounter* obj = new RecentCounter(); 179 | * int param_1 = obj->ping(t); 180 | */ 181 | ``` 182 | 183 | 184 | 185 | ## 3. LeetCode 146 [LRU Cache](https://leetcode.com/problems/lru-cache/) 186 | 187 | ### List 188 | 189 | [cplusplus](http://www.cplusplus.com/reference/list/list/?kw=list) 190 | 191 | ```c++ 192 | class LRUCache { 193 | public: 194 | LRUCache(int capacity) : _capacity(capacity) {} 195 | 196 | int get(int key) { 197 | auto it = cache.find(key); 198 | if (it == cache.end()) return -1; 199 | use(it); 200 | return it->second.first; 201 | } 202 | 203 | void put(int key, int value) { 204 | auto it = cache.find(key); 205 | if (it != cache.end()) { 206 | use(it); 207 | } else { 208 | if (cache.size() == _capacity) { 209 | cache.erase(used.back()); 210 | used.pop_back(); 211 | } 212 | used.push_front(key); 213 | } 214 | cache[key] = {value, used.begin()}; 215 | } 216 | 217 | private: 218 | typedef list LI; // double-linked list 219 | typedef pair PIIT; 220 | typedef unordered_map HIPIIT; 221 | 222 | void use(HIPIIT::iterator it) { 223 | int key = it->first; 224 | used.erase(it->second.second); 225 | used.push_front(key); 226 | it->second.second = used.begin(); 227 | } 228 | 229 | LI used; 230 | HIPIIT cache; 231 | int _capacity; 232 | }; 233 | 234 | /** 235 | * Your LRUCache object will be instantiated and called as such: 236 | * LRUCache obj = new LRUCache(capacity); 237 | * int param_1 = obj.get(key); 238 | * obj.put(key,value); 239 | */ 240 | ``` 241 | 242 | [solution](https://leetcode.com/problems/lru-cache/discuss/45976/C%2B%2B11-code-74ms-Hash-table-%2B-List) 243 | 244 | 245 | 246 | ## 4. LeetCode 460 [LFU Cache](https://leetcode.com/problems/lfu-cache/) 247 | 248 | [huahua-video](https://zxi.mytechroad.com/blog/hashtable/leetcode-460-lfu-cache/) 249 | 250 | ### (1) Hashmap + Balanced Search Tree(Set in C++) (O(logk) + O(logk)) 251 | 252 | ```c++ 253 | struct CacheNode { 254 | int key; 255 | int val; 256 | int freq; 257 | long tick; 258 | 259 | bool operator <(const CacheNode &rhs) const { 260 | if (freq < rhs.freq) { 261 | return true; 262 | } else if (freq == rhs.freq) { 263 | return tick < rhs.tick; 264 | } else { 265 | return false; 266 | } 267 | } 268 | }; 269 | 270 | class LFUCache { 271 | public: 272 | LFUCache(int capacity) : _capacity(capacity), _tick(0) {} 273 | 274 | int get(int key) { 275 | auto it = _mp.find(key); 276 | if (it == _mp.cend()) return -1; 277 | use(it->second); 278 | return it->second.val; 279 | } 280 | 281 | void put(int key, int value) { 282 | if (_capacity == 0) return; 283 | 284 | auto it = _mp.find(key); 285 | if (it != _mp.cend()) { 286 | it->second.val = value; 287 | use(it->second); 288 | return; 289 | } else { 290 | if (_cache.size() == _capacity) { 291 | const CacheNode &lfu = *_cache.cbegin(); 292 | _mp.erase(lfu.key); 293 | _cache.erase(lfu); 294 | } 295 | 296 | CacheNode node{key, value, 1, ++_tick}; 297 | _mp[key] = node; 298 | _cache.insert(node); 299 | } 300 | } 301 | 302 | private: 303 | void use(CacheNode &node) { 304 | _cache.erase(node); 305 | node.freq++; 306 | node.tick = ++_tick; 307 | _cache.insert(node); 308 | } 309 | 310 | unordered_map _mp; // key <=> Node 311 | set _cache; // used for sorting the nodes 312 | 313 | long _tick; // time counter 314 | int _capacity; // capacity 315 | }; 316 | /** 317 | * Your LFUCache object will be instantiated and called as such: 318 | * LFUCache obj = new LFUCache(capacity); 319 | * int param_1 = obj.get(key); 320 | * obj.put(key,value); 321 | */ 322 | ``` 323 | 324 | [solution](https://leetcode.com/problems/lfu-cache/discuss/94516/Concise-C%2B%2B-O(1)-solution-using-3-hash-maps-with-explanation) 325 | 326 | 327 | 328 | ### (2) Hashmap + Doubly-linked List (O(1) + O(1)) 329 | 330 | ```c++ 331 | struct CacheNode { 332 | int key; 333 | int val; 334 | int freq; 335 | 336 | // pointer to the node in the list 337 | list::const_iterator it; 338 | }; 339 | 340 | class LFUCache { 341 | public: 342 | LFUCache(int capacity) : _capacity(capacity), _min_freq(0) {} 343 | 344 | int get(int key) { 345 | auto it = _mp.find(key); 346 | if (it == _mp.cend()) return -1; 347 | use(it->second); 348 | return it->second.val; 349 | } 350 | 351 | void put(int key, int value) { 352 | if (_capacity == 0) return; 353 | 354 | auto it = _mp.find(key); 355 | if (it != _mp.cend()) { 356 | // key already exists, update the value and call use() 357 | it->second.val = value; 358 | use(it->second); 359 | return; 360 | } 361 | 362 | if (_mp.size() == _capacity) { 363 | // reach capacity, need to remove a node which 364 | // (1) has the lowest freq 365 | // (2) least recently used if there are multiple ones 366 | 367 | const int key_to_remove = _freqMP[_min_freq].back(); 368 | _freqMP[_min_freq].pop_back(); 369 | _mp.erase(key_to_remove); 370 | } 371 | 372 | // new item has freq of 1, thus _min_freq needs to be set to 1 373 | const int freq = 1; 374 | _min_freq = freq; 375 | 376 | // Add the key to freq list 377 | _freqMP[freq].push_front(key); 378 | 379 | // create a new node 380 | _mp[key] = {key, value, freq, _freqMP[freq].cbegin()}; 381 | } 382 | 383 | private: 384 | void use(CacheNode& node) { 385 | // update the frequency 386 | const int prev_freq = node.freq; 387 | const int cur_freq = ++(node.freq); 388 | 389 | // remove the entry from old freq list 390 | _freqMP[prev_freq].erase(node.it); 391 | 392 | if (_freqMP[prev_freq].empty() && prev_freq == _min_freq) { 393 | _min_freq++; 394 | } 395 | 396 | // insert the key into the front of the new freq list 397 | _freqMP[cur_freq].push_front(node.key); 398 | 399 | // update the pointer of node 400 | node.it = _freqMP[cur_freq].cbegin(); 401 | } 402 | 403 | int _capacity; 404 | int _min_freq; 405 | 406 | // key -> CacheNode 407 | unordered_map _mp; 408 | 409 | // freq -> keys with freq 410 | unordered_map> _freqMP; 411 | 412 | }; 413 | 414 | /** 415 | * Your LFUCache object will be instantiated and called as such: 416 | * LFUCache obj = new LFUCache(capacity); 417 | * int param_1 = obj.get(key); 418 | * obj.put(key,value); 419 | */ 420 | ``` 421 | 422 | 423 | 424 | ## 5. LeetCode 359 [Logger Rate Limiter](https://leetcode.com/problems/logger-rate-limiter/) 425 | 426 | ### Hash Table 427 | 428 | ```c++ 429 | class Logger { 430 | public: 431 | /** Initialize your data structure here. */ 432 | Logger() {} 433 | 434 | /** Returns true if the message should be printed in the given timestamp, otherwise returns false. 435 | If this method returns false, the message will not be printed. 436 | The timestamp is in seconds granularity. */ 437 | bool shouldPrintMessage(int timestamp, string message) { 438 | if (messages.count(message)) { 439 | if (timestamp - messages[message] < 10) { 440 | return false; 441 | } 442 | } 443 | messages[message] = timestamp; 444 | return true; 445 | } 446 | 447 | private: 448 | unordered_map messages; 449 | }; 450 | 451 | /** 452 | * Your Logger object will be instantiated and called as such: 453 | * Logger obj = new Logger(); 454 | * bool param_1 = obj.shouldPrintMessage(timestamp,message); 455 | */ 456 | ``` 457 | 458 | 459 | 460 | ## 6. LeetCode 362 [Design Hit Counter](https://leetcode.com/problems/design-hit-counter/) 461 | 462 | ```c++ 463 | class HitCounter { 464 | public: 465 | /** Initialize your data structure here. */ 466 | HitCounter() : times(300), hits(300) {} 467 | 468 | /** Record a hit. 469 | @param timestamp - The current timestamp (in seconds granularity). */ 470 | void hit(int timestamp) { 471 | int index = timestamp % 300; 472 | if (times[index] != timestamp) { 473 | times[index] = timestamp; 474 | hits[index] = 1; 475 | } else { 476 | hits[index]++; 477 | } 478 | } 479 | 480 | /** Return the number of hits in the past 5 minutes. 481 | @param timestamp - The current timestamp (in seconds granularity). */ 482 | int getHits(int timestamp) { 483 | int total = 0; 484 | for (int i = 0; i < 300; i++) { 485 | if (timestamp - times[i] < 300) { 486 | total += hits[i]; 487 | } 488 | } 489 | return total; 490 | } 491 | 492 | private: 493 | vector times; 494 | vector hits; 495 | }; 496 | 497 | /** 498 | * Your HitCounter object will be instantiated and called as such: 499 | * HitCounter obj = new HitCounter(); 500 | * obj.hit(timestamp); 501 | * int param_2 = obj.getHits(timestamp); 502 | */ 503 | ``` 504 | 505 | 506 | 507 | ## 7. LeetCode 716 [Max Stack](https://leetcode.com/problems/max-stack/) 508 | 509 | ```c++ 510 | class MaxStack { 511 | public: 512 | /** initialize your data structure here. */ 513 | MaxStack() {} 514 | 515 | void push(int x) { 516 | int mx = maxStack.empty() ? x : maxStack.top(); 517 | maxStack.push(mx > x ? mx : x); 518 | helperStack.push(x); 519 | } 520 | 521 | int pop() { 522 | maxStack.pop(); 523 | int top = helperStack.top(); 524 | helperStack.pop(); 525 | return top; 526 | } 527 | 528 | int top() { 529 | return helperStack.top(); 530 | } 531 | 532 | int peekMax() { 533 | return maxStack.top(); 534 | } 535 | 536 | int popMax() { 537 | int mx = peekMax(); 538 | stack buff; 539 | while (top() != mx) { 540 | buff.push(pop()); 541 | } 542 | pop(); 543 | while (!buff.empty()) { 544 | push(buff.top()); 545 | buff.pop(); 546 | } 547 | 548 | return mx; 549 | } 550 | 551 | private: 552 | stack helperStack; 553 | stack maxStack; 554 | }; 555 | 556 | /** 557 | * Your MaxStack object will be instantiated and called as such: 558 | * MaxStack obj = new MaxStack(); 559 | * obj.push(x); 560 | * int param_2 = obj.pop(); 561 | * int param_3 = obj.top(); 562 | * int param_4 = obj.peekMax(); 563 | * int param_5 = obj.popMax(); 564 | */ 565 | ``` 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Divide-and-Conquer.md: -------------------------------------------------------------------------------- 1 | # Divide & Conquer 2 | 3 | ## 1. LeetCode 315 [Count of Smaller Numbers After Self](https://leetcode.com/problems/count-of-smaller-numbers-after-self/) 4 | 5 | [geeksforgeeks](https://www.geeksforgeeks.org/counting-inversions/) 6 | 7 | [merge-sort](https://www.geeksforgeeks.org/merge-sort/) 8 | 9 | Formally speaking, two elements a[i] and a[j] form an inversion if a[i] > a[j] and i < j. 10 | 11 | ### (1) Merge-sort based Solution 12 | 13 | #### Explanation 14 | 15 | The smaller numbers on the right of a number are exactly those that jump from its right to its left during a stable sort. So I do mergesort with added tracking of those right-to-left jumps. 16 | 17 | [Explanation-Details](https://leetcode.com/problems/count-of-smaller-numbers-after-self/discuss/76607/C%2B%2B-O(nlogn)-Time-O(n)-Space-MergeSort-Solution-with-Detail-Explanation) 18 | 19 | [C++-solution-in-comment](https://leetcode.com/problems/count-of-smaller-numbers-after-self/discuss/76584/Mergesort-solution) 20 | 21 | #### inplace_merge 22 | 23 | Merges two consecutive sorted ranges: `[first,middle)` and `[middle,last)`, putting the result into the combined sorted range `[first,last)`. 24 | 25 | [cplusplus](http://www.cplusplus.com/reference/algorithm/inplace_merge/?kw=inplace_merge) 26 | 27 | 28 | 29 | ```c++ 30 | // Time Complexity: O(nlogn) 31 | // Space Complexity: O(n) 32 | 33 | class Solution { 34 | typedef vector>::iterator pit; 35 | public: 36 | vector countSmaller(vector& nums) { 37 | int n = nums.size(); 38 | if (n == 0) { 39 | return {}; 40 | } 41 | vector ans(n, 0); 42 | vector> nums_(n); 43 | for (int i=0; i &ans) { 51 | if (end - begin == 1) { 52 | return; 53 | } 54 | 55 | auto mid = begin + (end - begin) / 2; 56 | merge_sort(begin, mid, ans); 57 | merge_sort(mid, end, ans); 58 | for (auto i = begin, j = mid; i != mid; i++) { 59 | while (j != end && i->first > j->first) { 60 | j++; 61 | } 62 | ans[i->second] += (j - mid); 63 | } 64 | 65 | inplace_merge(begin, mid, end); 66 | } 67 | }; 68 | ``` 69 | 70 | 71 | 72 | ## 2. LeetCode 493 [Reverse Pairs](https://leetcode.com/problems/reverse-pairs/) 73 | 74 | ### Similar to LeetCode 315 75 | 76 | ```c++ 77 | // Time Complexity: O(nlogn) 78 | // Space Complexity: O(1) 79 | 80 | class Solution { 81 | typedef vector::iterator vit; 82 | public: 83 | int reversePairs(vector& nums) { 84 | if (nums.size() <= 1) return 0; 85 | int cnt = 0; 86 | merge_sort_and_count(nums.begin(), nums.end(), cnt); 87 | return cnt; 88 | } 89 | 90 | void merge_sort_and_count(vit begin, vit end, int &cnt) { 91 | if (end - begin == 1) { 92 | return; 93 | } 94 | 95 | auto mid = begin + (end - begin) / 2; 96 | merge_sort_and_count(begin, mid, cnt); 97 | merge_sort_and_count(mid, end, cnt); 98 | 99 | for (auto i=begin, j=mid; i != mid; i++) { 100 | // pay attention to overflow here: 2 * *j!!! 101 | while (j != end && *i > 2L * *j) { 102 | j++; 103 | } 104 | cnt += (j - mid); 105 | } 106 | 107 | inplace_merge(begin, mid, end); 108 | } 109 | }; 110 | ``` 111 | 112 | [solution](https://leetcode.com/problems/reverse-pairs/discuss/97287/C++-with-iterators) 113 | 114 | 115 | 116 | ## 3. LeetCode 327 [Count of Range Sum](https://leetcode.com/problems/count-of-range-sum/) 117 | 118 | ### Similar to LeetCode 315 119 | 120 | ```c++ 121 | // Time Complexity: O(nlogn) 122 | // Space Complexity: O(n) 123 | 124 | class Solution { 125 | typedef vector::iterator vit; 126 | public: 127 | int countRangeSum(vector& nums, int lower, int upper) { 128 | int n = nums.size(); 129 | if (n == 0) return 0; 130 | int cnt = 0; 131 | // pay attention to the range of sum (can I use int here?) 132 | vector sums(n+1, 0); 133 | for (int i=1; i<=n; i++) { 134 | sums[i] = nums[i-1] + sums[i-1]; 135 | } 136 | merge_sort_and_cnt(sums.begin(), sums.end(), cnt, lower, upper); 137 | return cnt; 138 | } 139 | 140 | void merge_sort_and_cnt(vit begin, vit end, int &cnt, int &lower, int &upper) { 141 | if (end - begin == 1) { 142 | return; 143 | } 144 | 145 | auto mid = begin + (end - begin) / 2; 146 | merge_sort_and_cnt(begin, mid, cnt, lower, upper); 147 | merge_sort_and_cnt(mid, end, cnt, lower, upper); 148 | for (auto i = begin, j = mid, k = mid; i != mid; i++) { 149 | while (j != end && *j - *i < lower) j++; 150 | while (k != end && *k - *i <= upper) k++; 151 | 152 | cnt += (k - j); 153 | } 154 | 155 | inplace_merge(begin, mid, end); 156 | } 157 | }; 158 | ``` 159 | 160 | [stefanPochmann-solution](https://leetcode.com/problems/count-of-range-sum/discuss/77991/Short-and-simple-O(n-log-n)) 161 | 162 | [notes-website](https://www.cp.eng.chula.ac.th/~piak/teaching/algo/algo2008/count-inv.htm) 163 | 164 | 165 | 166 | ### Consider Binary Indexed Tree Solution of the problems above later... 167 | 168 | 169 | 170 | ## 4. LeetCode 84 [Largest Rectangle in Histogram](https://leetcode.com/problems/largest-rectangle-in-histogram/) 171 | 172 | [segment-tree-range-minimum-query](https://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/) 173 | 174 | A **simple solution** is to one by one consider all bars as starting points and calculate area of all rectangles starting with every bar. Finally return maximum of all possible areas. Time complexity of this solution would be O(n^2). 175 | 176 | We can use **Divide and Conquer** to solve this in O(nLogn) time. The idea is to find the minimum value in the given array. Once we have index of the minimum value, the max area is maximum of following three values. 177 | **a)** Maximum area in left side of minimum value (Not including the min value) 178 | **b)** Maximum area in right side of minimum value (Not including the min value) 179 | **c)** Number of bars multiplied by minimum value. 180 | 181 | How to find the minimum efficiently? [Range Minimum Query using Segment Tree](https://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/) can be used for this. We build segment tree of the given histogram heights. Once the segment tree is built, all [range minimum queries take O(Logn) time](https://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/). So over all complexity of the algorithm becomes: 182 | 183 | Overall Time = Time to build Segment Tree + Time to recursively find maximum area 184 | 185 | [Time to build segment tree is O(n)](https://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/). Let the time to recursively find max area be T(n). It can be written as following. 186 | T(n) = O(Logn) + T(n-1) 187 | The solution of above recurrence is O(nLogn). So overall time is O(n) + O(nLogn) which is O(nLogn). 188 | 189 | ```c++ 190 | // A Divide and Conquer Program to find maximum rectangular area in a histogram 191 | #include 192 | #include 193 | #include 194 | #include 195 | 196 | using namespace std; 197 | 198 | // A utility function to get minimum of two numbers in hist[] 199 | int minVal(vector& hist, int i, int j) 200 | { 201 | if (i == -1) return j; 202 | if (j == -1) return i; 203 | return (hist[i] < hist[j])? i : j; 204 | } 205 | 206 | // A recursive function that constructs Segment Tree for hist[ss..se]. 207 | // si is index of current node in segment tree st 208 | int constructSTUtil(vector& hist, int ss, int se, int *st, int si) 209 | { 210 | // If there is one element in array, store it in current node of 211 | // segment tree and return 212 | if (ss == se) 213 | return (st[si] = ss); 214 | 215 | // If there are more than one elements, then recur for left and 216 | // right subtrees and store the minimum of two values in this node 217 | int mid = ss + (se - ss) / 2; 218 | st[si] = minVal(hist, constructSTUtil(hist, ss, mid, st, si*2+1), 219 | constructSTUtil(hist, mid+1, se, st, si*2+2)); 220 | return st[si]; 221 | } 222 | 223 | /* Function to construct segment tree from given array. This function 224 | allocates memory for segment tree and calls constructSTUtil() to 225 | fill the allocated memory */ 226 | int *constructST(vector& hist) 227 | { 228 | int n = hist.size(); 229 | // Allocate memory for segment tree 230 | int x = (int)(ceil(log2(n))); //Height of segment tree 231 | int max_size = 2*(int)pow(2, x) - 1; //Maximum size of segment tree 232 | int *st = new int[max_size]; 233 | 234 | // Fill the allocated memory st 235 | constructSTUtil(hist, 0, n-1, st, 0); 236 | 237 | // Return the constructed segment tree 238 | return st; 239 | } 240 | 241 | /* A recursive function to get the index of minimum value in a given range of 242 | indexes. The following are parameters for this function. 243 | 244 | hist --> Input array for which segment tree is built 245 | st --> Pointer to segment tree 246 | index --> Index of current node in the segment tree. Initially 0 is 247 | passed as root is always at index 0 248 | ss & se --> Starting and ending indexes of the segment represented by 249 | current node, i.e., st[index] 250 | qs & qe --> Starting and ending indexes of query range */ 251 | int RMQUtil(vector& hist, int *st, int ss, int se, int qs, int qe, int index) 252 | { 253 | // If segment of this node is a part of given range, then return the 254 | // min of the segment 255 | if (qs <= ss && qe >= se) 256 | return st[index]; 257 | 258 | // If segment of this node is outside the given range 259 | if (se < qs || ss > qe) 260 | return -1; 261 | 262 | // If a part of this segment overlaps with the given range 263 | int mid = ss + (se - ss) / 2; 264 | return minVal(hist, RMQUtil(hist, st, ss, mid, qs, qe, 2*index+1), 265 | RMQUtil(hist, st, mid+1, se, qs, qe, 2*index+2)); 266 | } 267 | 268 | // Return index of minimum element in range from index qs (quey start) to 269 | // qe (query end). It mainly uses RMQUtil() 270 | int RMQ(vector& hist, int *st, int qs, int qe) 271 | { 272 | int n = hist.size(); 273 | // Check for erroneous input values 274 | if (qs < 0 || qe > n-1 || qs > qe) 275 | { 276 | cout << "Invalid Input"; 277 | return -1; 278 | } 279 | 280 | return RMQUtil(hist, st, 0, n-1, qs, qe, 0); 281 | } 282 | 283 | // A recursive function to find the maximum rectangular area. 284 | // It uses segment tree 'st' to find the minimum value in hist[l..r] 285 | int getMaxAreaRec(vector& hist, int *st, int l, int r) 286 | { 287 | int n = hist.size(); 288 | // Base cases 289 | if (l > r) return INT_MIN; 290 | if (l == r) return hist[l]; 291 | 292 | // Find index of the minimum value in given range 293 | // This takes O(Logn)time 294 | int m = RMQ(hist, st, l, r); 295 | 296 | /* Return maximum of following three possible cases 297 | a) Maximum area in Left of min value (not including the min) 298 | a) Maximum area in right of min value (not including the min) 299 | c) Maximum area including min */ 300 | return max(max(getMaxAreaRec(hist, st, l, m-1), 301 | getMaxAreaRec(hist, st, m+1, r)), 302 | (r-l+1)*(hist[m]) ); 303 | } 304 | 305 | // The main function to find max area 306 | int getMaxArea(vector& hist) 307 | { 308 | int n = hist.size(); 309 | // Build segment tree from given array. This takes 310 | // O(n) time 311 | int *st = constructST(hist); 312 | 313 | // Use recursive utility function to find the 314 | // maximum area 315 | return getMaxAreaRec(hist, st, 0, n-1); 316 | } 317 | 318 | int main() 319 | { 320 | vector hist = {6, 1, 5, 4, 5, 2, 6}; 321 | cout << "Maximum area is " << getMaxArea(hist); 322 | return 0; 323 | } 324 | ``` 325 | 326 | [geeksforgeeks](https://www.geeksforgeeks.org/largest-rectangular-area-in-a-histogram-set-1/) 327 | 328 | ```c++ 329 | class Solution { 330 | public: 331 | int largestRectangleArea(vector& heights) { 332 | if (heights.empty()) return 0; 333 | int n = heights.size(); 334 | int *st = constructST(heights); 335 | 336 | return getMaxAreaRec(heights, st, 0, n-1); 337 | } 338 | 339 | private: 340 | int minVal(vector& hist, int i, int j) { 341 | if (i == -1) return j; 342 | if (j == -1) return i; 343 | return (hist[i] < hist[j])? i : j; 344 | } 345 | 346 | int constructSTUtil(vector& hist, int ss, int se, int *st, int si) { 347 | if (ss == se) 348 | return (st[si] = ss); 349 | 350 | int mid = ss + (se - ss) / 2; 351 | st[si] = minVal(hist, constructSTUtil(hist, ss, mid, st, si*2+1), 352 | constructSTUtil(hist, mid+1, se, st, si*2+2)); 353 | return st[si]; 354 | } 355 | 356 | int *constructST(vector& hist) { 357 | int n = hist.size(); 358 | int x = (int)(ceil(log2(n))); //Height of segment tree 359 | int max_size = 2*(int)pow(2, x) - 1; //Maximum size of segment tree 360 | int *st = new int[max_size]; 361 | 362 | constructSTUtil(hist, 0, n-1, st, 0); 363 | 364 | return st; 365 | } 366 | 367 | int RMQUtil(vector& hist, int *st, int ss, int se, int qs, int qe, int index) 368 | { 369 | if (qs <= ss && qe >= se) 370 | return st[index]; 371 | 372 | if (se < qs || ss > qe) 373 | return -1; 374 | 375 | int mid = ss + (se - ss) / 2; 376 | return minVal(hist, RMQUtil(hist, st, ss, mid, qs, qe, 2*index+1), 377 | RMQUtil(hist, st, mid+1, se, qs, qe, 2*index+2)); 378 | } 379 | 380 | int getMaxAreaRec(vector& hist, int *st, int l, int r) 381 | { 382 | int n = hist.size(); 383 | if (l > r) return INT_MIN; 384 | if (l == r) return hist[l]; 385 | 386 | int m = RMQUtil(hist, st, 0, n-1, l, r, 0); 387 | 388 | return max(max(getMaxAreaRec(hist, st, l, m-1), 389 | getMaxAreaRec(hist, st, m+1, r)), 390 | (r-l+1)*(hist[m]) ); 391 | } 392 | }; 393 | ``` 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Greedy.md: -------------------------------------------------------------------------------- 1 | # Greedy 2 | 3 | ## 1. LeetCode 406 [Queue Reconstruction by Height](https://leetcode.com/problems/queue-reconstruction-by-height/) 4 | 5 | -Sorting 6 | 7 | -First insert higher person, then we can use the k to insert every lower person 8 | 9 | ```c++ 10 | class Solution { 11 | public: 12 | // Use a custom C++14 polymorphic lambda 13 | vector> reconstructQueue(vector>& people) { 14 | sort(people.begin(), people.end(), [](pair &a, pair &b) { 15 | return a.first > b.first || (a.first == b.first && a.second < b.second); 16 | }); 17 | vector> res; 18 | for(auto p : people) { 19 | res.insert(res.begin()+p.second, p); 20 | } 21 | return res; 22 | } 23 | }; 24 | ``` 25 | 26 | 27 | 28 | ## 2. LeetCode 134 [Gas Station](https://leetcode.com/problems/gas-station/) 29 | 30 | ### (1) Naive Simulation (112ms) 31 | 32 | ```c++ 33 | // Time Complexity: O(n^2) 34 | 35 | class Solution { 36 | public: 37 | int canCompleteCircuit(vector& gas, vector& cost) { 38 | int n = gas.size(); 39 | 40 | for (int i=0; i= cost[i]) { 42 | int tank = 0; 43 | int j = 0; 44 | for (; j& gas, vector& cost) { 72 | int n = gas.size(); 73 | 74 | int min_balance = INT_MAX; 75 | int begin = -1; 76 | int balance = 0; 77 | for (int i=0; i balance) { 80 | begin = i+1; 81 | min_balance = balance; 82 | } 83 | } 84 | 85 | //if (balance < 0) return -1; 86 | //else return begin == n ? 0 : begin; 87 | return (balance < 0) ? -1 : begin % n; 88 | } 89 | }; 90 | ``` 91 | 92 | [proof](https://leetcode.com/problems/gas-station/discuss/42572/Proof-of-%22if-total-gas-is-greater-than-total-cost-there-is-a-solution%22.-C%2B%2B) 93 | 94 | 95 | 96 | ### (3) greedy 2 97 | 98 | The basic idea is every time we start from a station, we go as far as possible by increasing `end` until remaining gas is less than 0. If 'end' finally hits `start` we know we can travel around from 'start'. If we haven't traveled around, we know we cannot start from this station. Then we check the station before our start station if we can start from this station. Repeat until we have checked all stations. 99 | 100 | Note there is a little trick that every time we try to find the next start station, we always to back to extend the distance from start to end so that we can check all stations on the circuit. Otherwise, if we move start forward to decrease the distance from start to end, we are likely to end up with only checking part of the circuit. Another trick is we start from the end of the array so as to avoid some corner cases. 101 | 102 | ```c++ 103 | // Time Complexity: O(n) 104 | class Solution { 105 | public: 106 | int canCompleteCircuit(vector& gas, vector& cost) { 107 | int n = gas.size(); 108 | int sum = 0; 109 | int end = 0, start = n - 1; 110 | while (start >= end) { 111 | if (sum >= 0) { 112 | sum += gas[end] - cost[end]; 113 | end++; 114 | } else { 115 | sum += gas[start] - cost[start]; 116 | start--; 117 | } 118 | } 119 | return sum < 0 ? -1 : (start+1) % n; 120 | } 121 | }; 122 | 123 | // avoid corner case 124 | class Solution { 125 | public: 126 | int canCompleteCircuit(vector& gas, vector& cost) { 127 | int n = gas.size(); 128 | int end = 0, start = n - 1; 129 | int sum = gas[start] - cost[start]; 130 | while (start > end) { 131 | if (sum >= 0) { 132 | sum += gas[end] - cost[end]; 133 | end++; 134 | } else { 135 | start--; 136 | sum += gas[start] - cost[start]; 137 | } 138 | } 139 | return sum < 0 ? -1 : start; 140 | } 141 | }; 142 | ``` 143 | 144 | [solution](https://leetcode.com/problems/gas-station/discuss/42565/My-AC-is-O(1)-space-O(n)-running-time-solution.-Does-anybody-have-posted-this-solution) 145 | 146 | 147 | 148 | ## 3. LeetCode 135 [Candy](https://leetcode.com/problems/candy/) 149 | 150 | First, satisfy left-neighbor relationship, then right, finally combine. 151 | 152 | ```c++ 153 | // Time Complexity: O(n) 154 | // Space Complexity: O(n) 155 | 156 | // two-array for extra space 157 | class Solution { 158 | public: 159 | int candy(vector& ratings) { 160 | int n = ratings.size(); 161 | if (n == 1) return 1; 162 | 163 | vector left2right(n, 1); 164 | vector right2left(n, 1); 165 | 166 | for (int i=1; i ratings[i-1]) { 168 | left2right[i] = left2right[i-1] + 1; 169 | } 170 | } 171 | 172 | for (int i=n-2; i>=0; i--) { 173 | if (ratings[i] > ratings[i+1]) { 174 | right2left[i] = right2left[i+1] + 1; 175 | } 176 | } 177 | 178 | int res = 0; 179 | 180 | for (int i=0; i& ratings) { 193 | int n = ratings.size(); 194 | if (n == 1) return 1; 195 | 196 | vector candies(n, 1); 197 | 198 | for (int i=1; i ratings[i-1]) { 200 | candies[i] = candies[i-1] + 1; 201 | } 202 | } 203 | 204 | int res = candies[n-1]; 205 | for (int i=n-2; i>=0; i--) { 206 | if (ratings[i] > ratings[i+1]) { 207 | candies[i] = max(candies[i] ,candies[i+1] + 1); 208 | } 209 | res += candies[i]; 210 | } 211 | 212 | return res; 213 | } 214 | }; 215 | ``` 216 | 217 | [solution](https://leetcode.com/articles/candy/) 218 | 219 | 220 | 221 | ## 4. LeetCode 358 [Rearrange String k Distance Apart](https://leetcode.com/problems/rearrange-string-k-distance-apart/) 222 | 223 | ### hash map + max-heap + greedy 224 | 225 | ```c++ 226 | // Time Complexity: O(n) (O(n26log26)) 227 | // Space Complexity: O(1) (O(26)) 228 | 229 | class Solution { 230 | public: 231 | string rearrangeString(string s, int k) { 232 | if (k <= 0) return s; 233 | unordered_map dict; 234 | 235 | for (auto c : s) { 236 | dict[c]++; 237 | } 238 | 239 | priority_queue> pq; 240 | for (auto p : dict) { 241 | pq.push({p.second, p.first}); 242 | } 243 | 244 | int n = s.length(); 245 | string res = ""; 246 | while (!pq.empty()) { 247 | vector> cache; 248 | int window = min(k, n); 249 | 250 | for (int i=0; i 1) { 257 | cache.push_back({p.first-1, p.second}); 258 | } 259 | } 260 | 261 | for (auto p : cache) { 262 | pq.push(p); 263 | } 264 | } 265 | 266 | return res; 267 | } 268 | }; 269 | ``` 270 | 271 | 272 | 273 | ## 5. LeetCode 621 [Task Scheduler](https://leetcode.com/problems/task-scheduler/) 274 | 275 | ```c++ 276 | class Solution { 277 | public: 278 | int leastInterval(vector& tasks, int n) { 279 | vector mp(26, 0); 280 | int maxCount = INT_MIN; 281 | for (auto c : tasks) { 282 | mp[c - 'A']++; 283 | maxCount = max(maxCount, mp[c - 'A']); 284 | } 285 | 286 | int res = (n + 1) * (maxCount - 1); 287 | for (auto cnt : mp) { 288 | if (cnt == maxCount) { 289 | res++; 290 | } 291 | } 292 | 293 | return max((int)tasks.size(), res); 294 | } 295 | }; 296 | ``` 297 | 298 | [solution](https://leetcode.com/problems/task-scheduler/discuss/104504/C%2B%2B-8lines-O(n)): explanation in comments 299 | 300 | 301 | 302 | ## 6. LeetCode 942 [DI String Match](https://leetcode.com/problems/di-string-match/) 303 | 304 | ### std::count 305 | 306 | count (InputIterator first, InputIterator last, const T& val); 307 | 308 | **Intuition1** 309 | 310 | If we see say `S[0] == 'I'`, we can always put `0` as the first element, then next number will always be greater no matter what is selected; similarly, if we see `S[0] == 'D'`, we can always put `N` as the first element, then next number will always be less no matter what is selected. So for the rest of the numbers, similarly, If we see say `S[i] == 'I'`, we can always put the **smallest** as the `ith` element or if we see `S[i] == 'D'`, we can always put the **largest** as the `ith` element. 311 | 312 | **Algorithm** 313 | 314 | Keep track of the smallest and largest element we haven't placed. If we see an `'I'`, place the small element; otherwise place the large element. 315 | 316 | **Intuition2** 317 | 318 | First count how many `D` (or `I`) in the string. If the count is `M`, then put `M` in the result array; 319 | 320 | Now there are `M` number (0,1,2,...,M-1) less than `M`, the number of the larger number is equal to the number of `I`; 321 | 322 | Then we can split the number set into 2 parts—— left(0,1,2,...,M-1) and right(M+1, N); 323 | 324 | If `S[i] == 'I'`, we can insert the least in right, otherwise insert the largest one in left. 325 | 326 | ### Solution1 (One Pass): 327 | 328 | ```c++ 329 | // Time Complexity: O(n) 330 | // Space Complexity: O(1) 331 | 332 | class Solution { 333 | public: 334 | vector diStringMatch(string S) { 335 | int n = S.length(); 336 | int low = 0, high = n; 337 | vector res(n+1); 338 | 339 | for (int i=0; i diStringMatch(string S) { 358 | int n = S.length(); 359 | int left = count(S.begin(), S.end(), 'D'); 360 | int right = left; 361 | vector res(n+1); 362 | res[0] = left; 363 | 364 | for (int i=0; i movesToStamp(string stamp, string target) { 381 | vector ans; 382 | int len_t = target.length(); 383 | string questions(len_t, '?'); 384 | 385 | while (target != questions) { 386 | int index = match(stamp, target); 387 | if (index == len_t) return {}; 388 | ans.push_back(index); 389 | } 390 | 391 | reverse(ans.begin(), ans.end()); 392 | return ans; 393 | } 394 | 395 | private: 396 | int match(string &stamp, string &target) { 397 | int len_t = target.length(); 398 | int len_s = stamp.length(); 399 | 400 | for (int start = 0; start < len_t; start++) { 401 | int i = start; // iterator for target 402 | int j = 0; // iterator for stamp 403 | 404 | bool isStamped = false; 405 | while (i < len_t && j < len_s && (target[i] == '?' || target[i] == stamp[j])) { 406 | if (target[i] == stamp[j]) isStamped = true; 407 | i++; 408 | j++; 409 | } 410 | 411 | if (j == len_s && isStamped) { 412 | for (int k = start; k < start+len_s; k++) { 413 | target[k] = '?'; 414 | } 415 | return start; 416 | } 417 | } 418 | 419 | return len_t; 420 | } 421 | }; 422 | ``` 423 | 424 | 425 | 426 | ## 8. LeetCode 984 [String Without AAA or BBB](https://leetcode.com/problems/string-without-aaa-or-bbb/) 427 | 428 | ```c++ 429 | class Solution { 430 | public: 431 | string strWithout3a3b(int A, int B) { 432 | string ans; 433 | 434 | while (A > 0 || B > 0) { 435 | bool printA = false; 436 | int l = ans.length(); 437 | 438 | if (l >= 2 && ans[l-1] == ans[l-2]) { 439 | if (ans[l-1] == 'b') { 440 | printA = true; 441 | } 442 | } else { 443 | if (A >= B) { 444 | printA = true; 445 | } 446 | } 447 | 448 | if (printA) { 449 | A--; 450 | ans += 'a'; 451 | } else { 452 | B--; 453 | ans += 'b'; 454 | } 455 | } 456 | 457 | return ans; 458 | } 459 | }; 460 | ``` 461 | 462 | 463 | 464 | ## 9. LeetCode 659 [Split Array into Consecutive Subsequences](https://leetcode.com/problems/split-array-into-consecutive-subsequences/) 465 | 466 | ```c++ 467 | class Solution { 468 | public: 469 | bool isPossible(vector& nums) { 470 | unordered_map cnt, tails; 471 | for(int &i : nums) cnt[i]++; 472 | for(int &i : nums){ 473 | if(!cnt[i]) continue; 474 | cnt[i]--; 475 | if(tails[i-1] > 0){ 476 | tails[i-1]--; 477 | tails[i]++; 478 | } 479 | else if(cnt[i+1] && cnt[i+2]){ 480 | cnt[i+1]--; 481 | cnt[i+2]--; 482 | tails[i+2]++; 483 | } 484 | else return false; 485 | } 486 | return true; 487 | } 488 | }; 489 | ``` 490 | 491 | [solution](https://leetcode.com/problems/split-array-into-consecutive-subsequences/discuss/106493/C%2B%2B-O(n)-solution-two-pass) 492 | 493 | 494 | 495 | ## 10. LeetCode 763 [Partition Labels](https://leetcode.com/problems/partition-labels/) 496 | 497 | ```c++ 498 | class Solution { 499 | public: 500 | vector partitionLabels(string S) { 501 | vector lastpos(26); 502 | 503 | for (int i=0; i ans; 509 | for (int i=0; i counts(26); 534 | 535 | for (char c: S) counts[c - 'a'] += 100; 536 | for (int i = 0; i < 26; ++i) counts[i] += i; 537 | //Encoded counts[i] = 100*(actual count) + (i) 538 | sort(counts.begin(), counts.end()); 539 | 540 | string ans(N, '.'); 541 | int t = 1; 542 | for (int code : counts) { 543 | int ct = code / 100; 544 | char ch = 'a' + (code % 100); 545 | if (ct > (N+1) / 2) return ""; 546 | 547 | for (int i = 0; i < ct; ++i) { 548 | if (t >= N) t = 0; 549 | ans[t] = ch; 550 | t += 2; 551 | } 552 | } 553 | 554 | return ans; 555 | } 556 | }; 557 | ``` 558 | 559 | 560 | 561 | ## 12. LeetCode 910 [Smallest Range II](https://leetcode.com/problems/smallest-range-ii/) 562 | 563 | ### **Intuition**: 564 | 565 | For each integer `A[i]`, 566 | we may choose either `x = -K` or `x = K`. 567 | 568 | If we add `K` to all `B[i]`, the result won't change. 569 | 570 | It's the same as: 571 | For each integer `A[i]`, we may choose either `x = 0` or `x = 2 * K`. 572 | 573 | ### **Explanation**: 574 | 575 | We sort the `A` first, and we choose to add `x = 0` to all `A[i]`. 576 | Now we have `res = A[n - 1] - A[0]`. 577 | Starting from the smallest of `A`, we add `2 * K` to `A[i]`, 578 | hoping this process will reduce the difference. 579 | 580 | Update the new `mx = max(mx, A[i] + 2 * K)` 581 | Update the new `mn = min(A[i + 1], A[0] + 2 * K)` 582 | Update the `res = min(res, mx - mn)` 583 | 584 | ```c++ 585 | class Solution { 586 | public: 587 | int smallestRangeII(vector& A, int K) { 588 | sort(A.begin(), A.end()); 589 | int n = A.size(), mx = A[n - 1], mn = A[0], res = mx - mn; 590 | 591 | for (int i = 0; i < n - 1; ++i) { 592 | mx = max(mx, A[i] + 2 * K); 593 | mn = min(A[i + 1], A[0] + 2 * K); 594 | res = min(res, mx - mn); 595 | } 596 | return res; 597 | } 598 | }; 599 | ``` 600 | 601 | [solution](https://leetcode.com/problems/smallest-range-ii/discuss/173377/C%2B%2BJavaPython-Add-0-or-2-*-K) 602 | 603 | 604 | 605 | ## 13. LeetCode 881 [Boats to Save People](https://leetcode.com/problems/boats-to-save-people/) 606 | 607 | ### Two Pointer 608 | 609 | ```c++ 610 | class Solution { 611 | public: 612 | int numRescueBoats(vector& people, int limit) { 613 | sort(people.begin(), people.end()); 614 | 615 | int i = 0, j = people.size()-1; 616 | int res = 0; 617 | 618 | while (i <= j) { 619 | res++; 620 | if (people[i] + people[j] <= limit) { 621 | i++; 622 | } 623 | j--; 624 | } 625 | 626 | return res; 627 | } 628 | }; 629 | ``` 630 | 631 | 632 | 633 | ## 14. LeetCode 861 [Score After Flipping Matrix](https://leetcode.com/problems/score-after-flipping-matrix/) 634 | 635 | Assume `A` is `M * N`. 636 | 637 | 1. `A[i][0]` is worth `1 << (N - 1)` points, more than the sum of (`A[i][1] + .. + A[i][N-1]`). 638 | We need to toggle all `A[i][0]` to `1`, here I toggle all lines for `A[i][0] = 0`. 639 | 2. `A[i][j]` is worth `1 << (N - 1 - j)` 640 | For every col, I count the current number of `1`s. 641 | After step 1, `A[i][j]` becomes `1` if `A[i][j] == A[i][0]`. 642 | if `M - cur > cur`, we can toggle this column to get more `1`s. 643 | `max(M, M - cur)` will be the maximum number of `1`s that we can get. 644 | 645 | ```c++ 646 | // Time Complexity: O(MN) 647 | // Space Complexity: O(1) 648 | 649 | class Solution { 650 | public: 651 | int matrixScore(vector>& A) { 652 | if (A.empty() || A[0].empty()) return 0; 653 | int M = A.size(), N = A[0].size(); 654 | int res = (1 << (N - 1)) * M; 655 | 656 | for (int j=1; j mp(26); 8 | for (auto &c : s) { 9 | mp[c - 'a']++; 10 | } 11 | 12 | for (auto &c : t) { 13 | mp[c - 'a']--; 14 | } 15 | 16 | for (auto &i : mp) { 17 | if (i != 0) return false; 18 | } 19 | return true; 20 | } 21 | }; 22 | ``` 23 | 24 | 25 | 26 | ## 2. LeetCode 49 [Group Anagrams](https://leetcode.com/problems/group-anagrams/) 27 | 28 | ```c++ 29 | // Time Complexity: O(NKlogK) 30 | // Space Complexity: O(NK) 31 | // where N is the length of strs, and K is the maximum length of a string in strs. 32 | 33 | class Solution { 34 | public: 35 | vector> groupAnagrams(vector& strs) { 36 | if (strs.empty()) return {}; 37 | vector> res; 38 | 39 | unordered_map> mp; 40 | for (auto &s : strs) { 41 | auto key = s; 42 | sort(key.begin(), key.end()); 43 | mp[key].push_back(s); 44 | } 45 | 46 | for (auto &p : mp) { 47 | res.push_back(p.second); 48 | } 49 | 50 | return res; 51 | } 52 | }; 53 | 54 | // Time Complexity: O(NK) 55 | // Space Complexity: O(NK) 56 | // Time Complexity: O(NK), where N is the length of strs, and K is the maximum length of a 57 | // string in strs. Counting each string is linear in the size of the string, and we count 58 | // every string. 59 | 60 | class Solution { 61 | public: 62 | vector> groupAnagrams(vector& strs) { 63 | if (strs.empty()) return {}; 64 | vector> res; 65 | 66 | unordered_map> mp; 67 | for (auto &s : strs) { 68 | string key = ""; 69 | vector cnts(26, 0); 70 | for (auto &c : s) { 71 | cnts[c - 'a']++; 72 | } 73 | 74 | for (int i=0; i<26; i++) { 75 | key += ("#" + to_string(cnts[i])); 76 | } 77 | 78 | mp[key].push_back(s); 79 | } 80 | 81 | for (auto &p : mp) { 82 | res.push_back(p.second); 83 | } 84 | 85 | return res; 86 | } 87 | }; 88 | ``` 89 | 90 | 91 | 92 | ## 3. LeetCode 266 [Palindrome Permutation](https://leetcode.com/problems/palindrome-permutation/) 93 | 94 | ```c++ 95 | class Solution { 96 | public: 97 | bool canPermutePalindrome(string s) { 98 | unordered_map mp; 99 | int odd = 1; 100 | 101 | for (auto &c : s) { 102 | mp[c]++; 103 | } 104 | 105 | for (auto &p : mp) { 106 | if (p.second % 2) { 107 | if (odd == 0) return false; 108 | odd--; 109 | } 110 | } 111 | return true; 112 | } 113 | }; 114 | ``` 115 | 116 | 117 | 118 | ## 4. LeetCode 267 [Palindrome Permutation II](https://leetcode.com/problems/palindrome-permutation-ii/) 119 | 120 | ### Hashmap + Backtracking 121 | 122 | ```c++ 123 | class Solution { 124 | public: 125 | vector generatePalindromes(string s) { 126 | if (s.empty()) return {}; 127 | vector res; 128 | string mid = "", half = ""; 129 | unordered_map mp; 130 | int odd = 1; 131 | 132 | for (auto &c : s) { 133 | mp[c]++; 134 | } 135 | 136 | for (auto &p : mp) { 137 | if (p.second % 2) { 138 | if (odd == 0) return {}; 139 | odd--; 140 | } 141 | } 142 | 143 | // construct left half 144 | for (auto &p : mp) { 145 | if (p.second % 2) mid += p.first; 146 | half += string(p.second / 2, p.first); 147 | } 148 | 149 | // generate all unique permutation 150 | res = permutations(half); 151 | for (auto &s : res) { 152 | string t(s); 153 | reverse(t.begin(), t.end()); 154 | if (odd == 0) t = mid + t; 155 | s = s + t; 156 | } 157 | return res; 158 | } 159 | 160 | // O(n^2) 161 | vector permutations(string &s) { 162 | vector res; 163 | string t(s); 164 | do { 165 | res.push_back(t); 166 | next_permutation(t.begin(), t.end()); 167 | } while (t != s); 168 | 169 | return res; 170 | } 171 | }; 172 | ``` 173 | 174 | 175 | 176 | ## 5. LeetCode 438 [Find All Anagrams in a String](https://leetcode.com/problems/find-all-anagrams-in-a-string/) 177 | 178 | ### HashTable + Sliding Window 179 | 180 | ```c++ 181 | class Solution { 182 | public: 183 | vector findAnagrams(string s, string p) { 184 | vector res; 185 | int ls = s.length(); 186 | int lp = p.length(); 187 | if (lp > ls) return {}; 188 | 189 | vector mp(26); 190 | for (auto &c : p) { 191 | mp[c - 'a']++; 192 | } 193 | 194 | int cnt = lp, l = 0, r = 0; 195 | 196 | while (r < ls) { 197 | if (mp[s[r++] - 'a']-- > 0) { 198 | cnt--; 199 | } else { 200 | while (mp[s[l++] - 'a']++ >= 0) { 201 | cnt++; 202 | } 203 | } 204 | if (cnt == 0) { 205 | res.push_back(l); 206 | } 207 | } 208 | 209 | return res; 210 | } 211 | }; 212 | ``` 213 | 214 | 215 | 216 | ## 6. LeetCode 734 [Sentence Similarity](https://leetcode.com/problems/sentence-similarity/) 217 | 218 | ```c++ 219 | // N : length of words1(words2) 220 | // P : length of pairs 221 | // Time Complexity: O(N + P) 222 | // Space Complexity: O(P) 223 | 224 | class Solution { 225 | public: 226 | bool areSentencesSimilar(vector& words1, vector& words2, vector> pairs) { 227 | int l1 = words1.size(); 228 | int l2 = words2.size(); 229 | if (l1 != l2) return false; 230 | 231 | unordered_map> mp; 232 | for (auto &p : pairs) { 233 | mp[p.first].insert(p.second); 234 | mp[p.second].insert(p.first); 235 | } 236 | 237 | for (int i=0; isecond; 267 | } 268 | 269 | private: 270 | unordered_map> m; 271 | }; 272 | 273 | /** 274 | * Your TimeMap object will be instantiated and called as such: 275 | * TimeMap* obj = new TimeMap(); 276 | * obj->set(key,value,timestamp); 277 | * string param_2 = obj->get(key,timestamp); 278 | */ 279 | ``` 280 | 281 | 282 | 283 | ## 8. LeetCode 953 [Verifying an Alien Dictionary](https://leetcode.com/problems/verifying-an-alien-dictionary/) 284 | 285 | ```c++ 286 | class Solution { 287 | public: 288 | bool isAlienSorted(vector& words, string order) { 289 | vector mapping(26); 290 | for (int i = 0; i < 26; i++) 291 | mapping[order[i] - 'a'] = i; 292 | for (string &w : words) 293 | for (char &c : w) 294 | c = mapping[c - 'a']; 295 | return is_sorted(words.begin(), words.end()); 296 | } 297 | }; 298 | ``` 299 | 300 | 301 | 302 | ## 9. LeetCode 594 [Longest Harmonious Subsequence](https://leetcode.com/problems/longest-harmonious-subsequence/) 303 | 304 | ```c++ 305 | class Solution { 306 | public: 307 | int findLHS(vector& nums) { 308 | unordered_map mp; 309 | int res = 0; 310 | 311 | for (int &num : nums) { 312 | mp[num]++; 313 | 314 | if (mp.count(num + 1)) { 315 | res = max(res, mp[num] + mp[num+1]); 316 | } 317 | if (mp.count(num - 1)) { 318 | res = max(res, mp[num] + mp[num-1]); 319 | } 320 | } 321 | return res; 322 | } 323 | }; 324 | ``` 325 | 326 | 327 | 328 | ## 10. LeetCode 599 [Minimum Index Sum of Two Lists](https://leetcode.com/problems/minimum-index-sum-of-two-lists/) 329 | 330 | ```c++ 331 | class Solution { 332 | public: 333 | vector findRestaurant(vector& list1, vector& list2) { 334 | unordered_map mp; 335 | 336 | for (int i=0; i res; 341 | int min_sum = INT_MAX, sum; 342 | 343 | for (int j=0; j &A, const pair &B) const { 26 | return A.second > B.second; 27 | } 28 | }; 29 | 30 | public: 31 | vector topKFrequent(vector& nums, int k) { 32 | unordered_map cnts; 33 | for (auto const &i : nums) { 34 | cnts[i]++; 35 | } 36 | 37 | priority_queue, vector>, compare> pq; 38 | 39 | int i = 0; 40 | for (auto const &p : cnts) { 41 | if (i < k) { 42 | pq.push(p); 43 | } else { 44 | if (pq.top().second < p.second) { 45 | pq.pop(); 46 | pq.push(p); 47 | } 48 | } 49 | i++; 50 | } 51 | 52 | vector ans; 53 | while (!pq.empty()) { 54 | ans.push_back(pq.top().first); 55 | pq.pop(); 56 | } 57 | 58 | return ans; 59 | } 60 | }; 61 | 62 | 63 | class Solution { 64 | public: 65 | vector topKFrequent(vector& nums, int k) { 66 | unordered_map cnts; 67 | for (auto i : nums) { 68 | cnts[i]++; 69 | } 70 | 71 | // use lambda function comparator 72 | auto compare = [](pair &A, pair &B) { 73 | return A.second > B.second; 74 | }; 75 | 76 | priority_queue, vector>, decltype(compare)> pq(compare); 77 | 78 | int i = 0; 79 | for (auto p : cnts) { 80 | if (i < k) { 81 | pq.push(p); 82 | } else { 83 | if (pq.top().second < p.second) { 84 | pq.pop(); 85 | pq.push(p); 86 | } 87 | } 88 | i++; 89 | } 90 | 91 | vector ans; 92 | while (!pq.empty()) { 93 | ans.push_back(pq.top().first); 94 | pq.pop(); 95 | } 96 | 97 | return ans; 98 | } 99 | }; 100 | ``` 101 | 102 | 103 | 104 | ## 2. LeetCode 632 [Smallest Range](https://leetcode.com/problems/smallest-range/) 105 | 106 | ```c++ 107 | // Time Complexity: O(nlogk) (k = number of vectors) 108 | // Space Complexity: O(k) 109 | 110 | class Solution { 111 | public: 112 | vector smallestRange(vector>& nums) { 113 | int n = nums.size(); 114 | int max_val = INT_MIN; 115 | int range = INT_MAX; 116 | vector ans(2); 117 | 118 | auto compare = [](const pair> &A, const pair> &B) { 119 | return A.first > B.first; 120 | }; 121 | priority_queue>, vector>>, decltype(compare)> pq(compare); 122 | 123 | for (int i=0; i max_val) { 126 | max_val = nums[i][0]; 127 | } 128 | } 129 | 130 | while (true) { 131 | auto top = pq.top(); 132 | if (max_val - top.first < range) { 133 | range = max_val - top.first; 134 | ans[0] = top.first; 135 | ans[1] = max_val; 136 | } 137 | pq.pop(); 138 | if (top.second.second == nums[top.second.first].size() - 1) { 139 | break; 140 | } 141 | int new_insert = nums[top.second.first][top.second.second+1]; 142 | pq.push({new_insert, {top.second.first, top.second.second+1}}); 143 | if (new_insert > max_val) { 144 | max_val = new_insert; 145 | } 146 | } 147 | 148 | return ans; 149 | } 150 | }; 151 | ``` 152 | 153 | [solution](https://leetcode.com/problems/smallest-range/discuss/104893/Java-Code-using-PriorityQueue.-similar-to-merge-k-array) 154 | 155 | 156 | 157 | ## 3. LeetCode 373 [Find K Pairs with Smallest Sums](https://leetcode.com/problems/find-k-pairs-with-smallest-sums/) 158 | 159 | ```c++ 160 | // Time Complexity: O(klogk) 161 | // Space Complexity: O(k) 162 | 163 | class Solution { 164 | public: 165 | vector> kSmallestPairs(vector& nums1, vector& nums2, int k) { 166 | vector> ans; 167 | int l1 = nums1.size(); 168 | int l2 = nums2.size(); 169 | if (l1 == 0 || l2 == 0 || k <= 0) return ans; 170 | 171 | auto compare = [](pair, int> &A, pair, int> &B) { 172 | return A.second > B.second; 173 | }; 174 | priority_queue, int>, vector, int>>, decltype(compare)> pq(compare); 175 | for (int j=0; j min = pq.top().first; 181 | pq.pop(); 182 | ans.push_back({nums1[min.first], nums2[min.second]}); 183 | if (min.first+1 < l1) { 184 | pq.push({{min.first+1, min.second}, nums1[min.first+1]+nums2[min.second]}); 185 | } 186 | } 187 | 188 | return ans; 189 | } 190 | }; 191 | 192 | // improved version 193 | class Solution { 194 | public: 195 | vector> kSmallestPairs(vector& nums1, vector& nums2, int k) { 196 | vector> ans; 197 | int l1 = nums1.size(); 198 | int l2 = nums2.size(); 199 | if (l1 == 0 || l2 == 0 || k <= 0) return ans; 200 | 201 | auto compare = [&nums1, &nums2](pair &A, pair &B) { 202 | return nums1[A.first] + nums2[A.second] > nums1[B.first] + nums2[B.second]; 203 | }; 204 | priority_queue, vector>, decltype(compare)> pq(compare); 205 | for (int j=0; j min = pq.top(); 211 | pq.pop(); 212 | ans.push_back({nums1[min.first], nums2[min.second]}); 213 | if (min.first+1 < l1) { 214 | pq.push({min.first+1, min.second}); 215 | } 216 | } 217 | 218 | return ans; 219 | } 220 | }; 221 | ``` 222 | 223 | [solution](https://leetcode.com/problems/find-k-pairs-with-smallest-sums/discuss/84551/simple-Java-O(KlogK)-solution-with-explanation) 224 | 225 | 226 | 227 | ## 4. LeetCode 378 [Kth Smallest Element in a Sorted Matrix](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/) 228 | 229 | ### (1) max-heap (priority_queue) 230 | 231 | ```c++ 232 | // max-heap 233 | // Time Complexity: O(n^2logk) 234 | // Space Complexity: O(1) 235 | 236 | int kthSmallest(vector>& matrix, int k) { 237 | int n = (int) matrix.size(); 238 | priority_queue> pq; 239 | int l = n * n; 240 | for (int i=0; i cur) { 246 | pq.pop(); 247 | pq.push(cur); 248 | } 249 | } 250 | return pq.top(); 251 | } 252 | ``` 253 | 254 | 255 | 256 | ### (2) min-heap (priority_queue) 257 | 258 | ```c++ 259 | // min-heap 260 | // Time Complexity: O(klogn) (n: row of the matrix) 261 | // Space Complexity: O(n) 262 | 263 | struct compare { 264 | bool operator()(const pair> &A, const pair> &B) { 265 | return A.first > B.first; 266 | } 267 | }; 268 | 269 | int kthSmallest2(vector>& matrix, int k) { 270 | int n = (int) matrix.size(); 271 | priority_queue>, vector>>, greater>>> pq; 272 | 273 | for (int i=0; i 1) { 279 | int i = pq.top().second.first; 280 | int j = pq.top().second.second; 281 | pq.pop(); 282 | if (j < n-1) { 283 | // pq.push(make_pair(matrix[i][j+1], make_pair(i, j+1))); 284 | pq.push({ matrix[i][j+1], { i, j+1 }}); 285 | } 286 | } 287 | return pq.top().first; 288 | } 289 | ``` 290 | 291 | 292 | 293 | ## 5. LeetCode 692 [Top K Frequent Words](https://leetcode.com/problems/top-k-frequent-words/) 294 | 295 | ```c++ 296 | // Time Complexity: O(nlogk) 297 | // Space Complexity: O(n) 298 | 299 | // original 300 | class Solution { 301 | private: 302 | struct compare { 303 | bool operator() (const pair& a, const pair& b) const { 304 | return a.second == b.second ? a.first < b.first : a.second > b.second; 305 | } 306 | }; 307 | 308 | public: 309 | vector topKFrequent(vector& words, int k) { 310 | unordered_map um; 311 | vector res; 312 | for (auto word : words) { 313 | um[word]++; 314 | } 315 | priority_queue, vector>, compare> pq; 316 | for (auto p : um) { 317 | if (pq.size() < k) { 318 | pq.emplace(p); 319 | } else { 320 | if (p.second > pq.top().second || (p.second == pq.top().second && p.first < pq.top().first)) { 321 | pq.pop(); 322 | pq.emplace(p); 323 | } 324 | } 325 | } 326 | while (!pq.empty()) { 327 | res.push_back(pq.top().first); 328 | pq.pop(); 329 | } 330 | reverse(res.begin(), res.end()); 331 | return res; 332 | } 333 | }; 334 | 335 | // improved version (using lambda, some optimization) 336 | class Solution { 337 | public: 338 | vector topKFrequent(vector& words, int k) { 339 | unordered_map um; 340 | vector res; 341 | for (const auto &word : words) { 342 | um[word]++; 343 | } 344 | 345 | auto compare = [](pair& a, pair& b) { 346 | return a.second == b.second ? a.first < b.first : a.second > b.second; 347 | }; 348 | priority_queue, vector>, decltype(compare)> pq(compare); 349 | for (const auto &p : um) { 350 | if (pq.size() < k) { 351 | pq.push(p); 352 | } else { 353 | if (p.second > pq.top().second || (p.second == pq.top().second && p.first < pq.top().first)) { 354 | pq.pop(); 355 | pq.push(p); 356 | } 357 | } 358 | } 359 | while (!pq.empty()) { 360 | res.push_back(pq.top().first); 361 | pq.pop(); 362 | } 363 | reverse(res.begin(), res.end()); 364 | return res; 365 | } 366 | }; 367 | ``` 368 | 369 | 370 | 371 | ## 6. LeetCode 23 [Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/) 372 | 373 | ```c++ 374 | /** 375 | * Definition for singly-linked list. 376 | * struct ListNode { 377 | * int val; 378 | * ListNode *next; 379 | * ListNode(int x) : val(x), next(NULL) {} 380 | * }; 381 | */ 382 | class Solution { 383 | struct comparison { 384 | bool operator() (const ListNode* l1, const ListNode* l2) const { 385 | return l1->val > l2->val; 386 | } 387 | }; 388 | 389 | public: 390 | ListNode* mergeKLists(vector& lists) { 391 | priority_queue, comparison> pq; 392 | for(auto l : lists) { 393 | if(l) pq.push(l); 394 | } 395 | ListNode* res = new ListNode(0); 396 | ListNode* iter = res; 397 | while(!pq.empty()) { 398 | iter->next = pq.top(); 399 | pq.pop(); 400 | iter = iter->next; 401 | if(iter->next) { 402 | pq.push(iter->next); 403 | } 404 | } 405 | return res->next; 406 | } 407 | }; 408 | ``` 409 | 410 | 411 | 412 | ## 7. LeetCode 703 413 | 414 | ```c++ 415 | 416 | ``` 417 | 418 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/LinkedList.md: -------------------------------------------------------------------------------- 1 | # <1>Two Pointers Problem (Fast + Slow) 2 | 3 | ## 1. LeetCode 141 [Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/) 4 | 5 | ```c++ 6 | // Time Complexity: O(n) 7 | // Space Complexity: O(1) 8 | 9 | /** 10 | * Definition for singly-linked list. 11 | * struct ListNode { 12 | * int val; 13 | * ListNode *next; 14 | * ListNode(int x) : val(x), next(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | bool hasCycle(ListNode *head) { 20 | if (!head || !head->next) { return false;} 21 | ListNode* fast = head; 22 | ListNode* slow = head; 23 | while (fast && fast->next) { 24 | fast = fast->next->next; 25 | slow = slow->next; 26 | if (slow == fast) { 27 | return true; 28 | } 29 | } 30 | return false; 31 | } 32 | }; 33 | ``` 34 | 35 | 36 | 37 | ## 2. LeetCode 142 [Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/) 38 | 39 | ```c++ 40 | // Time Complexity: O(n) 41 | // Space Complexity: O(1) 42 | 43 | /** 44 | * Definition for singly-linked list. 45 | * struct ListNode { 46 | * int val; 47 | * ListNode *next; 48 | * ListNode(int x) : val(x), next(NULL) {} 49 | * }; 50 | */ 51 | class Solution { 52 | public: 53 | ListNode *detectCycle(ListNode *head) { 54 | if (!head || !head->next) { return NULL;} 55 | ListNode* fast = head; 56 | ListNode* slow = head; 57 | ListNode* p = head; 58 | while (fast && fast->next) { 59 | fast = fast->next->next; 60 | slow = slow->next; 61 | if (fast == slow) { 62 | if (p == slow) { 63 | return p; 64 | } else { 65 | while (p) { 66 | p = p->next; 67 | slow = slow->next; 68 | if (p == slow) { 69 | return p; 70 | } 71 | } 72 | } 73 | } 74 | } 75 | return NULL; 76 | } 77 | }; 78 | ``` 79 | 80 | 81 | 82 | ### Related: 83 | 84 | ### LeetCode 287 [Find the Duplicate Number](https://leetcode.com/problems/find-the-duplicate-number/) 85 | 86 | #### Explanation 87 | 88 | Change the Problem to find a cycle in the linkedlist! 89 | 90 | e.g. nums=[1,3,4,2,2] 91 | 92 | => nodes = [0=>1, 1=>3, 2=>4, 3=>2, 4=>2] 93 | 94 | => 0->1->3->2->4->2 95 | 96 | 97 | 98 | e.g. [3,1,3,4,2] => 0->3->4->2->3 + 1->1 99 | 100 | **Thus, what we need to do is to find the circle and get the first node of the circle, which is the duplicate number. And in this question, the cycle must happen after the first node.** 101 | 102 | ```c++ 103 | // Time Complexity: O(n) 104 | // Space Complexity: O(1) 105 | 106 | class Solution { 107 | public: 108 | int findDuplicate(vector& nums) { 109 | int len = nums.size(); // len should be larger than 1 110 | if (len < 2) return -1; 111 | if (len == 2) return nums[0]; 112 | int slow = nums[0], fast = nums[nums[0]]; 113 | while (slow != fast) { 114 | slow = nums[slow]; 115 | fast = nums[nums[fast]]; 116 | } 117 | 118 | int p = 0; 119 | while (nums[p] != nums[slow]) { 120 | p = nums[p]; 121 | slow = nums[slow]; 122 | } 123 | return nums[p]; 124 | } 125 | }; 126 | ``` 127 | 128 | 129 | 130 | ## 3. LeetCode 160 [Intersection of Two Linked Lists](https://leetcode.com/problems/intersection-of-two-linked-lists/) 131 | 132 | ### (1) Two Pointers 133 | 134 | ```c++ 135 | /** 136 | * Definition for singly-linked list. 137 | * struct ListNode { 138 | * int val; 139 | * ListNode *next; 140 | * ListNode(int x) : val(x), next(NULL) {} 141 | * }; 142 | */ 143 | class Solution { 144 | public: 145 | ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { 146 | if (!headA || !headB) return NULL; 147 | 148 | ListNode* iterA = headA; 149 | ListNode* iterB = headB; 150 | 151 | while (iterA->next && iterB->next) { 152 | iterA = iterA->next; 153 | iterB = iterB->next; 154 | } 155 | 156 | int balance = 0; 157 | if (!iterA->next) { 158 | while (iterB->next) { 159 | iterB = iterB->next; 160 | balance++; 161 | } 162 | } else { 163 | while (iterA->next) { 164 | iterA = iterA->next; 165 | balance--; 166 | } 167 | } 168 | 169 | if (iterA != iterB) return NULL; 170 | iterA = headA; 171 | iterB = headB; 172 | if (balance > 0) { 173 | while (balance--) { 174 | iterB = iterB->next; 175 | } 176 | } else { 177 | while (balance++) { 178 | iterA = iterA->next; 179 | } 180 | } 181 | 182 | while (iterA != iterB) { 183 | iterA = iterA->next; 184 | iterB = iterB->next; 185 | } 186 | return iterA; 187 | } 188 | }; 189 | ``` 190 | 191 | [solution](https://leetcode.com/articles/intersection-of-two-linked-lists/) 192 | 193 | 194 | 195 | # <2> General Linked List Problems 196 | 197 | ## 1. LeetCode 138 [Copy List with Random Pointer](https://leetcode.com/problems/copy-list-with-random-pointer/) 198 | 199 | ```c++ 200 | /** 201 | * Definition for singly-linked list with a random pointer. 202 | * struct RandomListNode { 203 | * int label; 204 | * RandomListNode *next, *random; 205 | * RandomListNode(int x) : label(x), next(NULL), random(NULL) {} 206 | * }; 207 | */ 208 | class Solution { 209 | public: 210 | RandomListNode *copyRandomList(RandomListNode *head) { 211 | if (!head) { return NULL;} 212 | RandomListNode* dummy = head; 213 | 214 | // copy the list 215 | while (dummy != NULL) { 216 | RandomListNode* copy = new RandomListNode(dummy->label); 217 | copy->next = dummy->next; 218 | dummy->next = copy; 219 | dummy = copy->next; 220 | } 221 | 222 | // assign random pointers for the copy nodes; 223 | dummy = head; 224 | while (dummy != NULL) { 225 | if (dummy->random != NULL) { 226 | dummy->next->random = dummy->random->next; 227 | } 228 | dummy = dummy->next->next; 229 | } 230 | 231 | // restore the original and extract the copy 232 | dummy = head; 233 | RandomListNode *copyHead = new RandomListNode(0); 234 | RandomListNode *copyDummy = copyHead; 235 | while (dummy != NULL) { 236 | copyDummy->next = dummy->next; 237 | copyDummy = copyDummy->next; 238 | // restore 239 | dummy->next = dummy->next->next; 240 | dummy = dummy->next; 241 | } 242 | return copyHead->next; 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 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Math.md: -------------------------------------------------------------------------------- 1 | ## 1. LeetCode 836 [Rectangle Overlap](https://leetcode.com/problems/rectangle-overlap/) 2 | 3 | ```c++ 4 | class Solution { 5 | public: 6 | bool isRectangleOverlap(vector& rec1, vector& rec2) { 7 | return (min(rec1[2], rec2[2]) > max(rec1[0], rec2[0]) 8 | && min(rec1[3], rec2[3]) > max(rec1[1], rec2[1])); 9 | } 10 | }; 11 | ``` 12 | 13 | 14 | 15 | ## 2. LeetCode 223 [Rectangle Area](https://leetcode.com/problems/rectangle-area/) 16 | 17 | ```c++ 18 | class Solution { 19 | public: 20 | int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) { 21 | long width = (long)min(C, G) - (long)max(A, E); 22 | long height = (long)min(D, H) - (long)max(B, F); 23 | 24 | long area = (C - A) * (D - B) + (G - E) * (H - F); 25 | 26 | if (width > 0 && height > 0) { 27 | return area - width * height; 28 | } 29 | 30 | return area; 31 | } 32 | }; 33 | ``` 34 | 35 | 36 | 37 | ## 3. LeetCode 991 [Broken Calculator](https://leetcode.com/problems/broken-calculator/) 38 | 39 | ```c++ 40 | class Solution { 41 | public: 42 | int brokenCalc(int X, int Y) { 43 | int ans = 0; 44 | 45 | while (Y > X) { 46 | ans++; 47 | if (Y % 2 == 1) 48 | Y++; 49 | else 50 | Y /= 2; 51 | } 52 | 53 | return ans + X - Y; 54 | } 55 | }; 56 | ``` 57 | 58 | 59 | 60 | ## 4. LeetCode 400 [Nth Digit](https://leetcode.com/problems/nth-digit/) 61 | 62 | ```c++ 63 | class Solution { 64 | public: 65 | int findNthDigit(int n) { 66 | int len = 1; 67 | long count = 9; 68 | int start = 1; 69 | 70 | while (n > len * count) { 71 | n -= len * count; 72 | len += 1; 73 | count *= 10; 74 | start *= 10; 75 | } 76 | 77 | start += (n - 1) / len; 78 | string s = to_string(start); 79 | 80 | return (s[(n-1) % len]) - '0'; 81 | } 82 | }; 83 | ``` 84 | 85 | 86 | 87 | ## 5. LeetCode 573 [Squirrel Simulation](https://leetcode.com/problems/squirrel-simulation/) 88 | 89 | ```c++ 90 | class Solution { 91 | public: 92 | int minDistance(int height, int width, vector& tree, vector& squirrel, vector>& nuts) { 93 | int total_dist = 0, d = INT_MIN; 94 | 95 | for (auto nut : nuts) { 96 | total_dist += distance(nut, tree) * 2; 97 | d = max(d, distance(nut, tree) - distance(nut, squirrel)); 98 | } 99 | 100 | return total_dist - d; 101 | } 102 | 103 | private: 104 | int distance(vector &a, vector &b) { 105 | return abs(a[0] - b[0]) + abs(a[1] - b[1]); 106 | } 107 | }; 108 | ``` 109 | 110 | 111 | 112 | ## 6. LeetCode 869 [Reordered Power of 2](https://leetcode.com/problems/reordered-power-of-2/) 113 | 114 | ```c++ 115 | class Solution { 116 | public: 117 | bool reorderedPowerOf2(int N) { 118 | vector A = count(N); 119 | 120 | for (int i=0; i<31; ++i) { 121 | if (equal(A.begin(), A.end(), count(1 << i).begin())) { 122 | return true; 123 | } 124 | } 125 | 126 | return false; 127 | } 128 | 129 | private: 130 | vector count(int N) { 131 | vector res(10); 132 | while (N > 0) { 133 | res[N % 10]++; 134 | N /= 10; 135 | } 136 | 137 | return res; 138 | } 139 | }; 140 | ``` 141 | 142 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Stack.md: -------------------------------------------------------------------------------- 1 | # Stack 2 | 3 | ## 1. LeetCode 394 [Decode String](https://leetcode.com/problems/decode-string/) 4 | 5 | ### (1) one stack 6 | 7 | ```c++ 8 | class Solution { 9 | public: 10 | string decodeString(string s) { 11 | int len = s.length(); 12 | string ans = ""; 13 | stack st; 14 | 15 | for (int i=0; i intStack = new Stack<>(); 58 | Stack strStack = new Stack<>(); 59 | StringBuilder cur = new StringBuilder(); 60 | int k = 0; 61 | for (char ch : s.toCharArray()) { 62 | if (Character.isDigit(ch)) { 63 | k = k * 10 + ch - '0'; 64 | } else if ( ch == '[') { 65 | intStack.push(k); 66 | strStack.push(cur); 67 | cur = new StringBuilder(); 68 | k = 0; 69 | } else if (ch == ']') { 70 | StringBuilder tmp = cur; 71 | cur = strStack.pop(); 72 | for (k = intStack.pop(); k > 0; --k) cur.append(tmp); 73 | } else cur.append(ch); 74 | } 75 | return cur.toString(); 76 | } 77 | } 78 | ``` 79 | 80 | [solution](https://leetcode.com/problems/decode-string/discuss/87534/Simple-Java-Solution-using-Stack) 81 | 82 | ```c++ 83 | // c++ version 84 | class Solution { 85 | public: 86 | string decodeString(string s) { 87 | int len = s.length(); 88 | string cur = ""; 89 | stack strSt; 90 | stack intSt; 91 | 92 | int k = 0; // used for building number 93 | 94 | for (auto const &c : s) { 95 | if (isdigit(c)) { 96 | k = k * 10 + c - '0'; 97 | } else if (c == '[') { 98 | intSt.push(k); 99 | strSt.push(cur); 100 | cur.clear(); 101 | k = 0; 102 | } else if (c == ']') { 103 | string tmp = cur; // current repeated string 104 | cur = strSt.top(); // get the prefix 105 | strSt.pop(); 106 | for (int i=intSt.top(); i>0; i--) { 107 | cur += tmp; 108 | } 109 | intSt.pop(); 110 | } else { 111 | cur.push_back(c); 112 | } 113 | } 114 | 115 | return cur; 116 | } 117 | }; 118 | ``` 119 | 120 | 121 | 122 | ## 2. LeetCode 150 [Evaluate Reverse Polish Notation](https://leetcode.com/problems/evaluate-reverse-polish-notation/) 123 | 124 | ### (1) original 125 | 126 | ```c++ 127 | class Solution { 128 | public: 129 | int evalRPN(vector& tokens) { 130 | stack st; 131 | for (auto const &t : tokens) { 132 | if (t == "+") { 133 | int b = st.top(); 134 | st.pop(); 135 | int a = st.top(); 136 | st.pop(); 137 | st.push(a + b); 138 | } else if (t == "-") { 139 | int b = st.top(); 140 | st.pop(); 141 | int a = st.top(); 142 | st.pop(); 143 | st.push(a - b); 144 | } else if (t == "*") { 145 | int b = st.top(); 146 | st.pop(); 147 | int a = st.top(); 148 | st.pop(); 149 | st.push(a * b); 150 | } else if (t == "/") { 151 | int b = st.top(); 152 | st.pop(); 153 | int a = st.top(); 154 | st.pop(); 155 | st.push(a / b); 156 | } else { 157 | st.push(stoi(t)); 158 | } 159 | } 160 | return st.top(); 161 | } 162 | }; 163 | ``` 164 | 165 | 166 | 167 | ### std::function 168 | 169 | #include 170 | 171 | [cppreference](https://zh.cppreference.com/w/cpp/utility/functional/function) 172 | 173 | ### (2) fancy 174 | 175 | ```c++ 176 | class Solution { 177 | public: 178 | int evalRPN(vector& tokens) { 179 | unordered_map> mp{ 180 | {"+", [] (const int& a, const int& b) { return a + b;}}, 181 | {"-", [] (const int& a, const int& b) { return a - b;}}, 182 | {"*", [] (const int& a, const int& b) { return a * b;}}, 183 | {"/", [] (const int& a, const int& b) { return a / b;}} 184 | }; 185 | stack st; 186 | for (auto const &t : tokens) { 187 | if (mp.count(t)) { 188 | int b = st.top(); 189 | st.pop(); 190 | int a = st.top(); 191 | st.pop(); 192 | st.push(mp[t](a, b)); 193 | } else { 194 | st.push(stoi(t)); 195 | } 196 | } 197 | return st.top(); 198 | } 199 | }; 200 | ``` 201 | 202 | [solution](https://leetcode.com/problems/evaluate-reverse-polish-notation/discuss/47514/Fancy-C%2B%2B-lambda-expression-solution) 203 | 204 | 205 | 206 | ## 3. LeetCode 84 [Largest Rectangle in Histogram](https://leetcode.com/problems/largest-rectangle-in-histogram/) 207 | 208 | [geeksforgeeks](https://www.geeksforgeeks.org/largest-rectangle-under-histogram/) 209 | 210 | ### Explanation 211 | 212 | **For every bar ‘x’, we calculate the area with ‘x’ as the smallest bar in the rectangle. If we calculate such area for every bar ‘x’ and find the maximum of all areas, our task is done.** How to calculate area with ‘x’ as smallest bar? We need to **know index of the first smaller (smaller than ‘x’) bar on left of ‘x’ and index of first smaller bar on right of ‘x’.** Let us call these indexes as ‘left index’ and ‘right index’ respectively. 213 | 214 | We traverse all bars from left to right, maintain a stack of bars. Every bar is pushed to stack once. A bar is popped from stack when a bar of smaller height is seen. When a bar is popped, we calculate the area with the popped bar as smallest bar. How do we get left and right indexes of the popped bar – the current index tells us the ‘right index’ and index of previous item in stack is the ‘left index’. Following is the complete algorithm. 215 | 216 | **1)** Create an empty stack. 217 | 218 | **2)** Start from first bar, and do following for every bar ‘hist[i]’ where ‘i’ varies from 0 to n-1. 219 | ……**a)** If stack is empty or hist[i] is higher than the bar at top of stack, then push ‘i’ to stack. 220 | ……**b)** If this bar is smaller than the top of stack, then keep removing the top of stack while top of the stack is greater. Let the removed bar be hist[tp]. Calculate area of rectangle with hist[tp] as smallest bar. For hist[tp], the ‘left index’ is previous (previous to tp) item in stack and ‘right index’ is ‘i’ (current index). 221 | 222 | **3)** If the stack is not empty, then one by one remove all bars from stack and do step 2.b for every removed bar. 223 | 224 | Following is implementation of the above algorithm. 225 | 226 | ```c++ 227 | // Time Complexity: O(n) Since every bar is pushed and popped only once, the time complexity // of this method is O(n). 228 | // Space Complexity: O(n) 229 | 230 | // corner case: repeated bar with the same height 231 | // e.g. 1,3,4,4,4,4,2,3,5 232 | // when we visit the second 4, we can pop the first 4 to make sure the bars stored in stack 233 | // are always in increasing order. 234 | // Thus, we treat the first 4 bar like a higher bar because actually we only need to 235 | // calculate the area with the last '4' as smallest bar. 236 | 237 | class Solution { 238 | public: 239 | int largestRectangleArea(vector& heights) { 240 | if (heights.empty()) return 0; 241 | int n = heights.size(); 242 | stack st; // used for store the indexes of the histograms 243 | int left = -1, right = 0; // left bound index & right bound index 244 | int res_area = 0; 245 | 246 | for (int i=0; i heights[st.top()]) { 248 | st.push(i); 249 | } else { 250 | while (!st.empty() && heights[i] <= heights[st.top()]) { 251 | int top = st.top(); 252 | st.pop(); 253 | left = !st.empty() ? st.top() : -1; 254 | right = i; 255 | res_area = max(res_area, heights[top] * (right - left - 1)); 256 | } 257 | st.push(i); 258 | } 259 | } 260 | 261 | right = n; 262 | while (!st.empty()) { 263 | int top = st.top(); 264 | st.pop(); 265 | left = !st.empty() ? st.top() : -1; 266 | res_area = max(res_area, heights[top] * (right - left - 1)); 267 | } 268 | 269 | return res_area; 270 | } 271 | }; 272 | 273 | // shorter version 274 | class Solution { 275 | public: 276 | int largestRectangleArea(vector& heights) { 277 | if (heights.empty()) return 0; 278 | int n = heights.size(); 279 | // Create an empty stack. The stack holds indexes 280 | // of heights array. The bars stored in stack are 281 | // always in increasing order of their heights. 282 | stack st; 283 | int top; // To store top of stack 284 | int max_area = 0; // Initalize max area 285 | 286 | // Run through all bars of given histogram 287 | int i = 0; 288 | while (i < n) { 289 | // If this bar is higher than the bar on top 290 | // stack, push it to stack 291 | if (st.empty() || heights[i] > heights[st.top()]) { 292 | st.push(i++); 293 | } else { 294 | // If this bar is lower than or equal to the top bar of stack, 295 | // then calculate area of rectangle with stack 296 | // top as the smallest (or minimum height) bar. 297 | // 'i' is 'right index' for the top and element 298 | // before top in stack is 'left index' 299 | while (!st.empty() && heights[i] <= heights[st.top()]) { 300 | top = st.top(); 301 | st.pop(); 302 | // Calculate the area with hist[tp] stack 303 | // as smallest bar 304 | // and update max area, if needed 305 | max_area = max(max_area, heights[top] * (st.empty() ? i : i - st.top() - 1)); 306 | } 307 | st.push(i++); 308 | } 309 | } 310 | 311 | // Now pop the remaining bars from stack and calculate 312 | // area with every popped bar as the smallest bar 313 | // same as above 314 | while (!st.empty()) { 315 | top = st.top(); 316 | st.pop(); 317 | max_area = max(max_area, heights[top] * (st.empty() ? i : i - st.top() - 1)); 318 | } 319 | 320 | return max_area; 321 | } 322 | }; 323 | ``` 324 | 325 | 326 | 327 | ## 4. LeetCode 20 [Valid Parentheses](https://leetcode.com/problems/valid-parentheses/) 328 | 329 | ### 12.7 Google-Mock-Problem 330 | 331 | ### (1) Intuitive 332 | 333 | Only push the open brackets into the stack, and check whether every closing brackets are matched with former open brackets. 334 | 335 | If stack is empty and current visited character is close brackets, then return false. 336 | 337 | Finally, check if the stack is empty, if so, return true! 338 | 339 | ```c++ 340 | // Time Complexity: O(n) 341 | // Space Complexity: O(n) 342 | 343 | class Solution { 344 | public: 345 | bool isValid(string s) { 346 | if (s.empty()) return true; 347 | 348 | stack st; 349 | for (auto c : s) { 350 | if (st.empty() && (c == ')' || c == ']' || c == '}')) { 351 | return false; 352 | } 353 | if (st.empty() || c == '(' || c == '[' || c == '{') { 354 | st.push(c); 355 | } else { 356 | if (isMatch(st.top(), c)) { 357 | st.pop(); 358 | } else { 359 | return false; 360 | } 361 | } 362 | } 363 | return st.empty(); 364 | } 365 | 366 | bool isMatch(char a, char b) { 367 | if (a == '(') { 368 | return b == ')'; 369 | } else if (a == '[') { 370 | return b == ']'; 371 | } else if (a == '{') { 372 | return b == '}'; 373 | } 374 | return false; 375 | } 376 | }; 377 | ``` 378 | 379 | 380 | 381 | ### (2) Better 382 | 383 | When visiting open brackets, push its closing pair into the stack; 384 | 385 | If stack is empty and current visited character is close bracket, return false; 386 | 387 | If current visited character is not equal to the top character in stack, return false; 388 | 389 | Otherwise, pop the top character. 390 | 391 | Finally, check if the stack is empty, if so, return true! 392 | 393 | ```c++ 394 | // Time Complexity: O(n) 395 | // Space Complexity: O(n) 396 | 397 | class Solution { 398 | public: 399 | bool isValid(string s) { 400 | if (s.empty()) return true; 401 | stack st; 402 | 403 | for (auto const &c : s) { 404 | if (c == '(') { 405 | st.push(')'); 406 | } else if (c == '{') { 407 | st.push('}'); 408 | } else if (c == '[') { 409 | st.push(']'); 410 | } else { 411 | if (st.empty() || c != st.top()) { 412 | return false; 413 | } 414 | st.pop(); 415 | } 416 | } 417 | 418 | return st.empty(); 419 | } 420 | }; 421 | ``` 422 | 423 | 424 | 425 | ## 5. LeetCode 32 [Longest Valid Parentheses](https://leetcode.com/problems/longest-valid-parentheses/) 426 | 427 | ```c++ 428 | // Time Complexity: O(n) 429 | // Space Complexity: O(n) 430 | 431 | class Solution { 432 | public: 433 | int longestValidParentheses(string s) { 434 | int n = s.length(); 435 | stack st; // store the index 436 | 437 | for (int i=0; i stk; // idx 472 | 473 | int res =0, max_len = 0; 474 | int left_most = -1; 475 | for (int i=0; i < s.size(); i++) { 476 | if (s[i] == '(') { 477 | stk.push(i); 478 | } else { 479 | if (stk.empty()) { 480 | left_most = i; 481 | } else { 482 | stk.pop(); 483 | if (stk.empty()) { 484 | max_len = max(max_len, i - left_most); 485 | } else { 486 | max_len = max(max_len, i - stk.top()); 487 | } 488 | } 489 | } 490 | } 491 | return max_len; 492 | } 493 | }; 494 | ``` 495 | 496 | [stack-solution](https://leetcode.com/problems/longest-valid-parentheses/discuss/14126/My-O(n)-solution-using-a-stack) 497 | 498 | 499 | 500 | ## 6. LeetCode 962 [Maximum Width Ramp](https://leetcode.com/problems/maximum-width-ramp/) 501 | 502 | ```c++ 503 | class Solution { 504 | public: 505 | int maxWidthRamp(vector& A) { 506 | stack s; 507 | int res = 0, n = A.size(); 508 | for (int i = 0; i < n; ++i) 509 | if (s.empty() || A[s.top()] > A[i]) 510 | s.push(i); 511 | for (int i = n - 1; i > res; --i) 512 | while (!s.empty() && A[s.top()] <= A[i]) 513 | res = max(res, i - s.top()), s.pop(); 514 | return res; 515 | } 516 | }; 517 | ``` 518 | 519 | [solution](https://leetcode.com/problems/maximum-width-ramp/discuss/208348/JavaC%2B%2BPython-O(N)-Using-Stack) 520 | 521 | 522 | 523 | ## 7. LeetCode 42 [Trapping Rain Water](https://leetcode.com/problems/trapping-rain-water/) 524 | 525 | ### Monotonic Stack 526 | 527 | ```c++ 528 | class Solution { 529 | public: 530 | int trap(vector& height) { 531 | int ans = 0, current = 0; 532 | stack st; 533 | while (current < height.size()) { 534 | while (!st.empty() && height[current] > height[st.top()]) { 535 | int top = st.top(); 536 | st.pop(); 537 | if (st.empty()) 538 | break; 539 | int distance = current - st.top() - 1; 540 | int bounded_height = min(height[current], height[st.top()]) - height[top]; 541 | ans += distance * bounded_height; 542 | } 543 | st.push(current++); 544 | } 545 | return ans; 546 | } 547 | }; 548 | ``` 549 | 550 | 551 | 552 | ## 8. LeetCode 496 [Next Greater Element I](https://leetcode.com/problems/next-greater-element-i/) 553 | 554 | ### Monotonic Stack 555 | 556 | ```c++ 557 | class Solution { 558 | public: 559 | vector nextGreaterElement(vector& findNums, vector& nums) { 560 | stack s; 561 | unordered_map m; 562 | for (int n : nums) { 563 | while (s.size() && s.top() < n) { 564 | m[s.top()] = n; 565 | s.pop(); 566 | } 567 | s.push(n); 568 | } 569 | vector ans; 570 | 571 | for (int n : findNums) { 572 | ans.push_back(m.count(n) ? m[n] : -1); 573 | } 574 | return ans; 575 | } 576 | }; 577 | ``` 578 | 579 | 580 | 581 | ## 9. LeetCode 503 [Next Greater Element II](https://leetcode.com/problems/next-greater-element-ii/) 582 | 583 | ### Monotonic Stack (keep the **indexes** of the **decreasing** subsequence) 584 | 585 | ```c++ 586 | class Solution { 587 | public: 588 | vector nextGreaterElements(vector& nums) { 589 | int n = nums.size(); 590 | vector res(n); 591 | stack st; 592 | 593 | for (int i=2*n-1; i>=0; i--) { 594 | while (!st.empty() && nums[st.top()] <= nums[i % n]) { 595 | st.pop(); 596 | } 597 | 598 | res[i % n] = st.empty() ? -1 : nums[st.top()]; 599 | st.push(i % n); 600 | } 601 | 602 | return res; 603 | } 604 | }; 605 | ``` 606 | 607 | 608 | 609 | ## 10. LeetCode 946 [Validate Stack Sequences](https://leetcode.com/problems/validate-stack-sequences/) 610 | 611 | ```c++ 612 | class Solution { 613 | public: 614 | bool validateStackSequences(vector& pushed, vector& popped) { 615 | int n = pushed.size(); 616 | stack st; 617 | 618 | int i = 0; 619 | for (int &num : pushed) { 620 | st.push(num); 621 | while (!st.empty() && i < n && st.top() == popped[i]) { 622 | st.pop(); 623 | i++; 624 | } 625 | } 626 | 627 | return i == n; 628 | } 629 | }; 630 | ``` 631 | 632 | 633 | 634 | ## 11. LeetCode 921 [Minimum Add to Make Parentheses Valid](https://leetcode.com/problems/minimum-add-to-make-parentheses-valid/) 635 | 636 | ### (1) O(N) + O(N) 637 | 638 | ```c++ 639 | class Solution { 640 | public: 641 | int minAddToMakeValid(string S) { 642 | int n = S.length(); 643 | stack st; 644 | 645 | for (char c : S) { 646 | if (c == '(') { 647 | st.push(c); 648 | } else { 649 | if (st.empty()) st.push(c); 650 | else { 651 | if (st.top() == '(') { 652 | st.pop(); 653 | } else { 654 | st.push(c); 655 | } 656 | } 657 | } 658 | } 659 | 660 | return st.size(); 661 | } 662 | }; 663 | ``` 664 | 665 | 666 | 667 | ### (2) O(N) + O(1) 668 | 669 | ```c++ 670 | class Solution { 671 | public: 672 | int minAddToMakeValid(string S) { 673 | int res = 0, bal = 0; 674 | 675 | for (int i=0; i> st; 730 | }; 731 | 732 | /** 733 | * Your StockSpanner object will be instantiated and called as such: 734 | * StockSpanner obj = new StockSpanner(); 735 | * int param_1 = obj.next(price); 736 | */ 737 | ``` 738 | 739 | 740 | 741 | ## 13. LeetCode 735 [Asteroid Collision](https://leetcode.com/problems/asteroid-collision/) 742 | 743 | ```c++ 744 | // Time Complexity: O(n) 745 | // Space Complexity: O(n) 746 | 747 | class Solution { 748 | public: 749 | vector asteroidCollision(vector& asteroids) { 750 | vector st; 751 | int n = asteroids.size(); 752 | 753 | for (int i=0; i 0 || st.empty() || st.back() < 0) { 755 | st.push_back(asteroids[i]); 756 | } 757 | else if (st.back() <= -asteroids[i]) { 758 | if (st.back() < -asteroids[i]) i--; 759 | st.pop_back(); 760 | } 761 | } 762 | 763 | return st; 764 | } 765 | }; 766 | ``` 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | -------------------------------------------------------------------------------- /Algorithm/LeetCode/Union-Find.md: -------------------------------------------------------------------------------- 1 | # Disjoint set / Union-Find Forest 2 | 3 | [youtube-video-by-huahua](https://www.youtube.com/watch?v=VJnUwsE4fWA) 4 | 5 | ```latex 6 | Find(x): find the root/cluster-id of x 7 | 8 | Union(x, y): merge two clusters 9 | 10 | Check whether two elements are in the same set or not in O(1)*. 11 | 12 | Find: O(ɑ(n))* ≈ O(1) 13 | 14 | Union: O(ɑ(n))* ≈ O(1) 15 | 16 | Space: O(n) 17 | 18 | Without optimization: Find: O(n) 19 | 20 | Two key optimizations: 21 | 22 | 1. Path compression: make tree flat 23 | -> happened during Find() 24 | 2. Union by rank: merge low rank tree to high rank one 25 | -> If two sub-tree has the same rank, break tie arbitrarily and increase the merged tree's 26 | rank by 1; 27 | -> Reduce path compression overhead. 28 | 29 | *: amortized 30 | 31 | ɑ(.): inverse Ackermann function 32 | 33 | ``` 34 | 35 | 36 | 37 | ## 1. LeetCode 399 [Evaluate Division](https://leetcode.com/problems/evaluate-division/) 38 | 39 | [huahua](http://zxi.mytechroad.com/blog/graph/leetcode-399-evaluate-division/) 40 | 41 | ```c++ 42 | // E: number of edges(equations) 43 | // Q: number of queries 44 | // Time Complexity: O(E + Q) 45 | // Space Complexity: O(E) 46 | 47 | class Solution { 48 | public: 49 | vector calcEquation(vector> equations, vector& values, vector> queries) { 50 | unordered_map> parents; 51 | 52 | for (int i=0; i ans; 72 | for (const auto& query : queries) { 73 | const string& X = query.first; 74 | const string& Y = query.second; 75 | if (!parents.count(X) || !parents.count(Y)) { 76 | ans.push_back(-1.0); 77 | continue; 78 | } 79 | 80 | auto& rX = find(X, parents); 81 | auto& rY = find(Y, parents); 82 | if (rX.first != rY.first) { 83 | ans.push_back(-1.0); 84 | } else { 85 | ans.push_back(rX.second / rY.second); 86 | } 87 | } 88 | 89 | return ans; 90 | } 91 | 92 | private: 93 | pair& find(const string& X, unordered_map> &parents) { 94 | if (X != parents[X].first) { 95 | const auto& p = find(parents[X].first, parents); 96 | parents[X].first = p.first; 97 | parents[X].second *= p.second; 98 | } 99 | return parents[X]; 100 | } 101 | }; 102 | ``` 103 | 104 | 105 | 106 | ## 2. LeetCode 547 [Friend Circles](https://leetcode.com/problems/friend-circles/) 107 | 108 | ```c++ 109 | class UnionFindSet { 110 | public: 111 | UnionFindSet(int n) { 112 | _parent = vector(n+1, 0); 113 | _rank = vector(n+1, 0); 114 | 115 | for (int i=1; i<=n; i++) { 116 | _parent[i] = i; 117 | } 118 | } 119 | 120 | bool Union(int x, int y) { 121 | int rx = Find(x); 122 | int ry = Find(y); 123 | 124 | if (rx == ry) return false; 125 | 126 | if (_rank[rx] > _rank[ry]) { 127 | _parent[ry] = rx; 128 | } else { 129 | _parent[rx] = ry; 130 | if (_rank[rx] == _rank[ry]) { 131 | _rank[ry]++; 132 | } 133 | } 134 | 135 | return true; 136 | } 137 | 138 | int Find(int x) { 139 | if (_parent[x] != x) { 140 | _parent[x] = Find(_parent[x]); 141 | } 142 | return _parent[x]; 143 | } 144 | 145 | private: 146 | vector _parent; 147 | vector _rank; 148 | }; 149 | 150 | class Solution { 151 | public: 152 | int findCircleNum(vector>& M) { 153 | int n = M.size(); 154 | UnionFindSet nfs(n); 155 | 156 | for (int i=0; i circles; 165 | for (int i=1; i<=n; i++) { 166 | circles.insert(nfs.Find(i)); 167 | } 168 | 169 | return circles.size(); 170 | } 171 | }; 172 | ``` 173 | 174 | 175 | 176 | ## 3. LeetCode 684 [Redundant Connection](https://leetcode.com/problems/redundant-connection/) 177 | 178 | ```c++ 179 | class UnionFindSet { 180 | public: 181 | UnionFindSet(int n) { 182 | _parent = vector(n+1, 0); 183 | _rank = vector(n+1, 0); 184 | 185 | for (int i=1; i<=n; i++) { 186 | _parent[i] = i; 187 | } 188 | } 189 | 190 | bool Union(int x, int y) { 191 | int rx = Find(x); 192 | int ry = Find(y); 193 | 194 | if (rx == ry) return false; 195 | if (_rank[rx] > _rank[ry]) { 196 | _parent[ry] = rx; 197 | } else { 198 | _parent[rx] = ry; 199 | if (_rank[rx] == _rank[ry]) { 200 | _rank[ry]++; 201 | } 202 | } 203 | 204 | return true; 205 | } 206 | 207 | int Find(int x) { 208 | if (_parent[x] != x) { 209 | _parent[x] = Find(_parent[x]); 210 | } 211 | return _parent[x]; 212 | } 213 | 214 | private: 215 | vector _parent; 216 | vector _rank; 217 | }; 218 | 219 | class Solution { 220 | public: 221 | vector findRedundantConnection(vector>& edges) { 222 | int n = edges.size(); 223 | UnionFindSet ufs(n); 224 | vector ans; 225 | 226 | for (int i=0; i parent; 245 | public: 246 | vector findRedundantDirectedConnection(vector>& edges) { 247 | parent = vector(edges.size()+1, 0); 248 | vector doubleParentA, doubleParentB; 249 | 250 | for(vector &edge : edges) { 251 | if(!parent[edge[1]]) 252 | parent[edge[1]] = edge[0]; 253 | else { 254 | //two parent 255 | doubleParentA = {parent[edge[1]], edge[1]}; 256 | doubleParentB = edge; 257 | edge[1] = 0; 258 | } 259 | } 260 | 261 | for(int i=0; i &edge : edges) { 264 | int a = edge[0]; 265 | int b = edge[1]; 266 | int v = find(a); 267 | if(b == 0) continue; 268 | if(v == b) { 269 | if(doubleParentA.empty()) { 270 | return edge; 271 | } 272 | else return doubleParentA; 273 | } 274 | parent[b] = v; 275 | } 276 | return doubleParentB; 277 | } 278 | 279 | int find(int x) { 280 | int root = parent[x]; 281 | if(x != root) { 282 | root = find(root); 283 | } 284 | return root; 285 | } 286 | }; 287 | ``` 288 | 289 | [solution](https://leetcode.com/problems/redundant-connection-ii/discuss/108045/C%2B%2BJava-Union-Find-with-explanation-O(n)) 290 | 291 | 292 | 293 | ## 5. LeetCode 952 [Largest Component Size by Common Factor](https://leetcode.com/problems/largest-component-size-by-common-factor/) 294 | 295 | [youtube](https://www.youtube.com/watch?v=GTX0kw63Tn0) 296 | 297 | ### Intuition 298 | 299 | Union each number with all its factor; 300 | 301 | Count the most frequent parent. 302 | 303 | [max_element](http://www.cplusplus.com/reference/algorithm/max_element/?kw=max_element) 304 | 305 | ```c++ 306 | // W: the largest number 307 | // Time Complexity: O(n*sqrt(W)) 308 | // Space Complexity: O(W) 309 | 310 | class UnionFindSet { 311 | public: 312 | UnionFindSet(int n) : _parent(n) { 313 | for (int i=0; i _parent; 331 | }; 332 | 333 | class Solution { 334 | public: 335 | int largestComponentSize(vector& A) { 336 | int n = *max_element(A.begin(), A.end()); 337 | UnionFindSet ufs(n+1); 338 | for (int &a : A) { 339 | for (int k = 2; k <= sqrt(a); k++) { 340 | if (a % k == 0) { 341 | ufs.Union(a, k); 342 | ufs.Union(a, a / k); 343 | } 344 | } 345 | } 346 | 347 | unordered_map mp; 348 | int ans = 1; 349 | for (int &a : A) { 350 | ans = max(ans, ++mp[ufs.Find(a)]); 351 | } 352 | return ans; 353 | } 354 | }; 355 | ``` 356 | 357 | 358 | 359 | ## 6. LeetCode 737 [Sentence Similarity II](https://leetcode.com/problems/sentence-similarity-ii/) 360 | 361 | ### Similar to LeetCode 399 362 | 363 | [huahua](http://zxi.mytechroad.com/blog/hashtable/leetcode-737-sentence-similarity-ii/) 364 | 365 | ### (1) DFS (without and with optimization using hashmap) 366 | 367 | ### (2) Union-Find 368 | 369 | ```c++ 370 | // Time Complexity: O(|pairs| + |words1|) 371 | // Space Complexity: O(|pairs|) 372 | 373 | class UnionFindSet { 374 | public: 375 | UnionFindSet(int n) { 376 | _parents.resize(n); 377 | _ranks.resize(n); 378 | 379 | for (int i=0; i _ranks[ry]) { 390 | _parents[ry] = rx; 391 | } else { 392 | _parents[rx] = ry; 393 | if (_ranks[rx] == _ranks[ry]) { 394 | _ranks[ry]++; 395 | } 396 | } 397 | 398 | return true; 399 | } 400 | 401 | int Find(int x) { 402 | if (_parents[x] != x) { 403 | _parents[x] = Find(_parents[x]); 404 | } 405 | return _parents[x]; 406 | } 407 | 408 | private: 409 | vector _parents; 410 | vector _ranks; 411 | }; 412 | 413 | class Solution { 414 | public: 415 | bool areSentencesSimilarTwo(vector& words1, vector& words2, vector> pairs) { 416 | int l1 = words1.size(); 417 | int l2 = words2.size(); 418 | if (l1 != l2) return false; 419 | 420 | int n = pairs.size(); 421 | UnionFindSet ufs(n*2); 422 | 423 | for (int i=0; i dictionary; 467 | }; 468 | ``` 469 | 470 | 471 | 472 | ## 7. LeetCode 200 [Number of Islands](https://leetcode.com/problems/number-of-islands/) 473 | 474 | ```c++ 475 | // Time Complexity: O(mn) 476 | // Space Complexity: O(mn) 477 | 478 | class UnionFindSet { 479 | public: 480 | UnionFindSet(vector>& grid) { 481 | int m = grid.size(); 482 | int n = grid[0].size(); 483 | _parents.resize(m*n); 484 | _ranks.resize(m*n); 485 | count = 0; 486 | for (int i=0; i _ranks[ry]) { 507 | _parents[ry] = rx; 508 | } else { 509 | _parents[rx] = ry; 510 | if (_ranks[rx] == _ranks[ry]) { 511 | _ranks[ry]++; 512 | } 513 | } 514 | 515 | return true; 516 | } 517 | 518 | int Find(int x) { 519 | if (_parents[x] != x) { 520 | _parents[x] = Find(_parents[x]); 521 | } 522 | return _parents[x]; 523 | } 524 | 525 | int getCount() const { 526 | return count; 527 | } 528 | 529 | private: 530 | vector _parents; 531 | vector _ranks; 532 | int count; // number of connected component 533 | }; 534 | 535 | class Solution { 536 | public: 537 | int numIslands(vector>& grid) { 538 | if (grid.empty() || grid[0].empty()) return 0; 539 | int m = grid.size(); 540 | int n = grid[0].size(); 541 | 542 | UnionFindSet ufs(grid); 543 | for (int i=0; i= 0 && grid[i-1][j] == '1') { 548 | ufs.Union(i*n+j, (i-1)*n+j); 549 | } 550 | if (i + 1 < m && grid[i+1][j] == '1') { 551 | ufs.Union(i*n+j, (i+1)*n+j); 552 | } 553 | if (j - 1 >= 0 && grid[i][j-1] == '1') { 554 | ufs.Union(i*n+j, i*n+j-1); 555 | } 556 | if (j + 1 < n && grid[i][j+1] == '1') { 557 | ufs.Union(i*n+j, i*n+j+1); 558 | } 559 | } 560 | } 561 | } 562 | return ufs.getCount(); 563 | } 564 | }; 565 | ``` 566 | 567 | 568 | 569 | ## 8. LeetCode 947 [Most Stones Removed with Same Row or Column](https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/) 570 | 571 | ```c++ 572 | // Time Complexity: O(n) 573 | // Space Complexity: O(n + 20000) 574 | 575 | class UnionFindSet { 576 | public: 577 | UnionFindSet(int n) { 578 | _parents.resize(n); 579 | _ranks.resize(n); 580 | 581 | for (int i=0; i _ranks[ry]) { 591 | _parents[ry] = rx; 592 | } else { 593 | _parents[rx] = ry; 594 | if (_ranks[rx] == _ranks[ry]) { 595 | _ranks[ry]++; 596 | } 597 | } 598 | return true; 599 | } 600 | 601 | int Find(int x) { 602 | if (_parents[x] != x) { 603 | // path compression 604 | _parents[x] = Find(_parents[x]); 605 | } 606 | return _parents[x]; 607 | } 608 | 609 | private: 610 | vector _parents; 611 | vector _ranks; 612 | }; 613 | 614 | class Solution { 615 | public: 616 | int removeStones(vector>& stones) { 617 | int n = stones.size(); 618 | UnionFindSet ufs(20000); 619 | 620 | for (int i=0; i components; 625 | for (int i=0; i& grid) { 644 | int n = grid.size(); 645 | DSU dsu(4 * n * n); 646 | for (int r = 0; r < n; ++r) 647 | for (int c = 0; c < n; ++c) { 648 | int index = 4 * (r * n + c); 649 | switch (grid[r][c]) { 650 | case '/': 651 | dsu.merge(index + 0, index + 3); 652 | dsu.merge(index + 1, index + 2); 653 | break; 654 | case '\\': 655 | dsu.merge(index + 0, index + 1); 656 | dsu.merge(index + 2, index + 3); 657 | break; 658 | case ' ': 659 | dsu.merge(index + 0, index + 1); 660 | dsu.merge(index + 1, index + 2); 661 | dsu.merge(index + 2, index + 3); 662 | break; 663 | default: break; 664 | } 665 | if (r + 1 < n) 666 | dsu.merge(index + 2, index + 4 * n + 0); 667 | if (c + 1 < n) 668 | dsu.merge(index + 1, index + 4 + 3); 669 | } 670 | int ans = 0; 671 | for (int i = 0; i < 4 * n * n; ++i) 672 | if (dsu.find(i) == i) ++ans; 673 | return ans; 674 | } 675 | 676 | private: 677 | class DSU { 678 | public: 679 | DSU(int n): parent_(n) { 680 | for (int i = 0; i < n; ++i) 681 | parent_[i] = i; 682 | } 683 | 684 | int find(int x) { 685 | if (parent_[x] != x) parent_[x] = find(parent_[x]); 686 | return parent_[x]; 687 | } 688 | 689 | void merge(int x, int y) { 690 | parent_[find(x)] = find(y); 691 | } 692 | 693 | private: 694 | vector parent_; 695 | }; 696 | }; 697 | ``` 698 | 699 | 700 | 701 | ## 10. LeetCode 839 [Similar String Groups](https://leetcode.com/problems/similar-string-groups/) 702 | 703 | ```c++ 704 | class disjoint_set { 705 | private: 706 | vector _roots; 707 | int sz; 708 | 709 | public: 710 | disjoint_set(int n) { 711 | makeset(n); 712 | } 713 | 714 | void makeset(int n) { 715 | _roots.resize(n); 716 | iota(_roots.begin(), _roots.end(), 0); 717 | sz = n; 718 | } 719 | 720 | int Find(int i) { 721 | if (i != _roots[i]) 722 | _roots[i] = Find(_roots[i]); 723 | return _roots[i]; 724 | } 725 | 726 | void Union(int i, int j) { 727 | int ri = Find(i), rj = Find(j); 728 | if (ri != rj) { 729 | _roots[ri] = rj; 730 | sz--; 731 | } 732 | } 733 | 734 | int size() { 735 | return sz; 736 | } 737 | }; 738 | 739 | class Solution { 740 | public: 741 | int numSimilarGroups(vector& A) { 742 | disjoint_set ds(A.size()); 743 | for (int i = 0; i < A.size(); i++) 744 | for (int j = i + 1; j < A.size(); j++) 745 | if (similar(A[i], A[j])) 746 | ds.Union(i, j); 747 | return ds.size(); 748 | } 749 | 750 | private: 751 | bool similar(string &a, string &b) { 752 | int n = 0; 753 | for (int i = 0; i < a.size(); i++) 754 | if (a[i] != b[i] && ++n > 2) 755 | return false; 756 | return true; 757 | } 758 | }; 759 | ``` 760 | 761 | 762 | 763 | ## 11. LeetCode 924 [Minimize Malware Spread](https://leetcode.com/problems/minimize-malware-spread/) 764 | 765 | ```c++ 766 | class UnionFindSet { 767 | public: 768 | UnionFindSet(int n) { 769 | _parents.resize(n); 770 | _ranks.resize(n); 771 | 772 | for (int i=0; i _ranks[ry]) { 782 | _parents[ry] = rx; 783 | } else { 784 | _parents[rx] = ry; 785 | if (_ranks[rx] == _ranks[ry]) { 786 | _ranks[ry]++; 787 | } 788 | } 789 | return true; 790 | } 791 | 792 | int Find(int x) { 793 | if (_parents[x] != x) { 794 | // path compression 795 | _parents[x] = Find(_parents[x]); 796 | } 797 | return _parents[x]; 798 | } 799 | 800 | private: 801 | vector _parents; 802 | vector _ranks; 803 | }; 804 | 805 | class Solution { 806 | public: 807 | int minMalwareSpread(vector>& graph, vector& initial) { 808 | int n = graph.size(); 809 | UnionFindSet ufs(n); 810 | 811 | for (int i=0; i area(n, 0), malware(n, 0); 820 | for (int i = 0; i < n; ++i) area[ufs.Find(i)]++; 821 | for (int i : initial) malware[ufs.Find(i)]++; 822 | vector res = {1, 0}; 823 | 824 | for (int i : initial) 825 | res = min(res, {(malware[ufs.Find(i)] == 1 ) * (-area[ufs.Find(i)]), i}); 826 | return res[1]; 827 | } 828 | }; 829 | ``` 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | -------------------------------------------------------------------------------- /C++/Basic-Notes.md: -------------------------------------------------------------------------------- 1 | ## Undefined Behaviors 2 | 3 | [My Question on Stackoverflow](https://stackoverflow.com/questions/52944007/what-is-the-order-of-calculating-ivi) 4 | 5 | [Undefined behavior and sequence points](https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) 6 | 7 | -------------------------------------------------------------------------------- /Design-Pattern/Facade.md: -------------------------------------------------------------------------------- 1 | ## Facade (门面设计模式) 2 | 3 | [Facade Design Pattern](https://laravelacademy.org/post/2807.html) 4 | 5 | [Facade-Wiki](https://en.wikipedia.org/wiki/Facade_pattern) 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 | -------------------------------------------------------------------------------- /Design-Pattern/IoC-DI.md: -------------------------------------------------------------------------------- 1 | ## IoC (Inversion of Control) & DI (Dependency Injection) 2 | 3 | [reference](https://laravelacademy.org/post/769.html) 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Yuchuan Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /OA/Linkedin_OA.md: -------------------------------------------------------------------------------- 1 | ## Linkedin OA 2 | 3 | ### 1. Friend Circles (LeetCode 547) 4 | 5 | DFS/Union-Find 6 | 7 | (1) DFS 8 | 9 | ```c++ 10 | // Time complexity: O(n^2) 11 | // Space complexity: O(n) 12 | 13 | // friend circles (DFS) 14 | int findCircleNum2(vector>& M) { 15 | if (M.empty()) return 0; 16 | int n = (int) M[0].size(); 17 | int cnt = 0; 18 | // deque visited(n, false); 19 | vector visited(n, false); 20 | 21 | for (int i=0; i>& M, vector & visited) { 28 | visited[i] = true; 29 | 30 | auto row = M[i]; 31 | for (int j = 0; j < (int)row.size(); j++) { 32 | if (!visited[j] && row[j] == 1) { 33 | dfs(j, M, visited); 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | 40 | 41 | (2) Union-Find: 42 | 43 | ```c++ 44 | // Time complexity: O(n^3) 45 | // Space complexity: O(n) 46 | 47 | // friend circles (UnionFind) 48 | // union by rank 49 | int findCircleNum(vector>& M) { 50 | if (M.empty()) return 0; 51 | int n = (int) M[0].size(); 52 | int cnt = n; 53 | vector parent(n); 54 | vector rank(n, 0); 55 | for (int i=0; i rank[rootJ]) { 66 | parent[rootJ] = rootI; 67 | } else { 68 | parent[rootI] = rootJ; 69 | if (rank[rootI] == rank[rootJ]) { 70 | rank[rootJ]++; 71 | } 72 | } 73 | cnt--; 74 | } 75 | } 76 | } 77 | return cnt; 78 | } 79 | 80 | int find(int x, vector &parent) { 81 | // Path compression 82 | if (parent[x] != x) { 83 | parent[x] = find(parent[x], parent); 84 | } 85 | return parent[x]; 86 | } 87 | ``` 88 | 89 | 90 | 91 | ### 2. simple queries(binary search) 92 | 93 | (1) binary search 94 | 95 | ```c++ 96 | //Time Complexity: O(nlogn) 97 | // Space Complexity: O(1) 98 | 99 | // simple queries(binary search) 100 | // Return an array containing how many integers in nums1 are smaller than or equal to each integer in nums2 101 | vector simpleQueries(vector nums1, vector nums2); 102 | int bs(vector v, int n); 103 | 104 | vector simpleQueries(vector nums1, vector nums2) { 105 | sort(nums1.begin(), nums1.end()); 106 | int len = (int) nums2.size(); 107 | vector queries(len, 0); 108 | for (int i=0; i v, int n) { 116 | int len = (int) v.size(); 117 | int l = 0, r = len-1; 118 | while (l < r) { 119 | int mid = l + (r - l) / 2; 120 | if (v[mid] > n) { 121 | r = mid; 122 | } else { 123 | l = mid + 1; 124 | } 125 | } 126 | return l; 127 | } 128 | ``` 129 | 130 | 131 | 132 | ### 3. monsoon umbrella (coin change) 133 | 134 | (1) backtracking (early pruning(termination)) 135 | 136 | ```c++ 137 | // Time Complexity: O(len(coins)*amount) 138 | // Space Complexity: O(amount) 139 | 140 | // backtrack 141 | int coinChange(vector& coins, int amount) { 142 | if (amount == 0) return 0; 143 | if (coins.empty()) return -1; 144 | int min_count = INT_MAX; 145 | sort(coins.begin(), coins.end(), greater()); 146 | backtrack(coins, amount, 0, min_count, 0); 147 | 148 | return min_count == INT_MAX ? -1 : min_count; 149 | } 150 | 151 | void backtrack(const vector& coins, int amount, int index, int &min_cnt, int cur_cnt) { 152 | if (amount == 0) { 153 | min_cnt = min(min_cnt, cur_cnt); 154 | return; 155 | } 156 | if (index == coins.size()) { 157 | return; 158 | } 159 | for (int i=amount/coins[index]; i>=0 && cur_cnt + i < min_cnt; i--) { 160 | backtrack(coins, amount-i*coins[index], index+1, min_cnt, cur_cnt+i); 161 | } 162 | } 163 | ``` 164 | 165 | 166 | 167 | (2) dp 168 | 169 | ```c++ 170 | // Time Complexity: O(MN) (M:amount, N:number of coins); 171 | // Space Complexity: O(M) 172 | 173 | // dp 174 | int coinChange2(vector& coins, int amount) { 175 | int n = (int) coins.size(); 176 | vector dp(amount+1, INT_MAX); 177 | dp[0] = 0; 178 | for (int i=0; i& coins) { 206 | int n = coins.size(); 207 | int cnt = 0; 208 | backtrack(amount, coins, 0, cnt); 209 | return cnt; 210 | } 211 | 212 | void backtrack(int amount, vector &coins, int index, int &cnt) { 213 | if (amount == 0) { 214 | cnt++; 215 | return; 216 | } 217 | if (index == coins.size()) return; 218 | 219 | for (int i=amount/coins[index]; i>=0; i--) { 220 | backtrack(amount-i*coins[index], coins, index+1, cnt); 221 | } 222 | } 223 | ``` 224 | 225 | 226 | 227 | (2) DP (bottom-up) 228 | 229 | ```c++ 230 | // Time Complexity: O(MN) (M:amount, N:number of coins); 231 | // Space Complexity: O(M) 232 | 233 | int change(int amount, vector& coins) { 234 | int n = coins.size(); 235 | vector dp(amount+1, 0); 236 | dp[0] = 1; 237 | for (int i=0; i=0 && cur_cnt+i dp(n+1, n); 283 | dp[0] = 0; 284 | for (int i=1; i<=s; i++) { 285 | int square = i*i; 286 | for (int j=square; j<=n; j++) { 287 | dp[j] = min(dp[j], dp[j-square]+1); 288 | } 289 | } 290 | return dp[n]; 291 | } 292 | 293 | 294 | // 2 295 | class Solution { 296 | public: 297 | int numSquares(int n) { 298 | static vector dp{0}; 299 | while(dp.size() <= n) { 300 | int m = dp.size(); 301 | int cnt = INT_MAX; 302 | for(int i=1; i*i<=m; i++) { 303 | cnt = min(cnt, dp[m-i*i] + 1); 304 | } 305 | dp.push_back(cnt); 306 | } 307 | return dp[n]; 308 | } 309 | }; 310 | 311 | // 3 using static to store the former results 312 | class Solution { 313 | public: 314 | int numSquares(int n) { 315 | static vector dp{0}; 316 | int m = dp.size(); 317 | dp.resize(max(m,n+1), INT_MAX); 318 | for(int i=1,j; (j=i*i)<=n; i++) { 319 | for(int k = max(m,j); k<=n; k++) { 320 | dp[k] = min(dp[k], dp[k-j] + 1); 321 | } 322 | } 323 | return dp[n]; 324 | } 325 | }; 326 | ``` 327 | 328 | 329 | 330 | (3) math 331 | 332 | ```c++ 333 | // 1 334 | class Solution { 335 | public: 336 | int numSquares(int n) { 337 | for(int i=0; i*i<=n; ++i) { 338 | for(int j=0; j*j<=n; ++j) { 339 | int k = sqrt(n - i*i - j*j); 340 | if(i*i + j*j + k*k == n) 341 | return !!i + !!j + !!k; 342 | } 343 | } 344 | return 4; 345 | } 346 | }; 347 | 348 | // 2 349 | class Solution { 350 | public: 351 | int numSquares(int n) { 352 | while(n % 4 == 0) n /= 4; 353 | if(n % 8 == 7) return 4; 354 | for(int i=0; i*i<=n; ++i) { 355 | int j = sqrt(n - i*i); 356 | if(i*i + j*j == n) 357 | return !!i + !!j; 358 | } 359 | return 3; 360 | } 361 | }; 362 | ``` 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | -------------------------------------------------------------------------------- /OA/Twitter_OA.md: -------------------------------------------------------------------------------- 1 | ## 1. Missing Words 2 | 3 | ### - Split a string in C++ 4 | 5 | - refrences: 6 | 7 | A. [cplusplus](http://www.cplusplus.com/faq/sequences/strings/split/) 8 | 9 | B. [stackoverflow](https://stackoverflow.com/questions/236129/how-do-i-iterate-over-the-words-of-a-string#) 10 | 11 | - functions & class 12 | 13 | [istringstream](http://www.cplusplus.com/reference/sstream/istringstream/) 14 | 15 | ```c++ 16 | #include 17 | 18 | string s; 19 | istringstream iss( s ); 20 | 21 | // std::ios::eof 22 | // Check whether eofbit is set 23 | // Returns true if the eofbit error state flag is set for the stream. 24 | 25 | // This flag is set by all standard input operations when the End-of-File is reached in the // sequence associated with the stream. 26 | bool eof() const; 27 | ``` 28 | 29 | ​ [std::getline](http://www.cplusplus.com/reference/string/string/getline/?kw=getline) 30 | 31 | ```c++ 32 | istream& getline (istream& is, string& str, char delim); 33 | ``` 34 | 35 | 36 | 37 | (1) iostreams and getline() 38 | 39 | ```c++ 40 | #include 41 | #include 42 | 43 | using namespace std; 44 | 45 | string s = "string,to,split"; 46 | istringstream ss( s ); 47 | while (!ss.eof()) // See the WARNING above for WHY we're doing this! 48 | { 49 | string x; // here's a nice, empty string 50 | getline( ss, x, ',' ); // try to read the next field into it 51 | cout << x << endl; // print it out, EVEN IF WE ALREADY HIT EOF 52 | } 53 | ``` 54 | 55 | 56 | 57 | (2) string::find_first_of 58 | 59 | ```c++ 60 | string s = "string,to,split"; 61 | string delimiters = ","; 62 | size_t current; 63 | size_t next = -1; 64 | do 65 | { 66 | current = next + 1; 67 | next = s.find_first_of( delimiters, current ); 68 | cout << s.substr( current, next - current ) << endl; 69 | } 70 | while (next != string::npos); 71 | ``` 72 | 73 | 74 | 75 | - Solution: 76 | 77 | ```c++ 78 | #include 79 | #include 80 | #include 81 | 82 | using namespace std; 83 | 84 | // Missing Words 85 | vector missingWords(string &s, string &t); 86 | vector split(string &s); 87 | 88 | vector missingWords(string &s, string &t) { 89 | vector ans; 90 | vector ss = split(s); 91 | vector st = split(t); 92 | 93 | int s_ptr = 0, t_ptr = 0; 94 | while (s_ptr < ss.size()) { 95 | if (t_ptr < st.size() && ss[s_ptr] == st[t_ptr]) { 96 | s_ptr++; 97 | t_ptr++; 98 | } else { 99 | ans.push_back(ss[s_ptr++]); 100 | } 101 | } 102 | return ans; 103 | } 104 | 105 | vector split(string &s) { 106 | vector splited; 107 | istringstream iss(s); 108 | while (!iss.eof()) { 109 | string x; 110 | getline(iss, x, ' '); 111 | splited.push_back(x); 112 | } 113 | return splited; 114 | } 115 | 116 | int main(int argc, const char * argv[]) { 117 | string s = "I am using HackerRank to improve programming"; 118 | string t = "am HackerRank to improve"; 119 | 120 | for (auto m : missingWords(s, t)) { 121 | cout << m << endl; 122 | } 123 | 124 | return 0; 125 | } 126 | ``` 127 | 128 | 129 | 130 | ## 2. Huffman Decoding 131 | 132 | ```c++ 133 | // Huffman Decoder 134 | string huffmanDecoder(vector dict, string input); 135 | vector splitByDelimiter(string &s, char delimiter); 136 | 137 | vector splitByDelimiter(string &s, char delimiter) { 138 | vector splited; 139 | istringstream iss(s); 140 | while (!iss.eof()) { 141 | string x; 142 | getline(iss, x, delimiter); 143 | splited.push_back(x); 144 | } 145 | return splited; 146 | } 147 | 148 | string huffmanDecoder(vector dict, string input) { 149 | string ans = ""; 150 | unordered_map map; 151 | 152 | for (auto s : dict) { 153 | vector splited = splitByDelimiter(s, ' '); 154 | if (splited[0] == "newline") { 155 | map[splited[1]] = "\n"; 156 | } else { 157 | map[splited[1]] = splited[0]; 158 | } 159 | } 160 | 161 | int begin = 0, end = 1; 162 | while (end <= input.length()) { 163 | string cur = input.substr(begin, end-begin); 164 | if (map.count(cur)) { 165 | ans += map[cur]; 166 | begin = end++; 167 | } else { 168 | end++; 169 | } 170 | } 171 | 172 | return ans; 173 | } 174 | ``` 175 | 176 | 177 | 178 | 179 | 180 | ## 3. HackerlandElection 181 | 182 | https://www.geeksforgeeks.org/find-winner-election-votes-represented-candidate-names/ 183 | 184 | https://www.geeksforgeeks.org/frequent-word-array-strings/ 185 | 186 | https://stackoverflow.com/questions/9370945/c-help-finding-the-max-value-in-a-map 187 | 188 | http://www.cplusplus.com/reference/algorithm/max_element/?kw=max_element 189 | 190 | ### - Hashmap 191 | 192 | ```c++ 193 | // HackerlandElection 194 | string hackerlandElection(vector votes); 195 | 196 | // using hashmap (Java-hashmap) 197 | string hackerlandElection(vector votes) { 198 | unordered_map map; 199 | for (auto vote : votes) { 200 | map[vote]++; 201 | } 202 | 203 | string winner; 204 | int max_election = 0; 205 | 206 | for (auto m : map) { 207 | if ((m.second > max_election) || (m.second == max_election && m.first > winner)) { 208 | max_election = m.second; 209 | winner = m.first; 210 | } 211 | } 212 | 213 | return winner; 214 | } 215 | 216 | // using map (Java-TreeMap/Red-Black-Tree) 217 | bool compare(const pair &A, const pair &B) { 218 | return A.second < B.second; // same as using min_element 219 | } 220 | 221 | string hackerlandElection(vector votes) { 222 | string winner; 223 | map> m; 224 | 225 | for (auto vote : votes) { 226 | m[vote]++; 227 | } 228 | 229 | return max_element(m.begin(), m.end(), compare)->first; 230 | } 231 | ``` 232 | 233 | 234 | 235 | ## 4. Rover Control 236 | 237 | ```c++ 238 | // Rover Control 239 | int roverMove(int size, vector cmds); 240 | 241 | int roverMove(int size, vector cmds) { 242 | int pi = 0, pj = 0; 243 | unordered_map> moves{ 244 | {"UP", {-1, 0}}, 245 | {"RIGHT", {0, 1}}, 246 | {"DOWN", {1, 0}}, 247 | {"LEFT", {0, -1}} 248 | }; 249 | 250 | for (auto cmd : cmds) { 251 | int ni = pi + moves[cmd][0]; 252 | int nj = pj + moves[cmd][1]; 253 | if (ni >= 0 && ni < size && nj >= 0 && nj < size) { 254 | pi = ni; 255 | pj = nj; 256 | } 257 | } 258 | return pi*size+pj; 259 | } 260 | ``` 261 | 262 | 263 | 264 | ## 5. Simple Text Queries 265 | 266 | ```c++ 267 | // SimpleTextQueries 268 | vector textQueries(vector &sentences, vector &phrases); 269 | vector split(string &s); 270 | 271 | vector split(string &s) { 272 | vector splited; 273 | istringstream iss(s); 274 | while (!iss.eof()) { 275 | string x; 276 | getline(iss, x, ' '); 277 | splited.push_back(x); 278 | } 279 | return splited; 280 | } 281 | 282 | vector textQueries(vector &sentences, vector &phrases) { 283 | vector ans; 284 | vector> maps; 285 | 286 | for (auto sentence : sentences) { 287 | vector splited = split(sentence); 288 | unordered_map wordcnts; 289 | for (auto s : splited) { 290 | wordcnts[s]++; 291 | } 292 | maps.push_back(wordcnts); 293 | } 294 | 295 | for (auto p : phrases) { 296 | int index = 0; 297 | vector words = split(p); 298 | string output = ""; 299 | for (auto m : maps) { 300 | int min_cnt = INT_MAX; 301 | for (auto word : words) { 302 | if (m[word] == 0) { 303 | min_cnt = INT_MAX; 304 | break; 305 | } 306 | min_cnt = min(min_cnt, m[word]); 307 | } 308 | if (min_cnt != INT_MAX && min_cnt > 0) { 309 | output += to_string(index) + " "; 310 | } 311 | index++; 312 | } 313 | if (output.length() == 0) { 314 | ans.push_back("-1"); 315 | } else { 316 | output.pop_back(); 317 | ans.push_back(output); 318 | } 319 | } 320 | 321 | return ans; 322 | } 323 | ``` 324 | 325 | 326 | 327 | ## 6. Who's the closest 328 | 329 | ```c++ 330 | // who's the closest (map + binary search) 331 | vector closest(string s, vector indexes); 332 | 333 | vector closest(string s, vector indexes) { 334 | vector ans; 335 | unordered_map> map; 336 | 337 | for (int i=0; i v(map[s[index]].begin(), map[s[index]].end()); 346 | int left = 0, right = (int) v.size() - 1; 347 | if (index == v[left]) { 348 | ans.push_back(v[left+1]); 349 | continue; 350 | } else if (index == v[right]) { 351 | ans.push_back(v[right-1]); 352 | continue; 353 | } 354 | while (left <= right) { 355 | int mid = left + (right - left) / 2; 356 | if (v[mid] == index) { 357 | ans.push_back((v[mid] - v[mid-1]) <= (v[mid+1] - v[mid]) ? v[mid-1] : v[mid+1]); 358 | break; 359 | } else if (v[mid] > index) { 360 | right = mid - 1; 361 | } else { 362 | left = mid + 1; 363 | } 364 | } 365 | } 366 | } 367 | 368 | return ans; 369 | } 370 | ``` 371 | 372 | 373 | 374 | ## 7. Image Matching 375 | 376 | LeetCode 694 Number of Distinct Island 377 | 378 | ```c++ 379 | // Image Matching (bfs/dfs) 380 | int countMatches(vector> &grid1, vector> &grid2); 381 | vector> getImage(int row, int col, vector> &grid); 382 | bool isMatch(vector> &image1, vector> &image2); 383 | 384 | int countMatches(vector> &grid1, vector> &grid2) { 385 | int ans = 0; 386 | 387 | int r = (int) grid1.size(); 388 | int c = (int) grid1[0].size(); 389 | for (int i=0; i> image1 = getImage(i, j, grid1); 392 | // cout << "size: " << image1.size() << endl; 393 | vector> image2 = getImage(i, j, grid2); 394 | 395 | if (!image1.empty() && !image2.empty() && isMatch(image1, image2)) { 396 | ans++; 397 | } 398 | } 399 | } 400 | return ans; 401 | } 402 | 403 | // bfs 404 | vector> getImage(int row, int col, vector> &grid) { 405 | vector> image; 406 | const vector> dirs{{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; 407 | 408 | if (grid[row][col] == 1) { 409 | queue> q; 410 | q.push({row, col}); 411 | while (!q.empty()) { 412 | pair cur = q.front(); 413 | image.push_back(cur); 414 | q.pop(); 415 | int i = cur.first; 416 | int j = cur.second; 417 | grid[i][j] = 0; 418 | for (int k=0; k<4; k++) { 419 | int ni = i + dirs[k][0]; 420 | int nj = j + dirs[k][1]; 421 | if (ni >=0 && ni < grid.size() && nj >= 0 && nj < grid[0].size() && grid[ni][nj] == 1) { 422 | q.push({ni, nj}); 423 | } 424 | } 425 | } 426 | } 427 | 428 | return image; 429 | } 430 | 431 | // match two images 432 | bool isMatch(vector> &image1, vector> &image2) { 433 | set>> us; 434 | sort(image1.begin(), image1.end()); 435 | sort(image2.begin(), image2.end()); 436 | us.insert(image1); 437 | us.insert(image2); 438 | return us.size() == 1; 439 | } 440 | ``` 441 | 442 | 443 | 444 | ## 8. No pairs Allowed 445 | 446 | ```c++ 447 | vector minimalOperations(vector input); 448 | 449 | vector minimalOperations(vector input) { 450 | vector ans; 451 | 452 | for (auto s : input) { 453 | int cnt = 0; 454 | for (int i=0; i st; 482 | for (auto c : s) { 483 | if (st.empty() || c == '(' || c == '[' || c == '{') { 484 | st.push(c); 485 | } else { 486 | if (isMatch(st.top(), c)) { 487 | st.pop(); 488 | } else { 489 | return false; 490 | } 491 | } 492 | } 493 | return st.empty(); 494 | } 495 | 496 | bool isMatch(char a, char b) { 497 | if (a == '(') { 498 | return b == ')'; 499 | } else if (a == '[') { 500 | return b == ']'; 501 | } else if (a == '{') { 502 | return b == '}'; 503 | } 504 | return false; 505 | } 506 | ``` 507 | 508 | 509 | 510 | ## 10. Primes in Subtree 511 | 512 | ```c++ 513 | // Primes in Subtree 514 | vector primeQueries(int n, vector starts, vector ends, vector values, vector queries); 515 | bool isPrime(int x); 516 | 517 | vector primeQueries(int n, vector starts, vector ends, vector values, vector queries) { 518 | vector ans; 519 | vector indexes(n); 520 | vector cnts(n); 521 | 522 | // initialize cnts 523 | for (int i=0; i primeQuery(int n, vector first, vector second, vector values, vector queries) { 591 | vector ans; 592 | vector indexes(n); 593 | unordered_map> map; 594 | vector parents(n); 595 | 596 | for (int i=0; i q; 606 | q.push(1); 607 | while (!q.empty()) { 608 | int parent = q.front(); 609 | q.pop(); 610 | 611 | for (auto& pair : map) { 612 | if (pair.first == parent) { 613 | for (auto child : pair.second) { 614 | q.push(child); 615 | parents[child-1] = parent-1; 616 | } 617 | } else { 618 | int isChild = false; 619 | for (auto cand : pair.second) { 620 | if (cand == parent && (pair.first-1) != parents[cand-1]) { 621 | q.push(pair.first); 622 | parents[pair.first-1] = parent-1; 623 | isChild = true; 624 | break; 625 | } 626 | } 627 | if (isChild) { 628 | pair.second.erase(parent); 629 | } 630 | } 631 | } 632 | } 633 | 634 | vector cnts(n); 635 | for (int i=0; iSpecificity Calculations 14 | 15 | Specificity is calculated by counting various components of your css and expressing them in a form (a,b,c,d): 16 | 17 | - *Element, Pseudo Element*: d = 1 –> (0,0,0,1) 18 | - *Class, Pseudo class, Attribute*: c = 1 –> (0,0,1,0) 19 | - *Id*: b = 1 -> (0,1,0,0) 20 | - *Inline Style*: a = 1 –> (1,0,0,0) 21 | 22 | **An id is more specific than a class is more specific than an element.** 23 | 24 | You calculate specificity by counting each of the above and adding 1 to either a,b,c, or d. It’s also important to note that 0,0,1,0 is more specific than 0,0,0,15. 25 | 26 | More examples: 27 | 28 | - p: 1 element – (0,0,0,1) 29 | - div: 1 element – (0,0,0,1) 30 | - \#sidebar: 1 id – (0,1,0,0) 31 | - div#sidebar: 1 element, 1 id – (0,1,0,1) 32 | - div#sidebar p: 2 elements, 1 id – (0,1,0,2) 33 | - div#sidebar p.bio: 2 elements, 1 class, 1 id – (0,1,1,2) 34 | 35 | ### Inheritance 36 | 37 | Elements inherit styles from their parent container. If you set the body tag to use color: red then the text for all elements inside the body will also be red unless otherwise specified. 38 | 39 | Not all css properties are inherited, though. For example *margins* and *paddings* are non-inherited properties. If you set a margin or padding on a div, the paragraphs inside that div do not inherit the margin and padding you set on the div. The paragraph will use the default browser margin and padding until you declare otherwise. 40 | 41 | You can explicitly set a property to inherit styles from it’s parent container, though. For example you could declare: 42 | 43 | ```css 44 | p { 45 | margin: inherit; 46 | padding: inherit; 47 | } 48 | ``` 49 | 50 | and your paragraph would then inherit both from it’s containing element. 51 | 52 | ### The Cascade 53 | 54 | At the highest level the cascade is what controls all css precedence and works as follows. 55 | 56 | 1. Find all css declarations that apply to the element and property in question. 57 | 2. Sort by origin and weight. Origin refers to the source of the declaration (author styles, user styles, browser defaults) and weight refers to the importance of the declaration. (author has more weight than user which has more weight than default. !importance has more weight than normal declarations) 58 | 3. Calculate specificity 59 | 4. If two rules are equal in all of the above, the one declared last wins. CSS embedded in the html always come after external stylesheets regardless of the order in the html 60 | 61 | \#3 above is likely the one you’ll need to pay attention to most. With #2 just understand that your styles will override how a user sets their browser unless they set their rules to be important. 62 | 63 | **Also realize that your styles will override the browser defaults, but those defaults do exist and is often what leads to cross browser issues. Using a reset file like [Eric Meyer’s CSS Reset](http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/) or [Yahoo’s YUI Reset CSS](http://developer.yahoo.com/yui/reset/) helps take the default styles out of the equation.** 64 | 65 | **Reference**: [vanseodesign](http://vanseodesign.com/css/css-specificity-inheritance-cascaade/) -------------------------------------------------------------------------------- /Web-Dev/Frontend/Daily-CSS-study-notes.md: -------------------------------------------------------------------------------- 1 | # Daily CSS Study Notes 2 | 3 | ## -Useful CSS Snippets 4 | 5 | [Learning Website](https://30-seconds.github.io/30-seconds-of-css/) 6 | 7 | ### 1. Bouncing loader 8 | 9 | HTML: 10 | 11 | ```html 12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | ``` 21 | 22 | CSS: 23 | 24 | ```css 25 | @keyframes bouncing-loader { 26 | 0% { 27 | opacity: 1; 28 | transform: translateY(0); 29 | } 30 | 100% { 31 | opacity: 0.1; 32 | transform: translateY(-1rem); 33 | } 34 | } 35 | 36 | .bouncing-loader { 37 | display: flex; 38 | justify-content: center; 39 | } 40 | 41 | .bouncing-loader > div { 42 | width: 1rem; 43 | height: 1rem; 44 | margin: 3rem 0.2rem; 45 | background: #8385aa; 46 | border-radius: 50%; 47 | animation: bouncing-loader .6s infinite alternate; 48 | } 49 | 50 | .bouncing-loader > div:nth-child(2) { 51 | animation-delay: .1s; 52 | } 53 | 54 | .bouncing-loader > div:nth-child(3) { 55 | animation-delay: .2s; 56 | } 57 | 58 | .bouncing-loader > div:nth-child(4) { 59 | animation-delay: .3s; 60 | } 61 | 62 | .bouncing-loader > div:nth-child(5) { 63 | animation-delay: .4s; 64 | } 65 | 66 | .bouncing-loader > div:nth-child(6) { 67 | animation-delay: .5s; 68 | } 69 | ``` 70 | 71 | [jsfiddle](http://jsfiddle.net/LacticAcidCYC/ab8g3o2d/) 72 | 73 | #### Explanation 74 | 75 | **Note: `1rem` is usually `16px`.** 76 | 77 | (1) `@keyframes` defines an animation that has two states, where the element changes `opacity` and is translated up on the 2D plane using `transform: translateY()`. 78 | 79 | (2) `.bouncing-loader` is the parent container of the bouncing circles and uses `display: flex` and `justify-content: center` to position them in the center. 80 | 81 | (3) `.bouncing-loader > div`, targets the three child `div`s of the parent to be styled. The `div`s are given a width and height of `1rem`, using `border-radius: 50%` to turn them from squares to circles. 82 | 83 | (4) `margin: 3rem 0.2rem` specifies that each circle has a top/bottom margin of `3rem` and left/right margin of `0.2rem` so that they do not directly touch each other, giving them some breathing room. 84 | 85 | (5) `animation` is a shorthand property for the various animation properties: `animation-name`, `animation-duration`, `animation-iteration-count`, `animation-direction` are used. 86 | 87 | (6) `nth-child(n)` targets the element which is the nth child of its parent. 88 | 89 | (7) `animation-delay` is used on the second and third `div` respectively, so that each element does not start the animation at the same time. 90 | 91 | 92 | 93 | ### 2. Loader Practice 94 | 95 | HTML: 96 | 97 | ```html 98 |
99 |
100 |
101 |
102 |
103 |
104 | ``` 105 | 106 | CSS: 107 | 108 | ```css 109 | @keyframes loader { 110 | from { 111 | opacity: 1; 112 | transform: scale(1, 1); 113 | } 114 | 115 | to { 116 | opacity: 0.2; 117 | transform: scale(0); 118 | } 119 | } 120 | 121 | .loader { 122 | display: flex; 123 | justify-content: center; 124 | } 125 | 126 | .loader > div { 127 | width: 1.5rem; 128 | height: 1.5rem; 129 | margin: 3rem 0.2rem; 130 | background: #8385aa; 131 | border-radius: 50%; 132 | animation: loader 0.6s ease-in-out infinite alternate; 133 | } 134 | 135 | .loader > div:nth-child(2) { 136 | animation-delay: .15s; 137 | } 138 | 139 | .loader > div:nth-child(3) { 140 | animation-delay: .3s; 141 | } 142 | 143 | .loader > div:nth-child(4) { 144 | animation-delay: .45s; 145 | } 146 | ``` 147 | 148 | [jsfiddle](http://jsfiddle.net/LacticAcidCYC/dbcz0gxL) 149 | 150 | 151 | 152 | ### 3. Box-sizing reset 153 | 154 | Usage: Resets the box-model so that `width`s and `height`s are not affected by their `border` or `padding`. 155 | 156 | HTML: 157 | 158 | ```html 159 |
border-box
160 |
content-box
161 | ``` 162 | 163 | CSS: 164 | 165 | ```css 166 | html { 167 | box-sizing: border-box; 168 | } 169 | *, 170 | *::before, 171 | *::after { 172 | box-sizing: inherit; 173 | } 174 | 175 | .box { 176 | display: inline-block; 177 | width: 150px; 178 | height: 150px; 179 | padding: 10px; 180 | background: tomato; 181 | color: white; 182 | border: 10px solid red; 183 | } 184 | 185 | .content-box { 186 | box-sizing: content-box; 187 | } 188 | ``` 189 | 190 | [codepen](https://codepen.io/lacticacidcyc/pen/JmBrpz) 191 | 192 | #### Explanation 193 | 194 | (1) `box-sizing: border-box` makes the addition of `padding` or `border`s not affect an element's `width` or `height`. 195 | 196 | (2) `box-sizing: inherit` makes an element respect its parent's `box-sizing` rule. 197 | 198 | 199 | 200 | ### 4. Circle 201 | 202 | Creates a circle shape with pure CSS. 203 | 204 | HTML: 205 | 206 | ```html 207 |
208 | ``` 209 | 210 | CSS: 211 | 212 | ```css 213 | .circle { 214 | background: tomato; 215 | width: 3rem; 216 | height: 3rem; 217 | border-radius: 50%; 218 | } 219 | ``` 220 | 221 | [codepen](https://codepen.io/lacticacidcyc/pen/NOBaJa) 222 | 223 | #### Explanation 224 | 225 | `border-radius: 50%` curves the borders of an element to create a circle. 226 | 227 | Since a circle has the same radius at any given point, the `width` and `height` must be the same. Differing values will create an ellipse. 228 | 229 | 230 | 231 | ### 5. Clearfix 232 | 233 | Ensures that an element self-clears its children. 234 | 235 | **Especially when using Float to set a picture on the left or right side. If the text next to it is shorter than the picture, without clearfix would cause the problem that the elements below are also next to the floated picture in the same block context.** 236 | 237 | *Note: This is only useful if you are still using float to build layouts. Please consider using a modern approach with flexbox layout or grid layout.* 238 | 239 | HTML: 240 | 241 | ```html 242 |
243 |
float a
244 |
float b
245 |
float c
246 |
247 |
float d
248 |
float e
249 |
float f
250 | ``` 251 | 252 | CSS: 253 | 254 | ```css 255 | .clearfix::after { 256 | content: ''; 257 | display: block; 258 | clear: both; 259 | } 260 | 261 | .floated { 262 | float: left; 263 | } 264 | ``` 265 | 266 | [codepen](https://codepen.io/lacticacidcyc/pen/mzjBNO) 267 | 268 | #### Explanation 269 | 270 | (1) `.clearfix::after` defines a pseudo-element. 271 | 272 | (2) `content: ''` allows the pseudo-element to affect layout. 273 | 274 | (3) `clear: both` indicates that the left, right or both sides of the element cannot be adjacent to earlier floated elements within the same block formatting context. 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 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | -------------------------------------------------------------------------------- /Web-Dev/Frontend/Frontend-Knowledge-Notes.md: -------------------------------------------------------------------------------- 1 | # 1. Deep Copy 2 | 3 | 4 | 5 | **Reference List**: 6 | 7 | 1. [Deep Copy vs Shallow Copy](https://juejin.im/post/5bc1ae9be51d450e8b140b0c) 8 | 2. [@jsmini/clone](https://github.com/jsmini/clone) 9 | 3. [Object.prototype.toString() in MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString) 10 | 4. [typeof in MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) 11 | 5. [Object.getPrototypeOf() in MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf) 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Web-Dev/Frontend/Some-CSS-notes.md: -------------------------------------------------------------------------------- 1 | ## Some Notes 2 | 3 | ### 1. repeat() 4 | 5 | #### *(1) Definition from MDN:* 6 | 7 | The `**repeat()**` [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS) function represents a repeated fragment of the track list, allowing a large number of columns or rows that exhibit a recurring pattern to be written in a more compact form. 8 | 9 | This function can be used in the CSS Grid properties [`grid-template-columns`](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns) and [`grid-template-rows`](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows). 10 | 11 | ### 12 | 13 | #### (2) Usage 14 | 15 | ```css 16 | /*example*/ 17 | ul { 18 | display: grid; 19 | /*grid-template-columns: 1fr 1fr 1fr 1fr;*/ 20 | grid-template-columns: repeat(4, 1fr); 21 | grid-gap: 1rem; 22 | } 23 | 24 | /*others*/ 25 | /* values */ 26 | repeat(4, 1fr) 27 | repeat(4, [col-start] 250px [col-end]) 28 | repeat(4, [col-start] 60% [col-end]) 29 | repeat(4, [col-start] 1fr [col-end]) 30 | repeat(4, [col-start] min-content [col-end]) 31 | repeat(4, [col-start] max-content [col-end]) 32 | repeat(4, [col-start] auto [col-end]) 33 | repeat(4, [col-start] minmax(100px, 1fr) [col-end]) 34 | repeat(4, [col-start] fit-content(200px) [col-end]) 35 | repeat(4, 10px [col-start] 30% [col-middle] auto [col-end]) 36 | repeat(4, [col-start] min-content [col-middle] max-content [col-end]) 37 | 38 | /* values */ 39 | repeat(auto-fill, 250px) 40 | repeat(auto-fit, 250px) 41 | repeat(auto-fill, [col-start] 250px [col-end]) 42 | repeat(auto-fit, [col-start] 250px [col-end]) 43 | repeat(auto-fill, [col-start] minmax(100px, 1fr) [col-end]) 44 | repeat(auto-fill, 10px [col-start] 30% [col-middle] 400px [col-end]) 45 | 46 | /* values */ 47 | repeat(4, 250px) 48 | repeat(4, [col-start] 250px [col-end]) 49 | repeat(4, [col-start] 60% [col-end]) 50 | repeat(4, [col-start] minmax(100px, 1fr) [col-end]) 51 | repeat(4, [col-start] fit-content(200px) [col-end]) 52 | repeat(4, 10px [col-start] 30% [col-middle] 400px [col-end]) 53 | ``` 54 | 55 | 56 | 57 | 58 | 59 | ### 2. CSS grid 60 | 61 | #### (1) grid-template-columns & grid-template-rows 62 | 63 | ```css 64 | grid-template-columns: none | | 65 | grid-template-rows: none | | 66 | 67 | I. : [? [ | ]] + ? 68 | 69 | II. : 70 | (1) : CSS length | CSS percentage | fr | min-content | max-content | auto 71 | (2) minmax( , ) 72 | (3) fit-content ( ) 73 | 74 | III. : repeat([ ] , [ ? ] + ?) 75 | 76 | IV. : name the grid lines to make the grid code easier to understand. 77 | repeat(4, [col-start] min-content [col-middle] max-content [col-end]) 78 | 79 | V. 80 | 81 | ``` 82 | 83 | -------------------------------------------------------------------------------- /Web-Dev/Web-Security/csrf-attack.md: -------------------------------------------------------------------------------- 1 | # CSRF (Cross-Site Request Forgery) Attacks & Protection 2 | 3 | ## 1. What is CSRF (also called 'one-click attack' or 'session riding') 4 | 5 | Cross-Site Request Forgery (CSRF) is an attack outlined in the [OWASP Top 10](https://www.veracode.com/directory/owasp-top-10) whereby **a malicious website will send a request to a web application that a user is already authenticated against from a different website**. This way an attacker can access functionality in a target web application via the victim's already authenticated browser. Targets include web applications like social media, in-browser email clients, online banking and web interfaces for network devices. 6 | 7 | 8 | 9 | ## 2. CSRF Basic 10 | 11 | - Malicious requests are sent from a site that a user visits to another site that the attacker believes the victim is validated against. 12 | - The malicious requests are routed to the target site via the victim’s browser, which is authenticated against the target site. 13 | - The vulnerability lies in the affected web application, not the victim’s browser or the site hosting the CSRF. 14 | 15 | 16 | 17 | ## 3. CSRF Attack Example 18 | 19 | (1) A user logged in the WebA and visit the pages on it. Simultaneously, WebA passed user's authentication and generate cookies in user's browser. 20 | 21 | (2) Now let’s say he happens to visit WebB. 22 | 23 | (3) It just so happens that this site is trying to attack people who uses WebA and has set up a CSRF attack on its site. For example, the attack will transfer $1,500.00 to account number 123456789. Somewhere on somemalicioussite.com, attackers have added this line of code: 24 | 25 | ```html 26 |