The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitbook
    └── assets
    │   ├── Sieve_of_Eratosthenes_animation.gif
    │   ├── binary-answer-1.png
    │   ├── binary-answer-2.png
    │   ├── bit-sum.png
    │   ├── bit-sum2 (1).png
    │   ├── bit-sum2 (2).png
    │   ├── bit-sum2.png
    │   ├── bit.png
    │   ├── bit1 (1).png
    │   ├── bit1.png
    │   ├── bit2.png
    │   ├── bit3.png
    │   ├── cross-product-right-hand-rule.png
    │   ├── image (1).png
    │   ├── image (2).png
    │   ├── image (3) (1).png
    │   ├── image (3).png
    │   ├── image.png
    │   ├── low-link-value.png
    │   ├── monostack.png
    │   ├── scc.png
    │   └── traveling-salesperson.png
├── README.md
├── SUMMARY.md
├── array
    ├── README.md
    ├── at-most-to-equal.md
    ├── count-inversions-in-an-array.md
    ├── interleaving-placement.md
    ├── kadane.md
    ├── left-to-right-state-transition.md
    ├── permutation.md
    ├── quick-select.md
    ├── sliding-window.md
    └── two-pointers.md
├── backtracking.md
├── binary-answer.key
├── binary-answer.md
├── binary-lifting.md
├── binary-search.md
├── binary-tree
    ├── README.md
    ├── avl-tree.md
    ├── binary-search-tree.md
    ├── serialization-and-deserialization.md
    └── traversal.md
├── bit-manipulation.md
├── company
    ├── README.md
    └── facebook.md
├── cpp
    ├── README.md
    ├── array.md
    ├── memset-3f.md
    └── overflow.md
├── data-structure
    ├── README.md
    ├── binary-indexed-tree.md
    ├── segment-tree-and-binary-index-tree.md
    ├── segment-tree.md
    ├── stack.md
    ├── trie.md
    ├── union-by-rank.png
    └── union-find.md
├── date.md
├── difference-array.md
├── discretization.md
├── divide-and-conquer.md
├── dynamic-programming
    ├── bitmask-dp.md
    ├── dp-on-subsets.md
    ├── dp-on-tree.md
    ├── dp-with-sorting.md
    ├── dynamic-programming.md
    ├── knapsack
    │   ├── 0-1-knapsack.md
    │   ├── README.md
    │   ├── bounded-knapsack.md
    │   └── unbounded-knapsack.md
    ├── selective-state-dp.md
    ├── traveling-salesperson.key
    └── travelling-salesperson.md
├── graph
    ├── README.md
    ├── bi-directional-breadth-first-search.md
    ├── bipartite.md
    ├── breadth-first-search.md
    ├── component-coloring.md
    ├── component-count.md
    ├── depth-first-search.md
    ├── eulerian-path.md
    ├── maximum-bipartite-matching.md
    ├── minimum-spanning-tree
    │   ├── README.md
    │   ├── kruskal.md
    │   └── prim.md
    ├── shortest-path
    │   ├── README.md
    │   ├── bellman-ford.md
    │   ├── dijkstra.md
    │   ├── floyd-warshall.md
    │   ├── johnson.md
    │   └── shortest-path-faster-algorithm.md
    ├── tarjan.md
    ├── topological-sort.md
    ├── tree-diameter.md
    └── tree-ring-order-traversal.md
├── gray-code.md
├── great-problems-for-practice.md
├── greedy
    ├── README.md
    ├── greedy-scheduling.md
    └── regret-greedy.md
├── interval-scheduling-maximization.md
├── io-optimization.md
├── k-subset-partitioning.md
├── line-sweep.md
├── longest-common-subsequence.md
├── longest-increasing-subsequence.md
├── math
    ├── README.md
    ├── catalan-number.md
    ├── combinatorics.md
    ├── factorial.md
    ├── factorization.md
    ├── fast-pow.md
    ├── gcd.md
    ├── geometry.md
    ├── get-digits.md
    ├── lcm.md
    ├── median-minimizes-sum-of-absolute-deviations.md
    ├── mode.md
    ├── modular-multiplicative-inverse.md
    ├── palindrome.md
    ├── prime-number.md
    ├── round-up.md
    ├── sieve-of-eratosthenes.md
    ├── stars-and-bars.md
    └── sum-of-sequence.md
├── meet-in-the-middle.md
├── minmax.md
├── miscellaneous
    ├── README.md
    ├── bin-packing.md
    ├── floyds-tortoise-and-hare.md
    ├── hungarian.md
    └── palindrome.md
├── mono-deque.md
├── monotonic-stack.md
├── offline-query.md
├── p-and-np.md
├── prefix-state-map.md
├── prefix-sum.md
├── random.md
├── reservoir-sampling.md
├── reverse-polish-notation.md
├── sort
    ├── README.md
    ├── bubble-sort.md
    ├── cycle-sort.md
    ├── heap-sort.md
    ├── merge-sort.md
    ├── quick-sort.md
    └── sorting.md
├── sqrt-decomposition.md
├── stl
    ├── README.md
    ├── cpp-stl.md
    ├── istringstream.md
    ├── lower_bound-upper_bound.md
    └── priority_queue.md
├── string
    ├── README.md
    ├── kmp.md
    ├── manacher.md
    ├── rabin-karp.md
    ├── string-processing.md
    └── z.md
└── summary.sh


/.gitbook/assets/Sieve_of_Eratosthenes_animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/Sieve_of_Eratosthenes_animation.gif


--------------------------------------------------------------------------------
/.gitbook/assets/binary-answer-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/binary-answer-1.png


--------------------------------------------------------------------------------
/.gitbook/assets/binary-answer-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/binary-answer-2.png


--------------------------------------------------------------------------------
/.gitbook/assets/bit-sum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit-sum.png


--------------------------------------------------------------------------------
/.gitbook/assets/bit-sum2 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit-sum2 (1).png


--------------------------------------------------------------------------------
/.gitbook/assets/bit-sum2 (2).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit-sum2 (2).png


--------------------------------------------------------------------------------
/.gitbook/assets/bit-sum2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit-sum2.png


--------------------------------------------------------------------------------
/.gitbook/assets/bit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit.png


--------------------------------------------------------------------------------
/.gitbook/assets/bit1 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit1 (1).png


--------------------------------------------------------------------------------
/.gitbook/assets/bit1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit1.png


--------------------------------------------------------------------------------
/.gitbook/assets/bit2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit2.png


--------------------------------------------------------------------------------
/.gitbook/assets/bit3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/bit3.png


--------------------------------------------------------------------------------
/.gitbook/assets/cross-product-right-hand-rule.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/cross-product-right-hand-rule.png


--------------------------------------------------------------------------------
/.gitbook/assets/image (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/image (1).png


--------------------------------------------------------------------------------
/.gitbook/assets/image (2).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/image (2).png


--------------------------------------------------------------------------------
/.gitbook/assets/image (3) (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/image (3) (1).png


--------------------------------------------------------------------------------
/.gitbook/assets/image (3).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/image (3).png


--------------------------------------------------------------------------------
/.gitbook/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/image.png


--------------------------------------------------------------------------------
/.gitbook/assets/low-link-value.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/low-link-value.png


--------------------------------------------------------------------------------
/.gitbook/assets/monostack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/monostack.png


--------------------------------------------------------------------------------
/.gitbook/assets/scc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/scc.png


--------------------------------------------------------------------------------
/.gitbook/assets/traveling-salesperson.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/.gitbook/assets/traveling-salesperson.png


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | # README
 2 | 
 3 | I put all my notes for algorithms here.
 4 | 
 5 | * Gitbook: [https://liuzhenglaichn.gitbook.io/algorithm/](https://liuzhenglaichn.gitbook.io/algorithm/)
 6 | * Github Repo: [https://github.com/lzl124631x/algorithm](https://github.com/lzl124631x/algorithm)
 7 | 
 8 | ## Remember during interview
 9 | 
10 | * Disambiguate the problem, ask questions, try to understand the inputs and outputs.
11 | * Think about edge cases.
12 | * First talk about the brute force solution, then think about better approaches.
13 | * Think out loud!
14 | 
15 | ## Resources
16 | 
17 | William Fiset
18 | 
19 | * [https://www.youtube.com/channel/UCD8yeTczadqdARzQUp29PJw](https://www.youtube.com/channel/UCD8yeTczadqdARzQUp29PJw)
20 | * [https://github.com/williamfiset/Algorithms](https://github.com/williamfiset/Algorithms)
21 | 


--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
  1 | # Algorithm
  2 | 
  3 | - [Array](array/README.md)
  4 |   * [At Most To Equal](array/at-most-to-equal.md)
  5 |   * [Count Inversions In An Array](array/count-inversions-in-an-array.md)
  6 |   * [Interleaving Placement](array/interleaving-placement.md)
  7 |   * [Kadane](array/kadane.md)
  8 |   * [Left To Right State Transition](array/left-to-right-state-transition.md)
  9 |   * [Permutation](array/permutation.md)
 10 |   * [Quick Select](array/quick-select.md)
 11 |   * [Sliding Window](array/sliding-window.md)
 12 |   * [Two Pointers](array/two-pointers.md)
 13 | - [Binary Tree](binary-tree/README.md)
 14 |   * [Avl Tree](binary-tree/avl-tree.md)
 15 |   * [Binary Search Tree](binary-tree/binary-search-tree.md)
 16 |   * [Serialization And Deserialization](binary-tree/serialization-and-deserialization.md)
 17 |   * [Traversal](binary-tree/traversal.md)
 18 | - [Company](company/README.md)
 19 |   * [Facebook](company/facebook.md)
 20 | - [Cpp](cpp/README.md)
 21 |   * [Array](cpp/array.md)
 22 |   * [Memset 3 F](cpp/memset-3f.md)
 23 |   * [Overflow](cpp/overflow.md)
 24 | - [Data Structure](data-structure/README.md)
 25 |   * [Binary Indexed Tree](data-structure/binary-indexed-tree.md)
 26 |   * [Segment Tree And Binary Index Tree](data-structure/segment-tree-and-binary-index-tree.md)
 27 |   * [Segment Tree](data-structure/segment-tree.md)
 28 |   * [Stack](data-structure/stack.md)
 29 |   * [Trie](data-structure/trie.md)
 30 |   * [Union Find](data-structure/union-find.md)
 31 | - [Dynamic Programming](dynamic-programming/dynamic-programming.md)
 32 |   - [Knapsack](dynamic-programming/knapsack/README.md)
 33 |     * [0 1 Knapsack](dynamic-programming/knapsack/0-1-knapsack.md)
 34 |     * [Bounded Knapsack](dynamic-programming/knapsack/bounded-knapsack.md)
 35 |     * [Unbounded Knapsack](dynamic-programming/knapsack/unbounded-knapsack.md)
 36 |   * [Bitmask Dp](dynamic-programming/bitmask-dp.md)
 37 |   * [Dp On Subsets](dynamic-programming/dp-on-subsets.md)
 38 |   * [Dp On Tree](dynamic-programming/dp-on-tree.md)
 39 |   * [Dp With Sorting](dynamic-programming/dp-with-sorting.md)
 40 |   * [Selective State Dp](dynamic-programming/selective-state-dp.md)
 41 |   * [Travelling Salesperson](dynamic-programming/travelling-salesperson.md)
 42 | - [Graph](graph/README.md)
 43 |   - [Minimum Spanning Tree](graph/minimum-spanning-tree/README.md)
 44 |     * [Kruskal](graph/minimum-spanning-tree/kruskal.md)
 45 |     * [Prim](graph/minimum-spanning-tree/prim.md)
 46 |   - [Shortest Path](graph/shortest-path/README.md)
 47 |     * [Bellman Ford](graph/shortest-path/bellman-ford.md)
 48 |     * [Dijkstra](graph/shortest-path/dijkstra.md)
 49 |     * [Floyd Warshall](graph/shortest-path/floyd-warshall.md)
 50 |     * [Johnson](graph/shortest-path/johnson.md)
 51 |     * [Shortest Path Faster Algorithm](graph/shortest-path/shortest-path-faster-algorithm.md)
 52 |   * [Bi Directional Breadth First Search](graph/bi-directional-breadth-first-search.md)
 53 |   * [Bipartite](graph/bipartite.md)
 54 |   * [Breadth First Search](graph/breadth-first-search.md)
 55 |   * [Component Coloring](graph/component-coloring.md)
 56 |   * [Component Count](graph/component-count.md)
 57 |   * [Depth First Search](graph/depth-first-search.md)
 58 |   * [Eulerian Path](graph/eulerian-path.md)
 59 |   * [Maximum Bipartite Matching](graph/maximum-bipartite-matching.md)
 60 |   * [Tarjan](graph/tarjan.md)
 61 |   * [Topological Sort](graph/topological-sort.md)
 62 |   * [Tree Diameter](graph/tree-diameter.md)
 63 |   * [Tree Ring Order Traversal](graph/tree-ring-order-traversal.md)
 64 | - [Greedy](greedy/README.md)
 65 |   * [Greedy Scheduling](greedy/greedy-scheduling.md)
 66 |   * [Regret Greedy](greedy/regret-greedy.md)
 67 | - [Math](math/README.md)
 68 |   * [Catalan Number](math/catalan-number.md)
 69 |   * [Combinatorics](math/combinatorics.md)
 70 |   * [Factorial](math/factorial.md)
 71 |   * [Factorization](math/factorization.md)
 72 |   * [Fast Pow](math/fast-pow.md)
 73 |   * [Gcd](math/gcd.md)
 74 |   * [Geometry](math/geometry.md)
 75 |   * [Get Digits](math/get-digits.md)
 76 |   * [Lcm](math/lcm.md)
 77 |   * [Median Minimizes Sum Of Absolute Deviations](math/median-minimizes-sum-of-absolute-deviations.md)
 78 |   * [Mode](math/mode.md)
 79 |   * [Modular Multiplicative Inverse](math/modular-multiplicative-inverse.md)
 80 |   * [Palindrome](math/palindrome.md)
 81 |   * [Prime Number](math/prime-number.md)
 82 |   * [Round Up](math/round-up.md)
 83 |   * [Sieve Of Eratosthenes](math/sieve-of-eratosthenes.md)
 84 |   * [Stars And Bars](math/stars-and-bars.md)
 85 |   * [Sum Of Sequence](math/sum-of-sequence.md)
 86 | - [Miscellaneous](miscellaneous/README.md)
 87 |   * [Bin Packing](miscellaneous/bin-packing.md)
 88 |   * [Floyds Tortoise And Hare](miscellaneous/floyds-tortoise-and-hare.md)
 89 |   * [Hungarian](miscellaneous/hungarian.md)
 90 |   * [Palindrome](miscellaneous/palindrome.md)
 91 | - [Sort](sort/README.md)
 92 |   * [Bubble Sort](sort/bubble-sort.md)
 93 |   * [Cycle Sort](sort/cycle-sort.md)
 94 |   * [Heap Sort](sort/heap-sort.md)
 95 |   * [Merge Sort](sort/merge-sort.md)
 96 |   * [Quick Sort](sort/quick-sort.md)
 97 |   * [Sorting](sort/sorting.md)
 98 | - [Stl](stl/README.md)
 99 |   * [Cpp Stl](stl/cpp-stl.md)
100 |   * [Istringstream](stl/istringstream.md)
101 |   * [Lower Bound Upper Bound](stl/lower_bound-upper_bound.md)
102 |   * [Priority Queue](stl/priority_queue.md)
103 | - [String](string/README.md)
104 |   * [Kmp](string/kmp.md)
105 |   * [Manacher](string/manacher.md)
106 |   * [Rabin Karp](string/rabin-karp.md)
107 |   * [String Processing](string/string-processing.md)
108 |   * [Z](string/z.md)
109 | * [Backtracking](backtracking.md)
110 | * [Binary Answer](binary-answer.md)
111 | * [Binary Lifting](binary-lifting.md)
112 | * [Binary Search](binary-search.md)
113 | * [Bit Manipulation](bit-manipulation.md)
114 | * [Date](date.md)
115 | * [Difference Array](difference-array.md)
116 | * [Discretization](discretization.md)
117 | * [Divide And Conquer](divide-and-conquer.md)
118 | * [Gray Code](gray-code.md)
119 | * [Great Problems For Practice](great-problems-for-practice.md)
120 | * [Interval Scheduling Maximization](interval-scheduling-maximization.md)
121 | * [Io Optimization](io-optimization.md)
122 | * [K Subset Partitioning](k-subset-partitioning.md)
123 | * [Line Sweep](line-sweep.md)
124 | * [Longest Common Subsequence](longest-common-subsequence.md)
125 | * [Longest Increasing Subsequence](longest-increasing-subsequence.md)
126 | * [Meet In The Middle](meet-in-the-middle.md)
127 | * [Minmax](minmax.md)
128 | * [Mono Deque](mono-deque.md)
129 | * [Monotonic Stack](monotonic-stack.md)
130 | * [Offline Query](offline-query.md)
131 | * [P And Np](p-and-np.md)
132 | * [Prefix State Map](prefix-state-map.md)
133 | * [Prefix Sum](prefix-sum.md)
134 | * [Random](random.md)
135 | * [Reservoir Sampling](reservoir-sampling.md)
136 | * [Reverse Polish Notation](reverse-polish-notation.md)
137 | * [Sqrt Decomposition](sqrt-decomposition.md)
138 | 


--------------------------------------------------------------------------------
/array/README.md:
--------------------------------------------------------------------------------
1 | # Array
2 | 
3 | 


--------------------------------------------------------------------------------
/array/at-most-to-equal.md:
--------------------------------------------------------------------------------
1 | # "At Most" to "Equal"
2 | 
3 | Exactly `k` times = At Most `k` times - At Most `k - 1` times.
4 | 
5 | ## Problems
6 | 
7 | * [930. Binary Subarrays With Sum (Medium)](https://leetcode.com/problems/binary-subarrays-with-sum/)
8 | * [992. Subarrays with K Different Integers (Hard)](https://leetcode.com/problems/subarrays-with-k-different-integers/)
9 | * [1248. Count Number of Nice Subarrays (Medium)](https://leetcode.com/problems/count-number-of-nice-subarrays/)


--------------------------------------------------------------------------------
/array/count-inversions-in-an-array.md:
--------------------------------------------------------------------------------
 1 | # Count Inversions In An Array
 2 | 
 3 | In array `A`, two elements `A[i]` and `A[j]` form an inversion if `A[i] > A[j]` and `i < j`
 4 | 
 5 | _The count of inversion_ of an array indicates how far the array is from sorted. If the array is already sorted, its inversion count is 0. If the array is sorted in the reverse order then its inversion count is the maximum.
 6 | 
 7 | ### Brute force
 8 | 
 9 | Brute force method is trivial -- for each number, count how many number to its right is smaller than it. The time complexit is `O(N^2)` and space complexity is `O(1)`.
10 | 
11 | ### Merge Sort \(Divide and Conquer\)
12 | 
13 | During the merge, if we need to select a number `x` from the right part, we can add the inversion count by the count of remaining items in the left part, because they must be all greater than `x`.
14 | 
15 | For example, assume we want to merge `[1,3]` and `[0,2]`.
16 | 
17 | * we need to first select the `0` and there are `2` numbers left in the left part, we add the count by `2`.
18 | * select `1` from the left part, leave the count unchanged.
19 | * select `2` from the right part, add the count by `1` because there is only one `3` left in the left part.
20 | * select `3` from the left part, leave the count unchanged.
21 | 
22 | So in total there are `2 + 1 = 3` inversions.
23 | 
24 | ```cpp
25 | // Time: O(NlogN)
26 | // Space: O(N)
27 | long long _mergeSort(vector<int> &A, vector<int> &tmp, int start, int end) {
28 |     if (start + 1 >= end) return 0;
29 |     long long mid = (start + end) / 2, cnt = 0;
30 |     cnt += _mergeSort(A, tmp, start, mid);
31 |     cnt += _mergeSort(A, tmp, mid, end);
32 |     for (int i = start, j = mid, k = 0; i < mid || j < end; ++k) {
33 |         if (i >= mid || (j < end && A[j] < A[i])) {
34 |             tmp[k] = A[j++];
35 |             cnt += mid - i;
36 |         } else tmp[k] = A[i++];
37 |     }
38 |     for (int i = start; i < end; ++i) A[i] = tmp[i - start];
39 |     return cnt;
40 | }
41 | long long mergeSort(vector<int> &A, int start, int end) {
42 |     vector<int> tmp(A.size());
43 |     return _mergeSort(A, tmp, start, end);
44 | }
45 | long long countInversions(vector<int>& A) {
46 |     return mergeSort(A, 0, A.size());
47 | }
48 | ```
49 | 
50 | 


--------------------------------------------------------------------------------
/array/interleaving-placement.md:
--------------------------------------------------------------------------------
1 | # Interleaving Placement
2 | 
3 | * [767. Reorganize String (Medium)](https://leetcode.com/problems/reorganize-string/)
4 | * [1054. Distant Barcodes (Medium)](https://leetcode.com/problems/distant-barcodes/)


--------------------------------------------------------------------------------
/array/kadane.md:
--------------------------------------------------------------------------------
 1 | # Kadane
 2 | 
 3 | Kadane's algorithm is used to find the maximum sum subarray from a given array. It's a DP algorithm.
 4 | 
 5 | ## Algorithm
 6 | 
 7 | Test your code with [53. Maximum Subarray (Medium)](https://leetcode.com/problems/maximum-subarray).
 8 | 
 9 | ```cpp
10 | // Time: O(N)
11 | // Space: O(1)
12 | int kadane(vector<int> &A) {
13 |     int ans = INT_MIN, mx = 0;
14 |     for (int n : A) {
15 |         mx = max(mx + n, n);
16 |         ans = max(ans, mx);
17 |     }
18 |     return ans;
19 | }
20 | ```
21 | 
22 | ## Problems
23 | 
24 | * [53. Maximum Subarray (Medium)](https://leetcode.com/problems/maximum-subarray) **Direct Application**
25 | * [363. Max Sum of Rectangle No Larger Than K (Hard)](https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/)
26 | * [2272. Substring With Largest Variance (Hard)](https://leetcode.com/problems/substring-with-largest-variance)


--------------------------------------------------------------------------------
/array/left-to-right-state-transition.md:
--------------------------------------------------------------------------------
 1 | # Left-to-Right State Transition
 2 | 
 3 | ## Problems
 4 | 
 5 | * [1653. Minimum Deletions to Make String Balanced (Medium)](https://leetcode.com/problems/minimum-deletions-to-make-string-balanced/)
 6 | * [1664. Ways to Make a Fair Array (Medium)](https://leetcode.com/problems/ways-to-make-a-fair-array/)
 7 | * [1769. Minimum Number of Operations to Move All Balls to Each Box (Medium)](https://leetcode.com/problems/minimum-number-of-operations-to-move-all-balls-to-each-box/)
 8 | * [2033. Minimum Operations to Make a Uni-Value Grid (Medium)](https://leetcode.com/problems/minimum-operations-to-make-a-uni-value-grid/)
 9 | * [2155. All Divisions With the Highest Score of a Binary Array (Medium)](https://leetcode.com/problems/all-divisions-with-the-highest-score-of-a-binary-array/)
10 | * [2448. Minimum Cost to Make Array Equal (Hard)](https://leetcode.com/problems/minimum-cost-to-make-array-equal)
11 | * [2615. Sum of Distances (Medium)](https://leetcode.com/problems/sum-of-distances)


--------------------------------------------------------------------------------
/array/permutation.md:
--------------------------------------------------------------------------------
 1 | # Permutation
 2 | 
 3 | 
 4 | 
 5 | ### Next Permutation
 6 | 
 7 | [31. Next Permutation \(Medium\)](https://leetcode.com/problems/next-permutation/)
 8 | 
 9 | Given a permutation, get the next permutation.
10 | 
11 | Example:
12 | 
13 | * given `[2,1,3]`, the next permutation is `[2,3,1]`.
14 | * given `[1,2,1]`, the next permutation is `[2,1,1]`.
15 | 
16 | ```cpp
17 | /**
18 |  * Returns true if the input `nums` is already the maximum in lexicographical order.
19 |  */
20 | bool nextPermutation(vector<int>& nums) {
21 |     int i = nums.size() - 2, j = nums.size() - 1;
22 |     while (i >= 0 && nums[i] >= nums[i + 1]) --i;
23 |     if (i >= 0) {
24 |         while (j > i && nums[j] <= nums[i]) --j;
25 |         swap(nums[i], nums[j]);
26 |     }
27 |     reverse(nums.begin() + i + 1, nums.end());
28 |     return i >= 0;
29 | }
30 | ```
31 | 
32 | The first section
33 | 
34 | ```cpp
35 | int i = nums.size() - 2;
36 | while (i >= 0 && nums[i] >= nums[i + 1]) --i;
37 | ```
38 | 
39 | is looking for the last element in front of the descending subarray.
40 | 
41 | For example, `nums = [2,1,4,3]`, then `i` will point to `1` which is the last element in front of the descending subarray `[4, 3]`.
42 | 
43 | If not found, it means that the whole array is descending. The next permutation will be the reverse of the input array.
44 | 
45 | If found, we can swap it with the smallest element greater than itself, which is covered in the `if` condition.
46 | 
47 | ```cpp
48 | if (i >= 0) {
49 |     while (j > i && nums[j] <= nums[i]) --j;
50 |     swap(nums[i], nums[j]);
51 | }
52 | ```
53 | 
54 | And to get the next permutation, we need to reverse the subarray starting from `nums[i + 1]` to the end.
55 | 
56 | For example, `nums = [1,6,3,5,4,2]`, then `i = 2` pointing to `3` and `j = 4` pointing to `4`. We swap `nums[i]` and `nums[j]` so swapping them gives `[1,6,4,5,3,2]`, then reverse the subarray starting from `2` to the end, getting `[1,6,4,2,3,5]`.
57 | 
58 | ### Permutations \(distinct digits\)
59 | 
60 | [46. Permutations \(Medium\)](https://leetcode.com/problems/permutations/)
61 | 
62 | See [my notes here](https://github.com/lzl124631x/LeetCode/tree/master/leetcode/46.%20Permutations)
63 | 
64 | ### Permutations \(might contain duplicate\)
65 | 
66 | [47. Permutations II \(Medium\)](https://leetcode.com/problems/permutations-ii/)
67 | 
68 | See [my notes here](https://github.com/lzl124631x/LeetCode/tree/master/leetcode/47.%20Permutations%20II)
69 | 
70 | ### Problems
71 | 
72 | * [46. Permutations \(Medium\)](https://leetcode.com/problems/permutations/)
73 | * [31. Next Permutation \(Medium\)](https://leetcode.com/problems/next-permutation/)
74 | * [47. Permutations II \(Medium\)](https://leetcode.com/problems/permutations-ii/)
75 | 
76 | 


--------------------------------------------------------------------------------
/array/quick-select.md:
--------------------------------------------------------------------------------
 1 | # Quick Select
 2 | 
 3 | Quickselect is a selection algorithm to find the k-th smallest/largest element in an unordered list. It uses the `partition` method in Quick Sort. The difference is, instead of recurring for both sides \(after finding pivot\), it recurs only for the part that contains the k-th smallest/largest element.
 4 | 
 5 | The time complexity is `O(N)` on average, and `O(N^2)` in the worst case.
 6 | 
 7 | ## Implementation
 8 | 
 9 | Quick select with elements sorted in ascending order.
10 | 
11 | ```cpp
12 | // OJ: https://leetcode.com/problems/kth-largest-element-in-an-array/
13 | // Author: github.com/lzl124631x
14 | // Time: O(N) on averge, O(N^2) in the worst case
15 | // Space: O(1)
16 | class Solution {
17 |     int partition(vector<int> &A, int L, int R) {
18 |         int i = L, pivotIndex = L + rand() % (R - L + 1), pivot = A[pivotIndex];
19 |         swap(A[pivotIndex], A[R]);
20 |         for (int j = L; j < R; ++j) {
21 |             if (A[j] < pivot) swap(A[i++], A[j]);
22 |         }
23 |         swap(A[i], A[R]);
24 |         return i;
25 |     }
26 | public:
27 |     int findKthLargest(vector<int>& A, int k) {
28 |         int L = 0, R = A.size() - 1;
29 |         k = A.size() - k + 1;
30 |         while (true) {
31 |             int M = partition(A, L, R);
32 |             if (M + 1 == k) return A[M];
33 |             if (M + 1 > k) R = M - 1;
34 |             else L = M + 1;
35 |         }
36 |     }
37 | };
38 | ```
39 | 
40 | Quick select with elements sorted in descending order.
41 | 
42 | ```cpp
43 | // OJ: https://leetcode.com/problems/kth-largest-element-in-an-array/
44 | // Author: github.com/lzl124631x
45 | // Time: O(N) on averge, O(N^2) in the worst case
46 | // Space: O(1)
47 | class Solution {
48 |     int partition(vector<int> &A, int L, int R) {
49 |         int i = L, pivotIndex = L + rand() % (R - L + 1), pivot = A[pivotIndex];
50 |         swap(A[pivotIndex], A[R]);
51 |         for (int j = L; j < R; ++j) {
52 |             if (A[j] > pivot) swap(A[i++], A[j]);
53 |         }
54 |         swap(A[i], A[R]);
55 |         return i;
56 |     }
57 | public:
58 |     int findKthLargest(vector<int>& A, int k) {
59 |         int L = 0, R = A.size() - 1;
60 |         while (true) {
61 |             int M = partition(A, L, R);
62 |             if (M + 1 == k) return A[M];
63 |             if (M + 1 > k) R = M - 1;
64 |             else L = M + 1;
65 |         }
66 |     }
67 | };
68 | ```
69 | 
70 | Or STL
71 | 
72 | ```cpp
73 | // OJ: https://leetcode.com/problems/kth-largest-element-in-an-array/
74 | // Author: github.com/lzl124631x
75 | // Time: O(N) on average, O(N^2) in the worst case
76 | // Space: O(1)
77 | class Solution {
78 | public:
79 |     int findKthLargest(vector<int>& A, int k) {
80 |         nth_element(begin(A), begin(A) + k - 1, end(A), greater<int>());
81 |         return A[k - 1];
82 |     }
83 | };
84 | ```
85 | 
86 | ## Reference
87 | 
88 | * [Quickselect Algorithm - GeeksforGeeks](https://www.geeksforgeeks.org/quickselect-algorithm/)
89 | 
90 | ## Problems
91 | 
92 | * [215. Kth Largest Element in an Array \(Medium\)](https://leetcode.com/problems/kth-largest-element-in-an-array/)
93 | * [973. K Closest Points to Origin \(Medium\)](https://leetcode.com/problems/k-closest-points-to-origin/)
94 | * [1471. The k Strongest Values in an Array (Medium)](https://leetcode.com/problems/the-k-strongest-values-in-an-array/)
95 | 


--------------------------------------------------------------------------------
/array/two-pointers.md:
--------------------------------------------------------------------------------
 1 | # Two Pointers
 2 | 
 3 | ## Problems
 4 | 
 5 | * [16. 3Sum Closest \(Medium\)](https://leetcode.com/problems/3sum-closest/)
 6 | * [350. Intersection of Two Arrays II (Easy)](https://leetcode.com/problems/intersection-of-two-arrays-ii)
 7 | * [484. Find Permutation (Medium)](https://leetcode.com/problems/find-permutation)
 8 | * [567. Permutation in String \(Medium\)](https://leetcode.com/problems/permutation-in-string/)
 9 | * [948. Bag of Tokens (Medium)](https://leetcode.com/problems/bag-of-tokens/)
10 | * [1871. Jump Game VII (Medium)](https://leetcode.com/problems/jump-game-vii/)


--------------------------------------------------------------------------------
/backtracking.md:
--------------------------------------------------------------------------------
 1 | # Backtracking
 2 | 
 3 | The rough time complexity estimation of a backtracking solution might seem very high, but since there are lots of cases skipped, usually such solution can pass.
 4 | 
 5 | ## Problems
 6 | 
 7 | * [51. N-Queens (Hard)](https://leetcode.com/problems/n-queens/)
 8 | * [473. Matchsticks to Square (Medium)](https://leetcode.com/problems/matchsticks-to-square/)
 9 | * [1723. Find Minimum Time to Finish All Jobs (Hard)](https://leetcode.com/problems/find-minimum-time-to-finish-all-jobs/)
10 | * [2014. Longest Subsequence Repeated k Times (Hard)](https://leetcode.com/problems/longest-subsequence-repeated-k-times/)
11 | 
12 | ### Subset
13 | 
14 | * [698. Partition to K Equal Sum Subsets (Medium)](https://leetcode.com/problems/partition-to-k-equal-sum-subsets/)
15 | * [2597. The Number of Beautiful Subsets (Medium)](https://leetcode.com/problems/the-number-of-beautiful-subsets)
16 | 


--------------------------------------------------------------------------------
/binary-answer.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/binary-answer.key


--------------------------------------------------------------------------------
/binary-answer.md:
--------------------------------------------------------------------------------
 1 | # Binary Answer
 2 | 
 3 | ## What's Binary Answer
 4 | When the search range is small, the binary answer problems are solvable by linear scaning the answer range. For example, assume the answer range is `[0, 100]`, we can check `0`, then `1`, ..., then `100`, and we return the maximum number that is valid.
 5 | 
 6 | However, when the answer range is large, say `[0, 10^5]`, linear scanning the entire answer range will get TLE. 
 7 | 
 8 | So, instead of doing `O(N)` linear scanning, we binary search in the answer range which reduces the time complexity to `O(logN)`.
 9 | 
10 | ## When can we use Binary Answer?
11 | 
12 | We can use "Binary Answer" solution if we can write a predicate function `valid(i)` that has **monotocity**:
13 | 
14 | * If `valid(i) == true`, then `valid(j) == true` for all `j <= i`.
15 | * If `valid(i) == false`, then `valid(j) == false` for all `j >= i`.
16 | 
17 | ![](.gitbook/assets/binary-answer-1.png)
18 | 
19 | ## Algorithm
20 | 
21 | Our goal is the find the maximum `i` that `valid(i) == true`.
22 | 
23 | We can use two pointers `L = minVal, R = maxVal`, and keep using binary search to move the pointers towards each other until they swap order. In the end, `R` will point to the largest value that is valid, `L` will point to the smallest value that is invalid.
24 | 
25 | ![](.gitbook/assets/binary-answer-2.png)
26 | 
27 | ## Pseudo Code
28 | 
29 | Assume the answer range is monotonically going from valid to invalid, and we are looking for the maximum valid value.
30 | 
31 | ```cpp
32 | int L = minVal, R = maxVal
33 | while (L <= R) {
34 |     int M = (L + R) / 2;
35 |     if (valid(M)) L = M + 1;
36 |     else R = M - 1;
37 | }
38 | return R >= minVal ? R : NOT_FOUND;
39 | ```
40 | 
41 | If we are looking for the minimal invalid value, simply return `L <= maxVal ? L : NOT_FOUND`.
42 | 
43 | ## Problems
44 | 
45 | * [410. Split Array Largest Sum \(Hard\)](https://leetcode.com/problems/split-array-largest-sum/)
46 | * [668. Kth Smallest Number in Multiplication Table (Hard)](https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/)
47 | * [718. Maximum Length of Repeated Subarray (Medium)](https://leetcode.com/problems/maximum-length-of-repeated-subarray/)
48 | * [719. Find K-th Smallest Pair Distance (Hard)](https://leetcode.com/problems/find-k-th-smallest-pair-distance/)
49 | * [778. Swim in Rising Water (Hard)](https://leetcode.com/problems/swim-in-rising-water/)
50 | * [1044. Longest Duplicate Substring \(Hard\)](https://leetcode.com/problems/longest-duplicate-substring/)
51 | * [1062. Longest Repeating Substring (Medium)](https://leetcode.com/problems/longest-repeating-substring/)
52 | * [1283. Find the Smallest Divisor Given a Threshold (Medium)](https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold/)
53 | * [1300. Sum of Mutated Array Closest to Target \(Medium\)](https://leetcode.com/problems/sum-of-mutated-array-closest-to-target/)
54 | * [1482. Minimum Number of Days to Make m Bouquets \(Medium\)](https://leetcode.com/problems/minimum-number-of-days-to-make-m-bouquets/)
55 | * [1648. Sell Diminishing-Valued Colored Balls (Medium)](https://leetcode.com/problems/sell-diminishing-valued-colored-balls/)
56 | * [1802. Maximum Value at a Given Index in a Bounded Array (Medium)](https://leetcode.com/problems/maximum-value-at-a-given-index-in-a-bounded-array/)
57 | * [1870. Minimum Speed to Arrive on Time (Medium)](https://leetcode.com/problems/minimum-speed-to-arrive-on-time/)


--------------------------------------------------------------------------------
/binary-lifting.md:
--------------------------------------------------------------------------------
 1 | # Binary Lifting
 2 | 
 3 | This technique is based on the fact that every integer can be represented in binary form.
 4 | 
 5 | Through pre-processing, a sparse table `dp[i][v]` can be calculated which stores the `2^i`th parent of vertex `v`, where `0 <= i <= logN`. (Example: [1483. Kth Ancestor of a Tree Node \(Hard\)](https://leetcode.com/problems/kth-ancestor-of-a-tree-node/)) This pre-processing takes `O(NlogN)` time.
 6 | 
 7 | When we want to get the `k`th parent of `v`, we can first break `k` into the binary representation `k = 2^p1 + 2^p2 + 2^p3 + ... + 2^pj` where `p1, ..., pj` are the indices where `k` has bit value `1`.
 8 | 
 9 | So we can get the `2^p1`th, `2^p2`th, ... `2^pj`th parent in any order to get `k`th parent of `v`.
10 | 
11 | Example: to get the `6`th parent of `v`, since `6 = 2^1 + 2^2`, the answer can be `P[1][ P[2][v] ]` or `P[2][ P[1][v] ]`.
12 | 
13 | Hence we can reduce the time complexity of getting the `K`th parent from `O(K)` to `O(logK)`.
14 | 
15 | ## Problems
16 | 
17 | * [1483. Kth Ancestor of a Tree Node \(Hard\)](https://leetcode.com/problems/kth-ancestor-of-a-tree-node/)
18 | 
19 | 


--------------------------------------------------------------------------------
/binary-tree/README.md:
--------------------------------------------------------------------------------
1 | # Binary Tree
2 | 
3 | 


--------------------------------------------------------------------------------
/binary-tree/avl-tree.md:
--------------------------------------------------------------------------------
 1 | # Avl Tree
 2 | 
 3 | An AVL Tree \(named after Soviet inventors **A**delson-**V**elsky and **L**andis\) is a self-balancing binary search tree \(BST\). It was the first such data structure to be invented.
 4 | 
 5 | In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Lookup, insertion, and deletion all take `O(logN)` time in both the average and worst cases, where `n` is the number of nodes in the tree prior to the operation. Insertions and deletions may require the tree to be rebalanced by one or more tree rotations.
 6 | 
 7 | ### Implementation
 8 | 
 9 | ```cpp
10 | class AvlTreeNode {
11 | private:
12 |     int diff = 0;
13 | public:
14 |     int value;
15 |     AvlTreeNode *left = NULL, *right = NULL;
16 |     AvlTreeNode(int val): value(val) {};
17 | }
18 | 
19 | class AvlTree {
20 | private:
21 |     AvlTreeNode *root;
22 |     AvlTreeNode *find(AclTreeNode *node, int target) {
23 |         if (!node) return NULL;
24 |         if (node->val == target) return node;
25 |         if (node->val > target) return find(node->left, target);
26 |         return find(node->right, target);
27 |     }
28 | public:
29 |     void insert(int val) {
30 |         if (!root) {
31 |             root = new AvlTree(val);
32 |         }
33 |     }
34 | 
35 |     AvlTreeNode* find(int val) {
36 |         return find(root, val);
37 |     }
38 | 
39 |     void remove(int val) {
40 | 
41 |     }
42 | }
43 | ```
44 | 
45 | ### Reference
46 | 
47 | * [Wiki](https://en.wikipedia.org/wiki/AVL_tree)
48 | * [AVL Tree \| Set 1 \(Insertion\)](https://www.geeksforgeeks.org/avl-tree-set-1-insertion/)
49 | 
50 | 


--------------------------------------------------------------------------------
/binary-tree/binary-search-tree.md:
--------------------------------------------------------------------------------
 1 | # Binary Search Tree
 2 | 
 3 | **Binary Search Tree** is a node-based binary tree data structure which has the following properties:
 4 | 
 5 | * The left subtree of a node contains only nodes with keys lesser than the node’s key.
 6 | * The right subtree of a node contains only nodes with keys greater than the node’s key.
 7 | * The left and right subtree each must also be a binary search tree.
 8 | 
 9 | ### Implementation
10 | 
11 | ```cpp
12 | struct TreeNode {
13 |     int val;
14 |     TreeNode *left, *right;
15 |     TreeNode(int val): val(val), left(NULL), right(NULL) {};
16 | };
17 | 
18 | class BinarySearchTree {
19 | private:
20 |     TreeNode *find(TreeNode *node, int target) {
21 |         if (!node || node->val == target) return node;
22 |         if (node->val > target) return find(node->left, target);
23 |         return find(node->right, target);
24 |     }
25 |     TreeNode *insert(TreeNode *node, int val) {
26 |         if (!node) return new TreeNode(val);
27 |         if (node->val < val) node->right = insert(node->right, val);
28 |         else if (node->val > val) node->left = insert(node->left, val);
29 |         return node;
30 |     }
31 | public:
32 |     TreeNode *root = NULL;
33 |     void insert(int val) {
34 |         root = insert(root, val);
35 |     }
36 | 
37 |     TreeNode* find(int target) {
38 |         return find(root, target);
39 |     }
40 | 
41 |     bool remove(int target) {
42 |         TreeNode **parent = &root, *node = root;
43 |         while (node) {
44 |             if (node->val == target) break;
45 |             if (node->val < target) {
46 |                 node = node->right;
47 |                 parent = &(*parent)->right;
48 |             } else {
49 |                 node = node->left;
50 |                 parent = &(*parent)->left;
51 |             }
52 |         }
53 |         if (!node) return false;
54 |         if (node->right) {
55 |             *parent = node->right;
56 |             auto left = node->left;
57 |             delete node;
58 |             node = *parent;
59 |             while (node->left) node = node->left;
60 |             node->left = left;
61 |         } else if (node->left) {
62 |             *parent = node->left;
63 |             delete node;
64 |         } else *parent = NULL;
65 |         return true;
66 |     }
67 | };
68 | ```
69 | 
70 | ### Reference
71 | 
72 | * [Binary Search Tree \| GeeksforGeeks](https://www.geeksforgeeks.org/binary-search-tree-data-structure/)
73 | 
74 | 


--------------------------------------------------------------------------------
/binary-tree/serialization-and-deserialization.md:
--------------------------------------------------------------------------------
 1 | # Serialization And Deserialization
 2 | 
 3 | [297. Serialize and Deserialize Binary Tree \(Hard\)](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/)
 4 | 
 5 | The following code can serialize and deserialize a binary tree in the same way as LeetCode.
 6 | 
 7 | ```cpp
 8 | // OJ: https://leetcode.com/problems/serialize-and-deserialize-binary-tree/
 9 | // Author: github.com/lzl124631x
10 | vector<string> stringToVector(string str) {
11 |     str = str.substr(1, str.size() - 2);
12 |     istringstream ss(str);
13 |     string token;
14 |     vector<string> ans;
15 |     while (getline(ss, token, ',')) ans.push_back(token);
16 |     return ans;
17 | }
18 | 
19 | string vectorToString(vector<string> v){
20 |     auto i = v.begin();
21 |     ostringstream ans;
22 |     ans << "[";
23 |     for(; i != v.end(); ++i) {
24 |         ans << *i;
25 |         if (i + 1 != v.end()) ans << ",";
26 |     }
27 |     ans << "]";
28 |     return ans.str();
29 | }
30 | 
31 | class Codec {
32 | private:
33 |     string nilToken = "null";
34 | public:
35 |     TreeNode* deserialize(string str) {
36 |         auto v = stringToVector(str);
37 |         if (v.empty()) return NULL;
38 |         queue<TreeNode*> q;
39 |         auto root = new TreeNode(stoi(v[0]));
40 |         q.push(root);
41 |         for (int i = 1, N = v.size(); i < N;) {
42 |             auto node = q.front();
43 |             q.pop();
44 |             if (v[i] != nilToken) q.push(node->left = new TreeNode(stoi(v[i])));
45 |             ++i;
46 |             if (i < N && v[i] != nilToken) q.push(node->right = new TreeNode(stoi(v[i])));
47 |             ++i;
48 |         }
49 |         return root;
50 |     }
51 | 
52 |     string serialize(TreeNode* root) {
53 |         vector<string> v;
54 |         if (!root) return vectorToString(v);
55 |         queue<TreeNode*> q;
56 |         q.push(root);
57 |         while (q.size()) {
58 |             root = q.front();
59 |             q.pop();
60 |             if (root) {
61 |                 v.push_back(to_string(root->val));
62 |                 q.push(root->left);
63 |                 q.push(root->right);
64 |             } else v.push_back(nilToken);
65 | 
66 |         }
67 |         while (v.back() == nilToken) v.pop_back();
68 |         return vectorToString(v);
69 |     }
70 | };
71 | ```
72 | 
73 | See more my solutions [here](https://github.com/lzl124631x/LeetCode/tree/master/leetcode/297.%20Serialize%20and%20Deserialize%20Binary%20Tree)
74 | 
75 | 


--------------------------------------------------------------------------------
/binary-tree/traversal.md:
--------------------------------------------------------------------------------
  1 | # Traversal
  2 | 
  3 | ## Preorder
  4 | 
  5 | [144. Binary Tree Preorder Traversal](https://leetcode.com/problems/binary-tree-preorder-traversal/)
  6 | 
  7 | See more my solutions [here](https://github.com/lzl124631x/LeetCode/tree/master/leetcode/144.%20Binary%20Tree%20Preorder%20Traversal)
  8 | 
  9 | ```cpp
 10 | // OJ: https://leetcode.com/problems/binary-tree-preorder-traversal/
 11 | // Author: github.com/lzl124631x
 12 | // Time: O(N)
 13 | // Space: O(H)
 14 | class Solution {
 15 | public:
 16 |     vector<int> preorderTraversal(TreeNode* root) {
 17 |         if (!root) return {};
 18 |         vector<int> ans;
 19 |         stack<TreeNode*> s{{root}};
 20 |         while (s.size()) {
 21 |             root = s.top();
 22 |             s.pop();
 23 |             ans.push_back(root->val);
 24 |             if (root->right) s.push(root->right);
 25 |             if (root->left) s.push(root->left);
 26 |         }
 27 |         return ans;
 28 |     }
 29 | };
 30 | ```
 31 | 
 32 | Or
 33 | 
 34 | ```cpp
 35 | // OJ: https://leetcode.com/problems/binary-tree-preorder-traversal/
 36 | // Author: github.com/lzl124631x
 37 | // Time: O(N)
 38 | // Space: O(H)
 39 | class Solution {
 40 | public:
 41 |     vector<int> preorderTraversal(TreeNode* root) {
 42 |         vector<int> ans;
 43 |         stack<TreeNode*> s;
 44 |         while (root || s.size()) {
 45 |             if (!root) {
 46 |                 root = s.top();
 47 |                 s.pop();
 48 |             }
 49 |             ans.push_back(root->val);
 50 |             if (root->right) s.push(root->right);
 51 |             root = root->left;
 52 |         }
 53 |         return ans;
 54 |     }
 55 | };
 56 | ```
 57 | 
 58 | See also [589. N-ary Tree Preorder Traversal (Easy)](https://leetcode.com/problems/n-ary-tree-preorder-traversal)
 59 | 
 60 | ## Inorder
 61 | 
 62 | [94. Binary Tree Inorder Traversal (Easy)](https://leetcode.com/problems/binary-tree-inorder-traversal/)
 63 | 
 64 | See more my solutions [here](https://github.com/lzl124631x/LeetCode/blob/master/leetcode/94.%20Binary%20Tree%20Inorder%20Traversal)
 65 | 
 66 | ```cpp
 67 | // OJ: https://leetcode.com/problems/binary-tree-inorder-traversal/
 68 | // Author: github.com/lzl124631x
 69 | // Time: O(N)
 70 | // Space: O(H)
 71 | class Solution {
 72 | public:
 73 |     vector<int> inorderTraversal(TreeNode* root) {
 74 |         vector<int> ans;
 75 |         stack<TreeNode*> s;
 76 |         while (root || s.size()) {
 77 |             while (root) {
 78 |                 s.push(root);
 79 |                 root = root->left;
 80 |             }
 81 |             root = s.top();
 82 |             s.pop();
 83 |             ans.push_back(root->val);
 84 |             root = root->right;
 85 |         }
 86 |         return ans;
 87 |     }
 88 | };
 89 | ```
 90 | 
 91 | ## Postorder
 92 | 
 93 | [145. Binary Tree Postorder Traversal (Easy)](https://leetcode.com/problems/binary-tree-postorder-traversal/)
 94 | 
 95 | See more my solutions [here](https://github.com/lzl124631x/LeetCode/blob/master/leetcode/145.%20Binary%20Tree%20Postorder%20Traversal)
 96 | 
 97 | ```cpp
 98 | // OJ: https://leetcode.com/problems/binary-tree-postorder-traversal/
 99 | // Author: github.com/lzl124631x
100 | // Time: O(N)
101 | // Space: O(H)
102 | class Solution {
103 | public:
104 |     vector<int> postorderTraversal(TreeNode* root) {
105 |         vector<int> ans;
106 |         stack<TreeNode*> s;
107 |         TreeNode *prev = nullptr;
108 |         while (root || s.size()) {
109 |             while (root) {
110 |                 s.push(root);
111 |                 root = root->left;
112 |             }
113 |             root = s.top();
114 |             if (!root->right || root->right == prev) { // if root->right is nonexistent or visited, visit root
115 |                 ans.push_back(root->val);
116 |                 s.pop();
117 |                 prev = root;
118 |                 root = nullptr;
119 |             } else root = root->right; // otherwise, visit right subtree
120 |         }
121 |         return ans;
122 |     }
123 | };
124 | ```
125 | 
126 | See also [590. N-ary Tree Postorder Traversal (Easy)](https://leetcode.com/problems/n-ary-tree-postorder-traversal)
127 | 
128 | ## Level-order
129 | 
130 | [102. Binary Tree Level Order Traversal \(Medium\)](https://leetcode.com/problems/binary-tree-level-order-traversal/)
131 | 
132 | See more my solutions [here](https://github.com/lzl124631x/LeetCode/blob/master/leetcode/102.%20Binary%20Tree%20Level%20Order%20Traversal)
133 | 
134 | ```cpp
135 | // OJ: https://leetcode.com/problems/binary-tree-level-order-traversal/
136 | // Author: github.com/lzl124631x
137 | // Time: O(N)
138 | // Space: O(N)
139 | class Solution {
140 | public:
141 |     vector<vector<int>> levelOrder(TreeNode* root) {
142 |         if (!root) return {};
143 |         vector<vector<int>> ans;
144 |         queue<TreeNode*> q;
145 |         q.push(root);
146 |         while (q.size()) {
147 |             int cnt = q.size();
148 |             ans.emplace_back();
149 |             while (cnt--) {
150 |                 root = q.front();
151 |                 q.pop();
152 |                 ans.back().push_back(root->val);
153 |                 if (root->left) q.push(root->left);
154 |                 if (root->right) q.push(root->right);
155 |             }
156 |         }
157 |         return ans;
158 |     }
159 | };
160 | ```
161 | 
162 | * [2641. Cousins in Binary Tree II (Medium)](https://leetcode.com/problems/cousins-in-binary-tree-ii)
163 | 
164 | ## Other variations
165 | 
166 | * [107. Binary Tree Level Order Traversal II \(Easy\)](https://leetcode.com/problems/binary-tree-level-order-traversal-ii/)
167 | * [103. Binary Tree Zigzag Level Order Traversal \(Medium\)](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/)
168 | 
169 | ## Problems
170 | 
171 | * [124. Binary Tree Maximum Path Sum \(Hard\)](https://leetcode.com/problems/binary-tree-maximum-path-sum/)
172 | 
173 | 


--------------------------------------------------------------------------------
/bit-manipulation.md:
--------------------------------------------------------------------------------
  1 | # Bit Manipulation
  2 | 
  3 | ## Bitwise NOT
  4 | 
  5 | ```
  6 | ~val
  7 | ```
  8 | 
  9 | ```text
 10 | NOT 0111 (decimal 7)
 11 | = 1000 (decimal 8)
 12 | ```
 13 | 
 14 | `~val` is also equivalent to `val != -1`, since `-1` is the only one number whose bitwise NOT is `0`.
 15 | 
 16 | So if `val` is some non-negative number, the following:
 17 | 
 18 | ```cpp
 19 | for (int i = val; ~i; --i)
 20 | ```
 21 | 
 22 | is equivalent to
 23 | 
 24 | ```cpp
 25 | for (int i = val; i >= 0; --i)
 26 | ```
 27 | 
 28 | ## Set the `i`th bit
 29 | 
 30 | ```cpp
 31 | mask |= 1 << i
 32 | ```
 33 | 
 34 | ## Unset the `i`th bit
 35 | 
 36 | ```cpp
 37 | mask &= ~(1 << i)
 38 | ```
 39 | 
 40 | ## Toggle the `i`th bit
 41 | 
 42 | ```cpp
 43 | mask ^= 1 << i
 44 | ```
 45 | 
 46 | ## Check if `i`th bit is set
 47 | 
 48 | ```cpp
 49 | mask & (1 << i)
 50 | // Or
 51 | mask >> i & 1 // less typing
 52 | ```
 53 | 
 54 | ## Set the `i`th bit with `x`
 55 | 
 56 | ```cpp
 57 | mask = (mask & ~(1 << i)) | (x << i)
 58 | ```
 59 | 
 60 | ## Get the lowest bit
 61 | 
 62 | ```cpp
 63 | function lowbit(int x) {
 64 |     return x & -x;
 65 | }
 66 | ```
 67 | 
 68 | Example:
 69 | ```
 70 |         12 = (01100)2
 71 |        -12 = (10100)2
 72 | 12 & (-12) = (00100)2
 73 | ```
 74 | 
 75 | ## Count bit 1s
 76 | 
 77 | ```cpp
 78 | __builtin_popcount(n);
 79 | ```
 80 | 
 81 | Note that the `pop` in this function means `population`.
 82 | 
 83 | ## Count trailing zeros
 84 | 
 85 | ```cpp
 86 | __builtin_ctz(n);
 87 | ```
 88 | 
 89 | ## Count leading zeros
 90 | 
 91 | ```cpp
 92 | __builtin_clz(n);
 93 | ```
 94 | 
 95 | ## Check if `n` is power of 2
 96 | 
 97 | ```cpp
 98 | __builtin_popcount(n) == 1
 99 | // or
100 | (n & (n - 1)) == 0 // & has lower precedence than ==. Must add the parenthesis.
101 | ```
102 | 
103 | ## Traverse all the subsets
104 | 
105 | ```cpp
106 | for (int mask = 0; mask < (1 << N); ++mask)
107 | ```
108 | 
109 | ## Complement of a subset
110 | 
111 | ```cpp
112 | // Assume `sub` is a subset of `mask`
113 | int complement = mask ^ sub;
114 | // Or
115 | int complement = mask - sub;
116 | ```
117 | 
118 | ## Traverse subsets of a set `mask`
119 | 
120 | ```cpp
121 | for (int sub = mask; sub; sub = (sub - 1) & mask) {
122 |     // `sub` is a non-empty subset of `mask`
123 | }
124 | ```
125 | 
126 | Sample output:
127 | 
128 | ```cpp
129 | // mask = 0b1011
130 | 1011
131 | 1010
132 | 1001
133 | 1000
134 | 0011
135 | 0010
136 | 0001
137 | ```
138 | 
139 | Or the other direction:
140 | 
141 | ```cpp
142 | for (int other = mask; other; other = (other - 1) & mask) {
143 |     int sub = mask - other;
144 |     // `other` is a non-empty subset of `mask`. `sub` is the complement of `other`.
145 | }
146 | ```
147 | 
148 | Sample output:
149 | 
150 | ```
151 | 0000
152 | 0001
153 | 0010
154 | 0011
155 | 1000
156 | 1001
157 | 1010
158 | ```
159 | 
160 | ## Given `N` elements, traverse subsets of size `K` (Gosper's Hack)
161 | 
162 | ```cpp
163 | // Time Complexity: O(C(N, K))
164 | int sub = (1 << k) - 1;
165 | while (sub < (1 << N)) {
166 |     // Access `sub` here. `sub` has `K` elements and is a subset of `N` elements.
167 |     int c = sub & - sub, r = sub + c;
168 |     sub = (((r ^ sub) >> 2) / c) | r;
169 | }
170 | ``` 
171 |  
172 | ## Traverse subsets of subsets
173 | 
174 | Given an array of `N` elements, traverse all its subsets. For each of the subsets, traverse its all non-empty subsets as well.
175 | 
176 | ```cpp
177 | // Time: O(3^N)
178 | for (int mask = 0; mask < (1 << N); ++mask) {
179 |     // `mask` is a subset of `N` elements
180 |     for (int sub = mask; sub; sub = (sub - 1) & mask) {
181 |         // `sub` is a subset of `mask`.
182 |     }
183 | }
184 | ```
185 | 
186 | Note that the time complexity is `O(3^N)` instead of `O(2^N * 2^N) = O(4^N)`.
187 | 
188 | **Math proof:**
189 | 
190 | For a subset `mask` with `K` bits of `1`s, there are `2^K` subsets of it.
191 | 
192 | For `N` elements, there are `C(N, K)` subsets with `K` bits of `1`s.
193 | 
194 | So the total number is `SUM( C(N, K) * 2^K | 0 <= K <= N )`.
195 | 
196 | Since `(1 + x)^N = C(N, 0) * x^0 + C(N, 1) * x^1 + ... + C(N, N) * x^N`, let `x = 2`, we have `3^N = SUM( C(N, K) * 2^K | 0 <= K <= N )`.
197 | 
198 | **Intuitive proof:**
199 | 
200 | For each bit index `i` (`0 <= i < N`), the `i`-th bits of `mask` and `sub` must be one of `11, 10, 00`, and can't be `01`. So each bit has `3` possibilities, the total complexity is `O(3^N)`.
201 | 
202 | ## Calculate subset sums
203 | 
204 | ```cpp
205 | // Time: O(N * 2^N)
206 | for (int mask = 0; mask < (1 << N); ++mask) {
207 |     for (int i = 0; i < N; ++i) {
208 |         if (mask >> i & 1) sum[mask] += A[i];
209 |     }
210 | }
211 | ```
212 | 
213 | Or 
214 | 
215 | ```cpp
216 | // DP solution
217 | // Time: O(2^N)
218 | for (int mask = 1; mask < (1 << N); ++mask) {
219 |     sum[mask] = sum[mask - lowbit(mask)] + A[__builtin_ctz(lowbit(mask))];
220 | }
221 | ```
222 | 
223 | where `lowbit(x) = x & -x`, and `__builtin_ctz(x)` counts the trailing zeros in `x`. Since `lowbit(mask)` is a power of two, `__builtin_ctz(lowbit(mask)) == log2(lowbit(mask))`.
224 | 
225 | ## Generate `logs` array
226 | 
227 | `logs[n]` is `floor(log2(n))`.
228 | 
229 | ```
230 | logs[1] = 0
231 | logs[2] = 1
232 | logs[3] = 1
233 | logs[4] = 2
234 | logs[5] = 2
235 | logs[6] = 2
236 | logs[7] = 2
237 | logs[8] = 3
238 | ...
239 | ```
240 | 
241 | ```cpp
242 | // Time: O(2^N)
243 | for (int mask = 2; mask < (1 << N); ++mask) {
244 |     logs[mask] = logs[mask >> 1] + 1;
245 | }
246 | ```
247 | 
248 | ## Reference
249 | 
250 | * [https://oi-wiki.org/math/bit/](https://oi-wiki.org/math/bit/)
251 | 
252 | 


--------------------------------------------------------------------------------
/company/README.md:
--------------------------------------------------------------------------------
1 | # Company
2 | 
3 | 


--------------------------------------------------------------------------------
/company/facebook.md:
--------------------------------------------------------------------------------
 1 | # Facebook
 2 | 
 3 | * [139. Word Break (Medium)](https://leetcode.com/problems/word-break/)
 4 | * [140. Word Break II (Hard)](https://leetcode.com/problems/word-break-ii/)
 5 | 
 6 | Phone Interview E5 London (45min)
 7 | 
 8 | * [953. Verifying an Alien Dictionary (Easy)](https://leetcode.com/problems/verifying-an-alien-dictionary/)
 9 | * [236. Lowest Common Ancestor of a Binary Tree (Medium)](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/)
10 | * [https://leetcode.com/problems/design-tic-tac-toe/](https://leetcode.com/problems/design-tic-tac-toe/)
11 | 
12 | [Facebook | E5 | MLE | Menlo Park](https://leetcode.com/discuss/interview-question/1158980/Facebook-or-E5-or-MLE-or-Menlo-Park)
13 | 
14 | * [1653. Minimum Deletions to Make String Balanced (Medium)](https://leetcode.com/problems/minimum-deletions-to-make-string-balanced/)
15 | 
16 | [https://www.facebookrecruiting.com/portal/interview\_prep\_hub](https://www.facebookrecruiting.com/portal/interview\_prep\_hub)
17 | 
18 | * [76. Minimum Window Substring (Hard)](https://leetcode.com/problems/minimum-window-substring/)
19 | * [1505. Minimum Possible Integer After at Most K Adjacent Swaps On Digits (Hard)](https://leetcode.com/problems/minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits/)
20 | * [20. Valid Parentheses (Easy)](https://leetcode.com/problems/valid-parentheses/)
21 | * [322. Coin Change (Medium)](https://leetcode.com/problems/coin-change/)
22 | 
23 | [New Year Gift - Curated List of Top 75 LeetCode Questions to Save Your Time](https://www.teamblind.com/post/New-Year-Gift---Curated-List-of-Top-75-LeetCode-Questions-to-Save-Your-Time-OaM1orEU)
24 | 


--------------------------------------------------------------------------------
/cpp/README.md:
--------------------------------------------------------------------------------
1 | # Cpp
2 | 
3 | 


--------------------------------------------------------------------------------
/cpp/array.md:
--------------------------------------------------------------------------------
 1 | # Array
 2 | 
 3 | Using array `int[]` is more performant than `vector<int>`. 
 4 | 
 5 | The following trick can initialize the array with customized values.
 6 | 
 7 | ```
 8 | int A[10] = { [0] = 0, [1 ... 9] = INT_MAX };
 9 | ```
10 | 
11 | See: https://www.geeksforgeeks.org/designated-initializers-c/


--------------------------------------------------------------------------------
/cpp/memset-3f.md:
--------------------------------------------------------------------------------
 1 | # Memset 3 F
 2 | 
 3 | There is no fixed way to represent Infinity. The first option that might come to our mind is `0x7f ff ff ff = 2^31 - 1 = 2,147,483,647` which is the maximum value of 32-bit `int`.
 4 | 
 5 | This choice has one issue -- when adding Infinity with another number, you will get overflow error.
 6 | 
 7 | A better choice is `0x3f 3f 3f 3f = 1,061,109,567`.
 8 | 
 9 | * It is of the same order of magnitude as `0x7f ff ff ff` but twice of it is still within the range of `int`.
10 | * When using `memset` to initialize an array of `int`, since `memset` is filling values as `unsigned char`, `memset(A, 0x3f, sizeof(A))` will perfectly fill `0x3f 3f 3f 3f` into the array.
11 | 
12 | ## Reference
13 | 
14 | * [https://www.kawabangga.com/posts/1153](https://www.kawabangga.com/posts/1153)
15 | 


--------------------------------------------------------------------------------
/cpp/overflow.md:
--------------------------------------------------------------------------------
1 | # Overflow
2 | 
3 | If we are detecting if `a * 10` will overflow `INT_MAX`, we compare `a` with `INT_MAX / 10`. If `a > INT_MAX / 10`, it will overflow.
4 | 
5 | If we are detecting if `a * 10 + b` will overflow `INT_MAX`, we use this check: If `a > INT_MAX / 10 || (a == INT_MAX / 10 && b > INT_MAX % 10)`, it will overflow.
6 | 
7 | 


--------------------------------------------------------------------------------
/data-structure/README.md:
--------------------------------------------------------------------------------
1 | # Data Structure
2 | 
3 | 


--------------------------------------------------------------------------------
/data-structure/binary-indexed-tree.md:
--------------------------------------------------------------------------------
  1 | # Binary Indexed Tree
  2 | 
  3 | aka Fenwick Tree.
  4 | 
  5 | ## Motivation
  6 | 
  7 | Fenwick tree was proposed to solve the [mutable range sum query problem](https://leetcode.com/problems/range-sum-query-mutable/).
  8 | 
  9 | It supports:
 10 | 
 11 | * Fast point update in `O(logN)` time
 12 | * Range Query in `O(logN)` time
 13 | 
 14 | Note that in addition to range sum, we can also use BIT to calculate range **multiplication**, range **xor**, range **maximum number**, range **minimum number** etc.
 15 | 
 16 | ## Binary Indexed
 17 | 
 18 | <figure><img src="../.gitbook/assets/bit.png" alt=""><figcaption></figcaption></figure>
 19 | 
 20 | BIT nodes are indexed using the lowbit of their original index.
 21 | 
 22 | <figure><img src="../.gitbook/assets/bit1.png" alt=""><figcaption></figcaption></figure>
 23 | 
 24 | For those with lowest bits at index 0 (we count the bit index from the right), the value is directly saved into BIT. These are the leaf nodes of the BIT.
 25 | 
 26 | <figure><img src="../.gitbook/assets/bit2.png" alt=""><figcaption></figcaption></figure>
 27 | 
 28 | For those with lowest bits at index 1, they are located at the 2nd layer from the bottom. We not only add their own values to BIT, but also add their child values to it. Their child indices are one less than their own indices. For example, `node[2]` (00010) has `node[1]` (00001) as its child, so `node[2] = A[2] + node[1] = 2 + 5 = 7`
 29 | 
 30 | <figure><img src="../.gitbook/assets/bit3.png" alt=""><figcaption></figcaption></figure>
 31 | 
 32 | For those with lowest bits at index 2, they are located at the 3rd layer from the bottom. For example, `node[4]` (00100) has `node[3]` (00011) and `node[2]` (00010) as its direct children, so `node[4] = A[4] + node[3] + node[2] = -3 + 9 + 7 = 13`
 33 | 
 34 | <figure><img src="../.gitbook/assets/image (2).png" alt=""><figcaption></figcaption></figure>
 35 | 
 36 | ## Sum Query
 37 | 
 38 | <figure><img src="../.gitbook/assets/bit-sum.png" alt=""><figcaption></figcaption></figure>
 39 | 
 40 | To calculate `sum(7) = A[1] + ... + A[7]`, we keep finding previous ranges by removing the lowbit from `7 = 111`. So, `sum(111) = node(111) + node(110) + node(100) = node[7] + node[6] + node[4]`
 41 | 
 42 | <figure><img src="../.gitbook/assets/bit-sum2 (1).png" alt=""><figcaption></figcaption></figure>
 43 | 
 44 | Another example, `sum(8) = sum(1000) = node(1000) = node[8]`
 45 | 
 46 | ## Update
 47 | 
 48 | <figure><img src="../.gitbook/assets/image (3) (1).png" alt=""><figcaption></figcaption></figure>
 49 | 
 50 | To add `10` to `A[4]`, we need to update all the nodes containing`A[4]`. We find such nodes by adding lowbit. So, `A[4]` is contained by `node[100] = node[4]` and `node[1000] = node[8]`.
 51 | 
 52 | ## Note
 53 | 
 54 | `N + 1` elements.
 55 | 
 56 | When querying, keep REMOVING low bit. (find the previous intervals)
 57 | 
 58 | When updating, keep ADDing low bit. (updating the tree towards higher levels)
 59 | 
 60 | ## Implementation
 61 | 
 62 | ```cpp
 63 | // Author: github.com/lzl124631x
 64 | class BIT {
 65 |     vector<int> sum;
 66 |     static inline int lowbit(int x) { return x & -x; }
 67 | public:
 68 |     BIT(int N) : sum(N + 1) {};
 69 |     // Add delta to A[i]
 70 |     void update(int i, int delta) { // Note: this `i` is 1-based.
 71 |         for (; i < sum.size(); i += lowbit(i)) sum[i] += delta;
 72 |     }
 73 |     // Return A[1] + ... + A[i]
 74 |     int query(int i) { // Note: this `i` is 1-based.
 75 |         int ans = 0;
 76 |         for (; i; i -= lowbit(i)) ans += sum[i];
 77 |         return ans;
 78 |     }
 79 |     // Return A[i] + ... + A[j]
 80 |     int rangeQuery(int i, int j) { // Note: these `i` and `j` are 1-based.
 81 |         return query(j) - query(i - 1);
 82 |     }
 83 | };
 84 | ```
 85 | 
 86 | The implementation for [307. Range Sum Query - Mutable (Medium)](https://leetcode.com/problems/range-sum-query-mutable/)
 87 | 
 88 | ```cpp
 89 | // OJ: https://leetcode.com/problems/range-sum-query-mutable/
 90 | // Author: github.com/lzl124631x
 91 | // Time: 
 92 | //      NumArray: O(N^2 * logN)
 93 | //      update: O(logN)
 94 | //      sumRange: O(logN)
 95 | // Ref: https://www.youtube.com/watch?v=WbafSgetDDk
 96 | class BIT {
 97 |     vector<int> A;
 98 |     static inline int lb(int x) { return x & -x; }
 99 | public:
100 |     BIT(vector<int> nums) : A(nums.size() + 1) {
101 |         for (int i = 0; i < nums.size(); ++i) {
102 |             update(i + 1, nums[i]);
103 |         }
104 |     }
105 |     int query(int i) {
106 |         int ans = 0;
107 |         for (; i; i -= lb(i)) ans += A[i];
108 |         return ans;
109 |     }
110 |     int rangeQuery(int i, int j) { // i, j are inclusive
111 |         return query(j) - query(i - 1);
112 |     }
113 |     void update(int i, int delta) {
114 |         for (; i < A.size(); i += lb(i)) A[i] += delta;
115 |     }
116 | };
117 | class NumArray {
118 |     BIT tree;
119 |     vector<int> A;
120 | public:
121 |     NumArray(vector<int>& A) : A(A), tree(A) {}
122 |     void update(int index, int val) {
123 |         tree.update(index + 1, val - A[index]);
124 |         A[index] = val;
125 |     }
126 |     int sumRange(int left, int right) {
127 |         return tree.rangeQuery(left + 1, right + 1);
128 |     }
129 | };
130 | ```
131 | 
132 | The implementation for [1649. Create Sorted Array through Instructions (Hard)](https://leetcode.com/problems/create-sorted-array-through-instructions/)
133 | 
134 | ```cpp
135 | // OJ: https://leetcode.com/problems/create-sorted-array-through-instructions/
136 | // Author: github.com/lzl124631x
137 | // Time: O(NlogM) where M is the range of A[i]
138 | // Space: O(M)
139 | // Ref: https://leetcode.com/problems/create-sorted-array-through-instructions/discuss/927531/JavaC%2B%2BPython-Binary-Indexed-Tree
140 | int c[100001] = {};
141 | class Solution {
142 | public:
143 |     static inline int lowbit(int x) { return x & -x; }
144 |     int createSortedArray(vector<int>& A) {
145 |         memset(c, 0, sizeof(c));
146 |         int ans = 0, N = A.size(), mod = 1e9 + 7;
147 |         for (int i = 0; i < N; ++i) {
148 |             ans = (ans + min(get(A[i] - 1), i - get(A[i]))) % mod;
149 |             update(A[i]);
150 |         }
151 |         return ans;
152 |     }
153 |     void update(int x) {
154 |         for (; x < 100001; x += lowbit(x)) c[x]++;
155 |     }
156 |     int get(int x) { // returns the sum of numbers <= x
157 |         int ans = 0;
158 |         for (; x > 0; x -= lowbit(x)) ans += c[x];
159 |         return ans;
160 |     }
161 | };
162 | ```
163 | 
164 | ## Problems
165 | 
166 | * [307. Range Sum Query - Mutable (Medium)](https://leetcode.com/problems/range-sum-query-mutable/)
167 | * [308. Range Sum Query 2D - Mutable (Hard)](https://leetcode.com/problems/range-sum-query-2d-mutable)
168 | * [315. Count of Smaller Numbers After Self (Hard)](https://leetcode.com/problems/count-of-smaller-numbers-after-self)
169 | * [1649. Create Sorted Array through Instructions (Hard)](https://leetcode.com/problems/create-sorted-array-through-instructions/)
170 | * [2179. Count Good Triplets in an Array (Hard)](https://leetcode.com/problems/count-good-triplets-in-an-array/)
171 | 
172 | ## Reference
173 | 
174 | * [https://leetcode.com/problems/range-sum-query-mutable/discuss/75753/Java-using-Binary-Indexed-Tree-with-clear-explanation](https://leetcode.com/problems/range-sum-query-mutable/discuss/75753/Java-using-Binary-Indexed-Tree-with-clear-explanation)
175 | * [https://www.topcoder.com/community/competitive-programming/tutorials/binary-indexed-trees/](https://www.topcoder.com/community/competitive-programming/tutorials/binary-indexed-trees/)
176 | * [https://oi-wiki.org/ds/fenwick/](https://oi-wiki.org/ds/fenwick/)
177 | * [https://www.youtube.com/watch?v=WbafSgetDDk](https://www.youtube.com/watch?v=WbafSgetDDk)
178 | * [https://visualgo.net/en/fenwicktree](https://visualgo.net/en/fenwicktree)
179 | * [https://www.luogu.com.cn/problem/solution/P3374](https://www.luogu.com.cn/problem/solution/P3374)
180 | * [树状数组(Binary Indexed Tree),看这一篇就够了](https://blog.csdn.net/Yaokai\_AssultMaster/article/details/79492190)
181 | 


--------------------------------------------------------------------------------
/data-structure/segment-tree-and-binary-index-tree.md:
--------------------------------------------------------------------------------
1 | # Problems solvable with segment tree or binary index tree
2 | 
3 | There are a group of questions with tags "Segment Tree", "Binary Index Tree", "Divide and Conquer".
4 | 
5 | * [315. Count of Smaller Numbers After Self (Hard)](https://leetcode.com/problems/count-of-smaller-numbers-after-self/)
6 | * [327. Count of Range Sum (Hard)](https://leetcode.com/problems/count-of-range-sum/)
7 | * [493. Reverse Pairs (Hard)](https://leetcode.com/problems/reverse-pairs/)
8 | * [2031. Count Subarrays With More Ones Than Zeros (Medium)](https://leetcode.com/problems/count-subarrays-with-more-ones-than-zeros/)
9 | * [2179. Count Good Triplets in an Array (Hard)](https://leetcode.com/problems/count-good-triplets-in-an-array/)


--------------------------------------------------------------------------------
/data-structure/segment-tree.md:
--------------------------------------------------------------------------------
  1 | # Segment Tree
  2 | 
  3 | Segment tree is a data structure that supports queries and update on intervals.
  4 | 
  5 | It can be used for solving range query problems like finding minimum, maximum, sum, greatest common divisor, least common denominator in array in logarithmic time.
  6 | 
  7 | ![Segment Tree](../.gitbook/assets/image.png)
  8 | 
  9 | ![Node values in a segment tree used in range sum query](../.gitbook/assets/image%20%281%29.png)
 10 | 
 11 | Example range sum query problem:
 12 | 
 13 | given an array, you need to do the following operations:
 14 | 
 15 | * add `k` to every numbers in a index range.
 16 | * get the sum of all the numbers within a index range.
 17 | 
 18 | The `merge` operation can be `sum` or any operation that satisfies **associative law**.
 19 | 
 20 | ```text
 21 | merge(merge(a, b), c) = merge(a, merge(b, c))
 22 | // Example
 23 | max(max(a, b), c) = max(a, max(b, c))
 24 | gcd(gcd(a, b), c) = gcd(a, gcd(b, c))
 25 | ```
 26 | 
 27 | ## Implementation
 28 | 
 29 | Here I use [307. Range Sum Query - Mutable \(Medium\)](https://leetcode.com/problems/range-sum-query-mutable/) as an example.
 30 | 
 31 | ```cpp
 32 | // OJ: https://leetcode.com/problems/range-sum-query-mutable/
 33 | // Author: github.com/lzl124631x
 34 | // Time: 
 35 | //      NumArray: O(N)
 36 | //      update: O(1)
 37 | //      sumRange: O(logN)
 38 | // Space: O(N)
 39 | class NumArray {
 40 |     vector<int> tree;
 41 |     int N;
 42 |     void buildTree(vector<int> &nums) {
 43 |         for (int i = 0, j = N; i < N;) tree[j++] = nums[i++]; // the input array values are stored in `tree[N...(2 * N - 1)]`
 44 |         for (int i = N - 1; i > 0; --i) tree[i] = tree[2 * i] + tree[2 * i + 1]; // from `tree[N-1]` to `tree[1]`, build the non-leaf nodes. Note that we don't use `tree[0]`.
 45 |     }
 46 | public:
 47 |     NumArray(vector<int>& nums) {
 48 |         if (nums.empty()) return;
 49 |         N = nums.size();
 50 |         tree = vector<int>(N * 2);
 51 |         buildTree(nums); // Segment tree requires initialization.
 52 |     }
 53 | 
 54 |     void update(int i, int val) {
 55 |         i += N; // Offset N to get the leaf node
 56 |         tree[i] = val;
 57 |         while (i > 0) {
 58 |             i /= 2; // Move to the parent node
 59 |             tree[i] = tree[2 * i] + tree[2 * i + 1]; // Update the parent node
 60 |         }
 61 |     }
 62 | 
 63 |     int sumRange(int i, int j) {
 64 |         i += N; // Offset N to get the leaf nodes
 65 |         j += N;
 66 |         int sum = 0;
 67 |         while (i <= j) { // When the range is not empty
 68 |             if (i % 2) sum += tree[i++];
 69 |             if (j % 2 == 0) sum += tree[j--];
 70 |             i /= 2;
 71 |             j /= 2;
 72 |         }
 73 |         return sum;
 74 |     }
 75 | };
 76 | ```
 77 | 
 78 | Another OOD implementation:
 79 | 
 80 | ```cpp
 81 | // OJ: https://leetcode.com/problems/range-sum-query-mutable/
 82 | // Author: github.com/lzl124631x
 83 | // Time: 
 84 | //      NumArray: O(N)
 85 | //      update: O(1)
 86 | //      sumRange: O(logN)
 87 | // Space: O(N)
 88 | typedef int Merge(const int &a, const int& b);
 89 | class SegTree {
 90 |     vector<int> tree;
 91 |     int N;
 92 |     Merge *merge;
 93 |     void buildTree(vector<int> &nums) {
 94 |         for (int i = 0, j = N; i < N;) tree[j++] = nums[i++];
 95 |         for (int i = N - 1; i > 0; --i) tree[i] = merge(tree[2 * i], tree[2 * i + 1]);
 96 |     }
 97 | public:
 98 |     SegTree(vector<int> &nums, Merge merge) {
 99 |         N = nums.size();
100 |         tree.resize(N * 2);
101 |         this->merge = merge;
102 |         buildTree(nums);
103 |     }
104 | 
105 |     void update(int i, int val) {
106 |         i += N;
107 |         tree[i] = val;
108 |         while (i > 0) {
109 |             i /= 2;
110 |             tree[i] = merge(tree[2 * i], tree[2 * i + 1]);
111 |         }
112 |     }
113 | 
114 |     int query(int from, int to, int def) {
115 |         int i = from + N, j = to + N;
116 |         int ans = def;
117 |         while (i <= j) {
118 |             if (i % 2) ans = merge(ans, tree[i++]);
119 |             if (j % 2 == 0) ans = merge(ans, tree[j--]);
120 |             i /= 2;
121 |             j /= 2;
122 |         }
123 |         return ans;
124 |     }
125 | };
126 | class NumArray {
127 |     SegTree* tree;
128 | public:
129 |     NumArray(vector<int>& nums) {
130 |         if (nums.empty()) return;
131 |         tree = new SegTree(nums, [](const int &a, const int &b) { return a + b; });
132 |     }
133 |     void update(int i, int val) {
134 |         tree->update(i, val);
135 |     }
136 |     int sumRange(int i, int j) {
137 |         return tree->query(i, j, 0);
138 |     }
139 | };
140 | ```
141 | 
142 | ## Lazy Propogation
143 | 
144 | When we want to update an interval all at once, we need to use lazy propagation to ensure good run-time complexity.
145 | 
146 | ## Problems
147 | 
148 | * [307. Range Sum Query - Mutable \(Medium\)](https://leetcode.com/problems/range-sum-query-mutable/)
149 | * [699. Falling Squares \(Hard\)](https://leetcode.com/problems/falling-squares/)
150 | * [1505. Minimum Possible Integer After at Most K Adjacent Swaps On Digits \(Hard\)](https://leetcode.com/problems/minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits/)
151 | * [327. Count of Range Sum (Hard)](https://leetcode.com/problems/count-of-range-sum/)
152 | 
153 | ## Reference
154 | 
155 | * [https://leetcode.com/problems/range-sum-query-mutable/solution/](https://leetcode.com/problems/range-sum-query-mutable/solution/)
156 | * [https://leetcode.com/articles/a-recursive-approach-to-segment-trees-range-sum-queries-lazy-propagation/](https://leetcode.com/articles/a-recursive-approach-to-segment-trees-range-sum-queries-lazy-propagation/)
157 | 
158 | 


--------------------------------------------------------------------------------
/data-structure/stack.md:
--------------------------------------------------------------------------------
1 | # Stack
2 | 
3 | ## Problems
4 | 
5 | * [84. Largest Rectangle in Histogram \(Hard\)](https://leetcode.com/problems/largest-rectangle-in-histogram/)
6 | * [901. Online Stock Span \(Medium\)](https://leetcode.com/problems/online-stock-span/)
7 | 
8 | 


--------------------------------------------------------------------------------
/data-structure/trie.md:
--------------------------------------------------------------------------------
 1 | # Trie
 2 | 
 3 | as known as prefix tree.
 4 | 
 5 | ### Implementation
 6 | 
 7 | ```cpp
 8 | struct TrieNode {
 9 |     TrieNode *next[26] = {};
10 |     int count = 0;
11 | };
12 | 
13 | class Trie {
14 | private:
15 |     TrieNode root;
16 |     TrieNode* searchToNode(string &prefix) {
17 |         auto node = &root;
18 |         for (char c : prefix) {
19 |             if (!node->next[c - 'a']) return NULL;
20 |             node = node->next[c - 'a'];
21 |         }
22 |         return node;
23 |     }
24 | public:
25 |     void insert(string word) {
26 |         auto node = &root;
27 |         for (char c : word) {
28 |             if (!node->next[c - 'a']) node->next[c - 'a'] = new TrieNode();
29 |             node = node->next[c - 'a'];
30 |         }
31 |         node->count++;
32 |     }
33 | 
34 |     bool search(string word) {
35 |         auto node = searchToNode(word);
36 |         return node && node->count;
37 |     }
38 | 
39 |     bool startsWith(string prefix) {
40 |         return searchToNode(prefix);
41 |     }
42 | };
43 | ```
44 | 
45 | ## Problems
46 | 
47 | * [208. Implement Trie (Prefix Tree) (Medium)](https://leetcode.com/problems/implement-trie-prefix-tree/) **Direct Implementation**
48 | 
49 | * [212. Word Search II \(Hard\)](https://leetcode.com/problems/word-search-ii/)
50 | * [745. Prefix and Suffix Search (Hard)](https://leetcode.com/problems/prefix-and-suffix-search/)
51 | * [839. Similar String Groups (Hard)](https://leetcode.com/problems/similar-string-groups/)
52 | * [1032. Stream of Characters (Hard)](https://leetcode.com/problems/stream-of-characters/)


--------------------------------------------------------------------------------
/data-structure/union-by-rank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/data-structure/union-by-rank.png


--------------------------------------------------------------------------------
/data-structure/union-find.md:
--------------------------------------------------------------------------------
  1 | # Union Find
  2 | 
  3 | ## Implementation
  4 | 
  5 | ### Basic
  6 | 
  7 | Note that there is a path compression in the `find` function. 
  8 | 
  9 | The time complexity of one operation in `UnionFind` with `N` elements and path compression only is amortized `O(logN)`.
 10 | 
 11 | ```cpp
 12 | class UnionFind {
 13 |     vector<int> id;
 14 | public:
 15 |     UnionFind(int n) : id(n) {
 16 |         iota(begin(id), end(id), 0);
 17 |     }
 18 |     int find(int a) {
 19 |         return id[a] == a ? a : (id[a] = find(id[a]));
 20 |     }
 21 |     void connect(int a, int b) {
 22 |         id[find(a)] = find(b);
 23 |     }
 24 |     bool connected(int a, int b) {
 25 |         return find(a) == find(b);
 26 |     }
 27 | };
 28 | ```
 29 | 
 30 | ### Get Size of Union
 31 | 
 32 | We can use a `size` array to keep track of the size of each union.
 33 | 
 34 | `cnt` keeps track of the number of unions.
 35 | 
 36 | ```cpp
 37 | class UnionFind {
 38 |     vector<int> id, size;
 39 |     int cnt;
 40 | public:
 41 |     UnionFind(int n) : id(n), size(n, 1), cnt(n) {
 42 |         iota(begin(id), end(id), 0);
 43 |     }
 44 |     int find(int a) {
 45 |         return id[a] == a ? a : (id[a] = find(id[a]));
 46 |     }
 47 |     void connect(int a, int b) {
 48 |         int x = find(a), y = find(b);
 49 |         if (x == y) return;
 50 |         id[x] = y;
 51 |         size[y] += size[x];
 52 |         --cnt;
 53 |     }
 54 |     bool connected(int a, int b) { return find(a) == find(b); }
 55 |     int getSize(int a) { return size[find(a)]; }
 56 |     int getCount() { return cnt; }
 57 | };
 58 | ```
 59 | 
 60 | 
 61 | ### Merge using Rank
 62 | 
 63 | The time complexity of one operation in `UnionFind` with `N` elements, path compression and union by rank is amortized `O(alpha(N))` where `alpha(N)` is the inverse function of Ackermann function. Note that `O(alpha(N))` is even more efficient than `O(logN)`.
 64 | 
 65 | ![](./union-by-rank.png)
 66 | 
 67 | ```cpp
 68 | class UnionFind {
 69 |     vector<int> id, rank;
 70 |     int cnt; // `cnt` is the number of connected components in the graph
 71 | public:
 72 |     UnionFind(int n) : id(n), rank(n, 0), cnt(n) {
 73 |         iota(begin(id), end(id), 0);
 74 |     }
 75 |     int find(int a) {
 76 |         return id[a] == a ? a : (id[a] = find(id[a]));
 77 |     }
 78 |     void connect(int i, int j) {
 79 |         int p = find(i), q = find(j);
 80 |         if (p == q) return;
 81 |         if (rank[p] > rank[q]) id[q] = p; // always use the node with GREATER rank as the root
 82 |         else {
 83 |             id[p] = q;
 84 |             if (rank[p] == rank[q]) rank[q]++;
 85 |         }
 86 |         --cnt;
 87 |     }
 88 |     bool connected(int i, int j) { return find(i) == find(j); }
 89 |     int getCount() { return cnt; }
 90 | };
 91 | ```
 92 | 
 93 | ## Problems
 94 | 
 95 | ### Static Connection
 96 | 
 97 | * [130. Surrounded Regions (Medium)](https://leetcode.com/problems/surrounded-regions/)
 98 | * [200. Number of Islands (Medium)](https://leetcode.com/problems/number-of-islands/)
 99 | * [737. Sentence Similarity II (Medium)](https://leetcode.com/problems/sentence-similarity-ii)
100 | * [924. Minimize Malware Spread \(Hard\)](https://leetcode.com/problems/minimize-malware-spread/)
101 | * [947. Most Stones Removed with Same Row or Column \(Medium\)](https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/)
102 | * [952. Largest Component Size by Common Factor (Hard)](https://leetcode.com/problems/largest-component-size-by-common-factor/)
103 | * [959. Regions Cut By Slashes (Medium)](https://leetcode.com/problems/regions-cut-by-slashes/) **Split into sub-cells**
104 | * [990. Satisfiability of Equality Equations (Medium)](https://leetcode.com/problems/satisfiability-of-equality-equations/)
105 | * [1202. Smallest String With Swaps (Medium)](https://leetcode.com/problems/smallest-string-with-swaps/)
106 | * [1319. Number of Operations to Make Network Connected \(Medium\)](https://leetcode.com/problems/number-of-operations-to-make-network-connected/)
107 | 
108 | ### Dynamic Connection
109 | 
110 | Involves multiple steps to build the connection gradually.
111 | 
112 | * [305. Number of Islands II (Hard)](https://leetcode.com/problems/number-of-islands-ii)
113 | 
114 | ### Back in Time
115 | 
116 | Since Union Find can only BUILD connection gradually, when we see problems that BREAK connection gradually with multiple steps, we can traverse the steps in reverse order so as to BUILD the connections gradually.
117 | 
118 | * [803. Bricks Falling When Hit (Hard)](https://leetcode.com/problems/bricks-falling-when-hit)
119 | * [1970. Last Day Where You Can Still Cross (Hard)](https://leetcode.com/problems/last-day-where-you-can-still-cross)


--------------------------------------------------------------------------------
/date.md:
--------------------------------------------------------------------------------
 1 | # Date
 2 | 
 3 | Implement a function to get the number of days from `0000-00-00` to `yyyy-mm-dd`.
 4 | 
 5 | ## Accumulate
 6 | 
 7 | ```cpp
 8 | // Author: github.com/lzl124631x
 9 | // Time: O(1)
10 | // Space: O(1)
11 | // Ref: https://leetcode.com/problems/number-of-days-between-two-dates/discuss/517605/Similar-to-day-of-the-year
12 | const int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
13 | bool isLeap(int year) {
14 |     return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
15 | }
16 | int getDays(string date) {
17 |     int y = stoi(date.substr(0, 4)), m = stoi(date.substr(5, 2)), d = stoi(date.substr(8));
18 |     for (int yr = 0; yr < y; ++yr) d += isLeap(yr) ? 366 : 365;
19 |     return d + (m > 2 && isLeap(y)) + accumulate(begin(days), begin(days) + m - 1, 0);
20 | }
21 | ```
22 | 
23 | ## Magic Formula
24 | 
25 | When `m=1` or `m=2` \(January or February\), we let `m=13` or `m=14` and let `y` decreased by 1. Imagine it is 13th or 14th month of the last year. By doing that, we let the magical formula also work for those two months. `(153 * m + 8) // 5` is just a carefully designed way to record the days of each month. More specifically, it is designed to record the difference of days between two months. Suppose we have March 1st and April 1st, `(153 * 3 + 8) // 5 = 93` while `(153 * 4 + 8) // 5 = 124`, the difference is 31 which is the number of days in March. Suppose we have April 1st to May 1st, `(153 * 4 + 8) // 5 = 124` and `(153 * 5 + 8) // 5 = 154`, the difference is now 30 which is the number of days in April. You can also check other months.
26 | 
27 | ```cpp
28 | // Author: github.com/lzl124631x
29 | // Time: O(1)
30 | // Space: O(1)
31 | // Ref: https://leetcode.com/problems/number-of-days-between-two-dates/discuss/517582/Python-Magical-Formula
32 | int days(string date) {
33 |     int y = stoi(date.substr(0, 4)), m = stoi(date.substr(5, 2)), d = stoi(date.substr(8));
34 |     if (m < 3) {
35 |         m += 12;
36 |         y -= 1;
37 |     }
38 |     return 365 * y + y / 4 + y / 400 - y / 100 + d + (153 * m + 8) / 5;
39 | }
40 | ```
41 | 
42 | ## Problems
43 | 
44 | * [1360. Number of Days Between Two Dates \(Easy\)](https://leetcode.com/problems/number-of-days-between-two-dates/)
45 | * [1154. Day of the Year \(Easy\)](https://leetcode.com/problems/day-of-the-year/)
46 | 
47 | 


--------------------------------------------------------------------------------
/difference-array.md:
--------------------------------------------------------------------------------
 1 | # Difference Array
 2 | 
 3 | Assume we have an array `A` of size `N`, and given a list of updates of length `K`, each of which is in the form of `[from, to, diff]` which means adding `diff` to all elements with indexes in range `[from, to]`.
 4 | 
 5 | For example:
 6 | 
 7 | ```
 8 | A: [0, 0, 0, 0]
 9 | updates: [[0,1,2], [1,2,1],[3,3,6]]
10 | 
11 | // after updates
12 | A: [2, 3, 1, 6]
13 | ```
14 | 
15 | The brute force way is to visit all elements in range `[from, to]` and add `diff` to them for each update. It will take `O(NK)` time.
16 | 
17 | We can improve this by using difference array, i.e. only storing the delta value at break points. Let `delta[i]` be `U[i] - U[i-1]` where `U[i]` is the sum of all `diff`s to `A[i]`.
18 | 
19 | ```
20 | A: [0, 0, 0, 0]
21 | updates: [[0,1,2], [1,2,1],[3,3,6]]
22 | 
23 | U: [2, 3, 1, 6]
24 | delta: [2, 1, -2, 5]
25 | // after update
26 | A: [2, 2+1, 2+1-2, 2+1-2+5] = [2, 3, 1, 6]
27 | ```
28 | 
29 | For `update[i] = [from, to, diff]`, we do:
30 | 
31 | * `delta[from] += diff`
32 | * `delta[to+1] -= diff`
33 | 
34 | ```
35 | updates: [[0,1,2], [1,2,1],[3,3,6]]
36 | // apply first update
37 | delta: [2, 0, -2, 0]
38 | // apply second update
39 | delta: [2, 1, -2, -1]
40 | // apply third update
41 | delta: [2, 1, -2, 5]
42 | ```
43 | 
44 | So in the end we just need to traverse `delta` array to recover the `U` array.
45 | 
46 | ## Problems
47 | 
48 | * [1674. Minimum Moves to Make Array Complementary (Medium)](https://leetcode.com/problems/minimum-moves-to-make-array-complementary/)
49 | * [1854. Maximum Population Year (Easy)](https://leetcode.com/problems/maximum-population-year/)


--------------------------------------------------------------------------------
/discretization.md:
--------------------------------------------------------------------------------
 1 | # Discretization
 2 | 
 3 | When the number range is very large and the numbers are very sparse, we can discretize the input numbers so that we can keep the ordering of the numbers while saving them in a much smaller array.
 4 | 
 5 | For example, the input array is:
 6 | 
 7 | ```text
 8 | -10000, 0, 10000
 9 | ```
10 | 
11 | If we need to create an array covering the range we need to create one with length 20001, but actually there are just 3 numbers in it.
12 | 
13 | We can turn it into
14 | 
15 | ```text
16 | 0, 1, 2
17 | ```
18 | 
19 | with the following mapping
20 | 
21 | ```text
22 | -10000 -> 0
23 | 0      -> 1
24 | 10000  -> 2
25 | ```
26 | 
27 | ## Implementation
28 | 
29 | ```cpp
30 | // Author: github.com/lzl124631x
31 | // Time: O(NlogN)
32 | // Space: O(N)
33 | vector<int> discretize(vector<int> &input) {
34 |     set<int> s(input.begin(), input.end()); // In this way, we dedupe the data and sort them
35 |     unordered_map<int, int> m; // mapping from old number to new number
36 |     int id = 0;
37 |     for (int n : s) m[n] = id++;
38 |     vector<int> output(input.size());
39 |     for (int i = 0; i < input.size(); ++i) output[i] = m[input[i]];
40 |     return output;
41 | }
42 | ```
43 | 
44 | ## Problem
45 | 
46 | * [327. Count of Range Sum (Hard)](https://leetcode.com/problems/count-of-range-sum) **When using with BIT**
47 | * [699. Falling Squares (Hard)](https://leetcode.com/problems/falling-squares/)
48 | 


--------------------------------------------------------------------------------
/divide-and-conquer.md:
--------------------------------------------------------------------------------
 1 | # Divide And Conquer
 2 | 
 3 | Solution template for the divide and conquer problems:
 4 | 
 5 | * Define the base case\(s\).
 6 | * Split the problem into subproblems and solve them recursively.
 7 | * Merge the solutions for the subproblems to obtain the solution for the original problem.
 8 | 
 9 | See all the related problems [here](https://leetcode.com/tag/divide-and-conquer/)
10 | 
11 | ## Problems
12 | 
13 | **Problems similar to Merge Sort**
14 | * [315. Count of Smaller Numbers After Self (Hard)](https://leetcode.com/problems/count-of-smaller-numbers-after-self/)
15 | * [493. Reverse Pairs (Hard)](https://leetcode.com/problems/reverse-pairs/)
16 | * [1649. Create Sorted Array through Instructions (Hard)](https://leetcode.com/problems/create-sorted-array-through-instructions/)
17 | * [327. Count of Range Sum (Hard)](https://leetcode.com/problems/count-of-range-sum/)


--------------------------------------------------------------------------------
/dynamic-programming/bitmask-dp.md:
--------------------------------------------------------------------------------
1 | # Bitmask Dp
2 | 
3 | ## Problems
4 | 
5 | * [1125. Smallest Sufficient Team \(Hard\)](https://leetcode.com/problems/smallest-sufficient-team/)
6 | * [1494. Parallel Courses II \(Hard\)](https://leetcode.com/problems/parallel-courses-ii/)
7 | * [1879. Minimum XOR Sum of Two Arrays (Hard)](https://leetcode.com/problems/minimum-xor-sum-of-two-arrays/)
8 | * [943. Find the Shortest Superstring (Hard)](https://leetcode.com/problems/find-the-shortest-superstring/)


--------------------------------------------------------------------------------
/dynamic-programming/dp-on-subsets.md:
--------------------------------------------------------------------------------
 1 | # Dp On Subsets
 2 | 
 3 | ## DP on Subsets
 4 | 
 5 | ## Problems
 6 | 
 7 | Note that the following problems can also be solved using DFS + Pruning tricks.
 8 | 
 9 | * [698. Partition to K Equal Sum Subsets (Medium)](https://leetcode.com/problems/partition-to-k-equal-sum-subsets/)
10 | * [473. Matchsticks to Square (Medium)](https://leetcode.com/problems/matchsticks-to-square/)
11 | * [1723. Find Minimum Time to Finish All Jobs (Hard)](https://leetcode.com/problems/find-minimum-time-to-finish-all-jobs/)
12 | 
13 | [https://leetcode.com/discuss/general-discussion/1125779/dynamic-programming-on-subsets-with-examples-explained](https://leetcode.com/discuss/general-discussion/1125779/dynamic-programming-on-subsets-with-examples-explained)
14 | 
15 | Q: Merge bitmask dp into this?
16 | 
17 | Q: can this be merged with traveling salesperson problem?
18 | 


--------------------------------------------------------------------------------
/dynamic-programming/dp-on-tree.md:
--------------------------------------------------------------------------------
1 | # DP on Tree
2 | 
3 | ## Problems
4 | 
5 | * [1896. Minimum Cost to Change the Final Value of Expression (Hard)](https://leetcode.com/problems/minimum-cost-to-change-the-final-value-of-expression/)


--------------------------------------------------------------------------------
/dynamic-programming/dp-with-sorting.md:
--------------------------------------------------------------------------------
1 | # DP with Sorting
2 | 
3 | * [1751. Maximum Number of Events That Can Be Attended II (Hard)](https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended-ii/)


--------------------------------------------------------------------------------
/dynamic-programming/dynamic-programming.md:
--------------------------------------------------------------------------------
 1 | # Dynamic Programming
 2 | 
 3 | Dynamic Programming is basically DFS with memoization.
 4 | 
 5 | We can use DFS to solve the DP problem in small scale, but when the input size is large, plain DFS will be too slow because we recompute the result for some specific states over and over again, wasting time.
 6 | 
 7 | ## What's the difference between Top-down DP and Bottom-up DP?
 8 | 
 9 | Top-down DP:
10 | * = DFS + memo
11 | * It's recursive
12 | * We start from the original problem, and search into sub-problems (i.e. use the results of the sub-problems).
13 | * If we visualize the DFS search as a tree, top-down DP is going from the root to leaf nodes.
14 | 
15 | Bottom-up DP:
16 | * It's iterative
17 | * We start from resolving the minimal sub-problems, then use those results to build up solutions for sub-problems with larger scale, until we get enough results to build the solution for the original problem.
18 | * If we visualize the DFS search as a tree, bottom-up DP is going from the leaf nodes to the root.
19 | 
20 | ## When to use DP?
21 | 
22 | 1. it involves searching, especially DFS. We can use DFS to solve the problem in small scale
23 | 2. it only cares about the optimal solution -- Optimal substructure
24 | 3. During searching, we might go into the same state from different paths -- Overlapping sub-problems.
25 | 
26 | ## What is the common process to solve DP problems?
27 | 
28 | 1. Think in DFS way. Identify the states we need to use in each DFS invocation.
29 | 2. Define the transition between states.
30 | 3. Define special/trivial cases.
31 | 
32 | ## Types of DP
33 | ### Sequence DP
34 | 
35 | We scan the sequence one by one, make decisions at each step.
36 | 
37 | #### Problems
38 | 
39 | * [983. Minimum Cost For Tickets (Medium)](https://leetcode.com/problems/minimum-cost-for-tickets/)
40 | * [691. Stickers to Spell Word](https://leetcode.com/problems/stickers-to-spell-word/)
41 | * [174. Dungeon Game \(Hard\)](https://leetcode.com/problems/dungeon-game/)
42 | * [576. Out of Boundary Paths \(Medium\)](https://leetcode.com/problems/out-of-boundary-paths/)
43 | * [446. Arithmetic Slices II - Subsequence \(Hard\)](https://leetcode.com/problems/arithmetic-slices-ii-subsequence/)
44 | * [1463. Cherry Pickup II (Hard)](https://leetcode.com/problems/cherry-pickup-ii/)
45 | * [1473. Paint House III (Hard)](https://leetcode.com/problems/paint-house-iii/)
46 | * [44. Wildcard Matching (Hard)](https://leetcode.com/problems/wildcard-matching/)
47 | * [1866. Number of Ways to Rearrange Sticks With K Sticks Visible (Hard)](https://leetcode.com/problems/number-of-ways-to-rearrange-sticks-with-k-sticks-visible/)
48 | 
49 | ### Interval DP
50 | 
51 | * [1478. Allocate Mailboxes (Hard)](https://leetcode.com/problems/allocate-mailboxes/)
52 | * [410. Split Array Largest Sum (Hard)](https://leetcode.com/problems/split-array-largest-sum/)
53 | * [1547. Minimum Cost to Cut a Stick (Hard)](https://leetcode.com/problems/minimum-cost-to-cut-a-stick/)
54 | * [1140. Stone Game II (Medium)](https://leetcode.com/problems/stone-game-ii/)
55 | * [1563. Stone Game V (Hard)](https://leetcode.com/problems/stone-game-v/)
56 | 
57 | Second Type 375 1246
58 | 
59 | ### weighted interval scheduling dp
60 | 
61 | ### State Compression DP
62 | 
63 | Usually used to solve NP-hard problems on small scale dataset, faster then search \(DFS or BFS\).
64 | 
65 | Example: Travelling salesman problem \(TSP\)
66 | 
67 | #### Problems
68 | 
69 | * [1349. Maximum Students Taking Exam \(Hard\)](https://leetcode.com/problems/maximum-students-taking-exam/)
70 | 
71 | ### Longest Palindromic Subsequence
72 | 
73 | *  [516. Longest Palindromic Subsequence (Medium)](https://leetcode.com/problems/longest-palindromic-subsequence/)
74 | *  [1771. Maximize Palindrome Length From Subsequences (Hard)](https://leetcode.com/problems/maximize-palindrome-length-from-subsequences/)
75 | 
76 | ### Uncategorized
77 | 
78 | * [1000. Minimum Cost to Merge Stones (Hard)](https://leetcode.com/problems/minimum-cost-to-merge-stones/)
79 | * [1368. Minimum Cost to Make at Least One Valid Path in a Grid (Hard)](https://leetcode.com/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid/): BFS + DP
80 | * [1815. Maximum Number of Groups Getting Fresh Donuts (Hard)](https://leetcode.com/problems/maximum-number-of-groups-getting-fresh-donuts/): Greedy + DP
81 | * [1937. Maximum Number of Points with Cost (Medium)](https://leetcode.com/problems/maximum-number-of-points-with-cost/)
82 | 
83 | ### Links
84 | 
85 | * [DP Problem Classifications - Helpful Notes](https://leetcode.com/problems/longest-palindromic-subsequence/discuss/222605/DP-Problem-Classifications-Helpful-Notes)


--------------------------------------------------------------------------------
/dynamic-programming/knapsack/0-1-knapsack.md:
--------------------------------------------------------------------------------
 1 | # 0-1 Knapsack (01背包问题)
 2 | 
 3 | Given a list of items with weight `w[i]` and value `v[i]`, what's the maximum value you can get given a knapsack with capacity `C`, i.e. it can hold items with at most weight `C` in total. You can pick each item **at most once** \(i.e. either pick an item `i` 0 times or 1 time\).
 4 | 
 5 | ## Algorithm
 6 | 
 7 | Let `dp[i + 1][c]` be the maximum value we can get using the first `i + 1` items \(index from `0` to `i`\) and weight capped by `c`.
 8 | 
 9 | ```text
10 | dp[i + 1][c] = max(
11 |     dp[i][c],             // If we skip `i`-th item
12 |     dp[i][c-w[i]] + v[i]  // If we pick `i`-th item
13 | )
14 | 
15 | dp[0][c] = 0
16 | ```
17 | 
18 | ## Implementation
19 | 
20 | ```cpp
21 | // Time: O(NC)
22 | // Space: O(NC)
23 | vector<vector<int>> dp(N + 1, vector<int>(C + 1));
24 | for (int i = 0; i < N; ++i) {
25 |     for (int c = w[i]; c <= C; ++c) {
26 |         dp[i + 1][c] = max( dp[i][c], dp[i][c - w[i]] + v[i] );
27 |     }
28 | }
29 | return dp[N][C];
30 | ```
31 | 
32 | ## Space Optimization
33 | 
34 | ```cpp
35 | // Time: O(NC)
36 | // Space: O(C)
37 | vector<int> dp(C + 1);
38 | for (int i = 0; i < N; ++i) {
39 |     for (int c = C; c >= w[i]; --c) {
40 |         dp[c] = max( dp[c], dp[c - w[i]] + v[i] );
41 |     }
42 | }
43 | return dp[C];
44 | ```
45 | 
46 | ## A Constant Optimization
47 | 
48 | Since we only need `dp[N][C]`, which only requires `dp[N-1][C]` and `dp[N-1][C-w[N-1]]`. So for `i = N - 2` \(the second from the last item\), we only need to loop from `max( w[N-2], C - w[N-1] )` to `C`.
49 | 
50 | `dp[N-1][C-w[N-1]]` requires `dp[N-2][C]` and `dp[N-2][C-w[N-1]-w[N-2]]`, so for `i = N - 3`, we only need to loop from `max( w[N-3], C - w[N-1] - w[N-2] )` to `C`.
51 | 
52 | Generalization: for `i`-th item, the inner loop should be from `max( w[i], C - sum(w[j] | i < j < N ) )` to `C`.
53 | 
54 | ```cpp
55 | // Time: O(NC)
56 | // Space: O(C)
57 | vector<int> dp(C + 1);
58 | int sum = accumulate(w.begin(), w.end(), 0);
59 | for (int i = 0; i < N; ++i) {
60 |     sum -= w[i];
61 |     for (int c = C; c >= max(w[i], C - sum); --c) {
62 |         dp[c] = max( dp[c], dp[c - w[i]] + v[i] );
63 |     }
64 | }
65 | return dp[C];
66 | ```
67 | 
68 | ## Problems
69 | 
70 | * [416. Partition Equal Subset Sum \(Medium\)](https://leetcode.com/problems/partition-equal-subset-sum/)
71 | * [474. Ones and Zeroes \(Medium\)](https://leetcode.com/problems/ones-and-zeroes/)
72 | * [494. Target Sum (Medium)](https://leetcode.com/problems/target-sum/)
73 | 
74 | 


--------------------------------------------------------------------------------
/dynamic-programming/knapsack/README.md:
--------------------------------------------------------------------------------
 1 | # Knapsack
 2 | 
 3 | The knapsack problem is a typical DP problem.
 4 | 
 5 | ## Type
 6 | 
 7 | 1. 0-1 Knapsack (01背包问题. 每个物品最多选一次)
 8 | 2. Unbounded Knapsack (完全背包问题. 每个物品可以选无限次)
 9 | 3. Bounded Knapsack (多重背包问题. 每个物品可以选有限次)
10 | 4. 混合背包问题 (每个物品能选取的次数可能是1次, 有限次或者无限次)
11 | 5. 二维费用背包问题
12 | 6. 分组背包问题 (同一组内的物品只能选一个)
13 | 7. 背包问题求方案数
14 | 8. 求背包问题的方案
15 | 9. 有依赖的背包问题
16 | 
17 | ## Reference
18 | 
19 | * [背包九讲](https://github.com/tianyicui/pack)
20 | 
21 | * [背包九讲专题 | 大雪菜](https://www.bilibili.com/video/BV1qt411Z7nE)


--------------------------------------------------------------------------------
/dynamic-programming/knapsack/bounded-knapsack.md:
--------------------------------------------------------------------------------
1 | # Bounded Knapsack (有限背包问题)
2 | 
3 | ## Problems
4 | 
5 | * [2585. Number of Ways to Earn Points (Hard)](https://leetcode.com/problems/number-of-ways-to-earn-points)
6 | * [2902. Count of Sub-Multisets With Bounded Sum (Hard)](https://leetcode.com/problems/count-of-sub-multisets-with-bounded-sum)


--------------------------------------------------------------------------------
/dynamic-programming/knapsack/unbounded-knapsack.md:
--------------------------------------------------------------------------------
 1 | # Unbounded Knapsack (无限背包问题)
 2 | 
 3 | Given a list of items with weight `w[i]` and value `v[i]`, what's the maximum value you can get given a knapsack with capacity `C`, i.e. it can hold items with at most weight `C` in total. You can pick each item **unlimited times**.
 4 | 
 5 | ## Basic Version
 6 | 
 7 | ### Algorithm
 8 | 
 9 | Let `dp[i + 1][c]` be the maximum value we can get using the first `i + 1` items \(index from `0` to `i`\).
10 | 
11 | ```text
12 | dp[i + 1][c] = max( dp[i][c - k * w[i]] + k * v[i] | k >= 0 && c - k * w[i] >= 0 )
13 | dp[0][c] = 0
14 | ```
15 | 
16 | ### Implementation
17 | 
18 | ```cpp
19 | // Time: O(NC^2)
20 | // Space: O(NC)
21 | vector<vector<int>> dp(N + 1, vector<int>(C + 1));
22 | for (int i = 0; i < N; ++i) {
23 |     for (int c = w[i]; c <= C; ++c) {
24 |         for (int k = 0; c - k * w[i] >= 0; ++k) {
25 |             dp[i + 1][c] = max( dp[i + 1][c], dp[i][c - k * w[i]] + k * v[i] );
26 |         }
27 |     }
28 | }
29 | return dp[N][C];
30 | ```
31 | 
32 | ## Optimized Version
33 | 
34 | ### Algorithm
35 | 
36 | We can examine the relationship between `dp[i + 1][c]` and `dp[i + 1][c - w[i]]`.
37 | 
38 | ```text
39 | dp[i + 1][c] = max(
40 |                     dp[i][c],
41 |                     dp[i][c - w[i]] + v[i],
42 |                     dp[i][c - 2 * w[i]] + 2 * v[i],
43 |                     ...
44 |                   )
45 | dp[i + 1][c - w[i]] = max(
46 |                             dp[i][c - w[i]],
47 |                             dp[i][c - 2 * w[i]] + v[i],
48 |                             dp[i][c - 3 * w[i]] + 2 * v[i],
49 |                             ...
50 |                          )
51 | ```
52 | 
53 | So we have
54 | 
55 | ```text
56 | dp[i + 1][c] = max( dp[i][c], dp[i + 1][c - w[i]] + v[i] )
57 | ```
58 | 
59 | ### Implementation
60 | 
61 | ```cpp
62 | // Time: O(NC)
63 | // Space: O(NC)
64 | vector<vector<int>> dp(N + 1, vector<int>(C + 1));
65 | for (int i = 0; i < N; ++i) {
66 |     for (int c = w[i]; c <= C; ++c) {
67 |         dp[i + 1][c] = max( dp[i][c], dp[i + 1][c - w[i]] + v[i] );
68 |     }
69 | }
70 | return dp[N][C];
71 | ```
72 | 
73 | ### Space Optimization
74 | 
75 | ```cpp
76 | // Time: O(NC)
77 | // Space: O(C)
78 | vector<int> dp(C + 1);
79 | for (int i = 0; i < N; ++i) {
80 |     for (int c = w[i]; c <= C; ++c) {
81 |         dp[c] = max( dp[c], dp[c - w[i]] + v[i] );
82 |     }
83 | }
84 | return dp[C];
85 | ```
86 | 
87 | ## Problems
88 | 
89 | * [518. Coin Change 2 \(Medium\)](https://leetcode.com/problems/coin-change-2/)
90 | 
91 | 


--------------------------------------------------------------------------------
/dynamic-programming/selective-state-dp.md:
--------------------------------------------------------------------------------
1 | # Selective State DP
2 | 
3 | TODO 
4 | 
5 | * 1262 select remainder as state


--------------------------------------------------------------------------------
/dynamic-programming/traveling-salesperson.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lzl124631x/algorithm/95ef6c166ecc639fcaf594ceffc7092032be995a/dynamic-programming/traveling-salesperson.key


--------------------------------------------------------------------------------
/dynamic-programming/travelling-salesperson.md:
--------------------------------------------------------------------------------
 1 | # Travelling Salesperson Problem
 2 | 
 3 | The Travelling Salesperson Problem is a classic DP problem. 
 4 | 
 5 | The brute force solution is to enumerate all `N!` permutations of nodes.
 6 | 
 7 | To eliminate repetitive computations, we need to observe the fact that there is only one optimal answer (i.e. cost) for a subset of nodes, so we can memoize the optimal answer for subsets of nodes. In this way, instead of enumerating on all `N!` permutations, we just enumerate on all `2^N` subsets.
 8 | 
 9 | ![](../.gitbook/assets/traveling-salesperson.png)
10 | 
11 | ## Problems
12 | 
13 | * [1879. Minimum XOR Sum of Two Arrays (Hard)](https://leetcode.com/problems/minimum-xor-sum-of-two-arrays/)
14 | * [943. Find the Shortest Superstring (Hard)](https://leetcode.com/problems/find-the-shortest-superstring/)


--------------------------------------------------------------------------------
/graph/README.md:
--------------------------------------------------------------------------------
1 | # Graph
2 | 
3 | 


--------------------------------------------------------------------------------
/graph/bi-directional-breadth-first-search.md:
--------------------------------------------------------------------------------
1 | # Bi-directional Breadth First Search
2 | 
3 | ## Problems
4 | 
5 | * [127. Word Ladder (Hard)](https://leetcode.com/problems/word-ladder/)


--------------------------------------------------------------------------------
/graph/bipartite.md:
--------------------------------------------------------------------------------
 1 | # Bipartite
 2 | 
 3 | A bipartite graph (or bigraph) is a graph whose vertices can be divided into two disjoint and independent sets U and V such that every edge connects a vertex in U to one in V. Vertex sets U and V are usually called the parts of the graph. Equivalently, a bipartite graph is a graph that does not contain any odd-length cycles.
 4 | 
 5 | ![Bipartite](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Simple-bipartite-graph.svg/220px-Simple-bipartite-graph.svg.png)
 6 | 
 7 | ## Is graph bipartite?
 8 | 
 9 | [785. Is Graph Bipartite? \(Medium\)](https://leetcode.com/problems/is-graph-bipartite/)
10 | 
11 | ### DFS
12 | 
13 | **DFS to jump between two parts and assign part number to nodes**
14 | 
15 | Take each node in the Graph as starting point of DFS.
16 | 
17 | Assign the nodes to one of two parts, `-1` and `1`, in an alternating order.
18 | 
19 | If a node is already assigned to a part, once it's visited again, its part should be the same as the part of the previous node.
20 | 
21 | ```cpp
22 | // OJ: https://leetcode.com/problems/is-graph-bipartite/
23 | // Author: github.com/lzl124631x
24 | // Time: O(V + E)
25 | // Space: O(V + E)
26 | class Solution {
27 | public:
28 |     bool isBipartite(vector<vector<int>>& G) {
29 |         vector<int> id(G.size());
30 |         function<bool(int, int)> dfs = [&](int u, int prev) {
31 |             if (id[u]) return id[u] != prev; // This node's part should be the same as the part of the previous part
32 |             id[u] = -prev; // Assign nodes to one of the two parts, -1 or 1
33 |             for (int v : G[u]) {
34 |                 if (!dfs(v, id[u])) return false;
35 |             }
36 |             return true;
37 |         };
38 |         for (int i = 0; i < G.size(); ++i) {
39 |             if (id[i]) continue; // This node is already assigned to a part
40 |             if (!dfs(i, 1)) return false;
41 |         }
42 |         return true;
43 |     }
44 | };
45 | ```
46 | 
47 | ### BFS
48 | 
49 | Take each node in the Graph as starting point of BFS.
50 | 
51 | Assign nodes to part `-1` or `1` layer by layer in an alternating order.
52 | 
53 | If a node is already assigned to a part, once it's visited again, its part should be the same as the part of the previous node.
54 | 
55 | ```cpp
56 | // OJ: https://leetcode.com/problems/is-graph-bipartite/
57 | // Author: github.com/lzl124631x
58 | // Time: O(V + E)
59 | // Space: O(V + E)
60 | class Solution {
61 | public:
62 |     bool isBipartite(vector<vector<int>>& G) {
63 |         vector<int> id(G.size());
64 |         queue<int> q;
65 |         for (int i = 0; i < G.size(); ++i) {
66 |             if (id[i]) continue; // This node is already assigned to a part
67 |             q.push(i);
68 |             id[i] = 1; // Assign this starting node to part 1
69 |             while (q.size()) {
70 |                 int u = q.front();
71 |                 q.pop();
72 |                 for (int v : G[u]) {
73 |                     if (id[v]) {
74 |                         if (id[v] != -id[u]) return false; // Two neighboring nodes shouldn't be in the same part
75 |                         continue;
76 |                     }
77 |                     id[v] = -id[u]; // Assign neighbor node to the other part
78 |                     q.push(v);
79 |                 }
80 |             }
81 |         }
82 |         return true;
83 |     }
84 | };
85 | ```
86 | 
87 | ## Problems
88 | 
89 | * [785. Is Graph Bipartite? \(Medium\)](https://leetcode.com/problems/is-graph-bipartite/)
90 | * [886. Possible Bipartition \(Medium\)](https://leetcode.com/problems/possible-bipartition/)
91 | 
92 | 


--------------------------------------------------------------------------------
/graph/breadth-first-search.md:
--------------------------------------------------------------------------------
 1 | # Breadth First Search (BFS)
 2 | 
 3 | ## Note
 4 | 
 5 | Use `queue<T>` to store the nodes in Breadth-first order.
 6 | 
 7 | To avoid visiting the same node twice, use a `vector<bool>` or `unordered_set<T>` to store whether the node has been visited.
 8 | 
 9 | Make sure marking the node as visited **before** the node is enqueued! Otherwise the same node might be added multiple times.
10 | 
11 | ## Problems
12 | 
13 | * [1311. Get Watched Videos by Your Friends (Medium)](https://leetcode.com/problems/get-watched-videos-by-your-friends/)


--------------------------------------------------------------------------------
/graph/component-coloring.md:
--------------------------------------------------------------------------------
 1 | # Component Coloring
 2 | 
 3 | Color each connected component in a graph with different colors.
 4 | 
 5 | ## Implementation
 6 | 
 7 | Implement a function `int componentColoring(vector<vector<int>> &G, vector<int> &color)` where `G` is an adjacency list representation of the graph, `color` should be updated such that `color[i]` is the color index \(starting from `0`\) of the component where `i`th node belongs, and the return value is the number of colors \(i.e. components\).
 8 | 
 9 | ### DFS
10 | 
11 | ```cpp
12 | void dfs(vector<vector<int>> &G, int u, vector<int> &color, int k) {
13 |     color[u] = k;
14 |     for (int v : G[u]) {
15 |         if (color[v] > -1) continue;
16 |         dfs(G, v, color, k);
17 |     }
18 | }
19 | int componentColoring(vector<vector<int>> &G, vector<int> &color) {
20 |     int N = G.size(), k = 0;
21 |     color.resize(N);
22 |     fill(color.begin(), color.end(), -1);
23 |     for (int i = 0; i < N; ++i) {
24 |         if (color[i] > -1) continue;
25 |         dfs(G, i, color, k++);
26 |     }
27 |     return k;
28 | }
29 | ```
30 | 
31 | ### BFS
32 | 
33 | ```cpp
34 | int componentColoring(vector<vector<int>> &G, vector<int> &color) {
35 |     int N = G.size(), k = 0;
36 |     color.resize(N);
37 |     fill(color.begin(), color.end(), -1);
38 |     for (int i = 0; i < N; ++i) {
39 |         if (color[i] > -1) continue;
40 |         queue<int> q;
41 |         q.push(i);
42 |         color[i] = k;
43 |         while (q.size()) {
44 |             int u = q.front();
45 |             q.pop();
46 |             for (int v : G[u]) {
47 |                 if (color[v] > -1) continue;
48 |                 q.push(v);
49 |                 color[v] = k;
50 |             }
51 |         }
52 |         ++k;
53 |     }
54 |     return k;
55 | }
56 | ```
57 | 
58 | ### Union Find
59 | 
60 | ```cpp
61 | class UnionFind {
62 |     vector<int> id;
63 | public:
64 |     UnionFind(int n) : id(n) {
65 |         for (int i = 0; i < n; ++i) id[i] = i;
66 |     }
67 |     void connect(int a, int b) {
68 |         int x = find(a), y = find(b);
69 |         if (x == y) return;
70 |         id[x] = y;
71 |     }
72 |     int find(int a) {
73 |         return id[a] == a ? a : (id[a] = find(id[a]));
74 |     }
75 | };
76 | int componentColoring(vector<vector<int>> &G, vector<int> &color) {
77 |     int N = G.size(), k = 0;
78 |     color.resize(N);
79 |     fill(color.begin(), color.end(), -1);
80 |     UnionFind uf(N);
81 |     for (int u = 0; u < N; ++u) {
82 |         for (int v : G[u]) uf.connect(u, v);
83 |     }
84 |     for (int i = 0; i < N; ++i) {
85 |         int r = uf.find(i);
86 |         if (color[r] == -1) color[r] = k++;
87 |         color[i] = color[r];
88 |     }
89 |     return k;
90 | }
91 | ```
92 | 
93 | 


--------------------------------------------------------------------------------
/graph/component-count.md:
--------------------------------------------------------------------------------
  1 | # Component Count
  2 | 
  3 | A \[**component**\]\([https://en.wikipedia.org/wiki/Component\_\(graph\_theory](https://en.wikipedia.org/wiki/Component_%28graph_theory)\)\) in a graph is a set of vertices where each of them are neighbors and none of them is neighbor of vertices outside of this set.
  4 | 
  5 | Count connected components in a graph.
  6 | 
  7 | ## Implementation
  8 | 
  9 | [323. Number of Connected Components in an Undirected Graph (Medium)](https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/)
 10 | 
 11 | Implement a function `int getComponentCount(vector<vector<int>> &G)`, where `G` is an adjacency list representation of the graph, and the return value is the count of components in the graph.
 12 | 
 13 | ### DFS
 14 | 
 15 | ```cpp
 16 | void bfs(vector<vector<int>> &G, vector<bool> &visited, int start) {
 17 |     visited[start] = true;
 18 |     queue<int> q;
 19 |     q.push(start);
 20 |     while (q.size()) {
 21 |         int u = q.front();
 22 |         q.pop();
 23 |         for (int v : G[u]) {
 24 |             if (visited[v]) continue;
 25 |             visited[v] = true;
 26 |             q.push(v);
 27 |         }
 28 |     }
 29 | }
 30 | int getComponentCount(vector<vector<int>> &G) {
 31 |     int ans = 0;
 32 |     vector<bool> visited(G.size());
 33 |     for (int i = 0; i < G.size(); ++i) {
 34 |         if (visited[i]) continue;
 35 |         ++ans;
 36 |         bfs(G, visited, i);
 37 |     }
 38 |     return ans;
 39 | }
 40 | ```
 41 | 
 42 | ### BFS
 43 | 
 44 | ```cpp
 45 | void bfs(vector<vector<int>> &G, vector<bool> &visited, int start) {
 46 |     visited[start] = true;
 47 |     queue<int> q;
 48 |     q.push(start);
 49 |     while (q.size()) {
 50 |         int u = q.front();
 51 |         q.pop();
 52 |         for (int v : G[u]) {
 53 |             if (visited[v]) continue;
 54 |             visited[v] = true;
 55 |             q.push(v);
 56 |         }
 57 |     }
 58 | }
 59 | int getComponentCount(vector<vector<int>> &G) {
 60 |     int ans = 0;
 61 |     vector<bool> visited(G.size());
 62 |     for (int i = 0; i < G.size(); ++i) {
 63 |         if (visited[i]) continue;
 64 |         ++ans;
 65 |         bfs(G, visited, i);
 66 |     }
 67 |     return ans;
 68 | }
 69 | ```
 70 | 
 71 | ### Union Find
 72 | 
 73 | ```cpp
 74 | class UnionFind {
 75 |     vector<int> id, rank;
 76 |     int cnt;
 77 | public:
 78 |     UnionFind(int n) : cnt(n), id(n), rank(n, 1) {
 79 |         for (int i = 0; i < n; ++i) id[i] = i;
 80 |     }
 81 |     int find(int a) {
 82 |         return id[a] == a ? a : (id[a] = find(id[a]));
 83 |     }
 84 |     void connect(int a, int b) {
 85 |         int x = find(a), y = find(b);
 86 |         if (x == y) return;
 87 |         if (rank[x] <= rank[y]) {
 88 |             id[x] = y;
 89 |             if (rank[x] == rank[y]) rank[y]++;
 90 |         } else id[y] = x;
 91 |         --cnt;
 92 |     }
 93 |     int getCount() { return cnt; }
 94 | };
 95 | int getComponentCount(vector<vector<int>> &G) {
 96 |     UnionFind uf(G.size());
 97 |     for (int u = 0; u < G.size(); ++u) {
 98 |         for (int v : G[u]) uf.connect(u, v);
 99 |     }
100 |     return uf.getCount();
101 | }
102 | ```
103 | 
104 | ## Problems
105 | 
106 | * [947. Most Stones Removed with Same Row or Column \(Medium\)](https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/)
107 | * [200. Number of Islands \(Medium\)](https://leetcode.com/problems/number-of-islands/)
108 | * [323. Number of Connected Components in an Undirected Graph (Medium)](https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/)


--------------------------------------------------------------------------------
/graph/depth-first-search.md:
--------------------------------------------------------------------------------
 1 | # Depth First Search (DFS)
 2 | 
 3 | Note that if a graph is acyclic, we don't need to keep a set of visited nodes to prevent going into a loop.
 4 | 
 5 | Example: [797. All Paths From Source to Target (Medium)](https://leetcode.com/problems/all-paths-from-source-to-target/)
 6 | 
 7 | ## Problems
 8 | 
 9 | * [17. Letter Combinations of a Phone Number \(Medium\)](https://leetcode.com/problems/letter-combinations-of-a-phone-number/)
10 | * [39. Combination Sum \(Medium\)](https://leetcode.com/problems/combination-sum/)
11 | * [40. Combination Sum II \(Medium\)](https://leetcode.com/problems/combination-sum-ii/)
12 | * [77. Combinations \(Medium\)](https://leetcode.com/problems/combinations/)
13 | * [212. Word Search II \(Hard\)](https://leetcode.com/problems/word-search-ii/)
14 | * [216. Combination Sum III \(Medium\)](https://leetcode.com/problems/combination-sum-iii/)
15 | * [797. All Paths From Source to Target (Medium)](https://leetcode.com/problems/all-paths-from-source-to-target/)
16 | * [1219. Path with Maximum Gold (Medium)](https://leetcode.com/problems/path-with-maximum-gold/)
17 | * [1601. Maximum Number of Achievable Transfer Requests (Hard)](https://leetcode.com/problems/maximum-number-of-achievable-transfer-requests/)


--------------------------------------------------------------------------------
/graph/eulerian-path.md:
--------------------------------------------------------------------------------
 1 | # Eulerian Path
 2 | 
 3 | An Eulerian path (欧拉路径; 一笔画问题) is a path visiting every **edge** exactly once.
 4 | 
 5 | Any connected directed graph where all nodes have equal in-degree and out-degree has an Eulerian circuit \(an Eulerian path ending where it started.\)
 6 | 
 7 | If the end point is the same as the starting point, this Eulerian Path is called an **Eulerian Circuit** (欧拉回路).
 8 | 
 9 | ## Detecting Eulerian Path
10 | 
11 | Undirected Graph:
12 | * If there are only TWO nodes with odd degrees and all other nodes have even degrees, then there must exist an Eulerian Path (NOT Circuit) from one of the odd-degree node to the other odd-degree node.
13 | * If all nodes have even degrees, this Eulerian Path is also a Eulerian Circuit.
14 | 
15 | Directioned Graph:
16 | * If there is at most one node `u` whose `outdegree[u] = indegree[u] + 1`, and at most one node `v` whose `indegree[v] = outdegree[v] + 1`, then there must exists an Eulerian Path from `u` (If `u` doesn't exist, any node works) to `v` (If `v` doesn't exist, any node works).
17 | * If every nodes `n` has `indegree[n] = outdegree[n]`, then there is an Eulerian Circuit.
18 | 
19 | ## Finding Eulerian Circuit: Hierholzer’s Algorithm
20 | 
21 | [Hierholzer’s Algorithm for directed graph](https://www.geeksforgeeks.org/hierholzers-algorithm-directed-graph/)
22 | 
23 | We can find the circuit/path in `O(E)`, i.e. linear time.
24 | 
25 | The algorithem is as follows \([wiki](https://en.wikipedia.org/wiki/Eulerian_path#Hierholzer.27s_algorithm)\):
26 | 
27 | * Choose any starting vertex `v`, and follow a trail of edges from that vertex until returning to `v`. It is not possible to get stuck at any vertex other than `v`, because the even degree of all vertices ensures that, when the trail enters another vertex `w` there must be an unused edge leaving `w`. The tour formed in this way is a closed tour, but may not cover all the vertices and edges of the initial graph.
28 | * As long as there exists a vertex `u` that belongs to the current tour but that has adjacent edges not part of the tour, start another trail from `u`, following unused edges until returning to `u`, and join the tour formed in this way to the previous tour.
29 | * Since we assume the original graph is connected, repeating the previous step will exhaust all edges of the graph.
30 | 
31 | 
32 | This is a Post-order DFS.
33 | 
34 | The following code is for [2097. Valid Arrangement of Pairs (Hard)](https://leetcode.com/problems/valid-arrangement-of-pairs/)
35 | 
36 | ```cpp
37 | // OJ: https://leetcode.com/problems/valid-arrangement-of-pairs/
38 | // Author: github.com/lzl124631x
39 | // Time: O(N + U) where N is the number of pairs and U is the number of unique numbers in the pairs
40 | // Space: O(N + U)
41 | class Solution {
42 | public:
43 |     vector<vector<int>> validArrangement(vector<vector<int>>& E) {
44 |         int N = E.size();
45 |         unordered_map<int, vector<int>> G;
46 |         unordered_map<int, int> indegree, outdegree;
47 |         G.reserve(N);
48 |         indegree.reserve(N);
49 |         outdegree.reserve(N);
50 |         for (auto &e : E) {
51 |             int u = e[0], v = e[1];
52 |             outdegree[u]++;
53 |             indegree[v]++;
54 |             G[u].push_back(v);
55 |         }
56 |         int start = -1;
57 |         for (auto &[u, vs] : G) {
58 |             if (outdegree[u] - indegree[u] == 1) {
59 |                 start = u; // If there exists one node `u` that `outdegree[u] = indegree[u] + 1`, use `u` as the start node.
60 |                 break;
61 |             }
62 |         }
63 |         if (start == -1) start = E[0][0]; // If there doesn't exist such node `u`, use any node as the start node
64 |         vector<vector<int>> ans;
65 |         function<void(int)> euler = [&](int u) {
66 |             auto &vs = G[u];
67 |             while (vs.size()) {
68 |                 int v = vs.back();
69 |                 vs.pop_back();
70 |                 euler(v);
71 |                 ans.push_back({ u, v }); // Post-order DFS. The edge is added after node `v` is exhausted
72 |             }
73 |         };
74 |         euler(start);
75 |         reverse(begin(ans), end(ans)); // Need to reverse the answer array in the end.
76 |         return ans;
77 |     }
78 | };
79 | ```
80 | 
81 | ## Problems
82 | 
83 | * [332. Reconstruct Itinerary (Hard)](https://leetcode.com/problems/reconstruct-itinerary/)
84 | * [753. Cracking the Safe \(Hard\)](https://leetcode.com/problems/cracking-the-safe/)
85 | * [2097. Valid Arrangement of Pairs (Hard)](https://leetcode.com/problems/valid-arrangement-of-pairs/)
86 | 


--------------------------------------------------------------------------------
/graph/maximum-bipartite-matching.md:
--------------------------------------------------------------------------------
 1 | # Maximum Bipartite Matching
 2 | 
 3 | ## Hungarian Maximum Matching Algorithm
 4 | 
 5 | ```cpp
 6 | // OJ: https://leetcode.com/problems/maximum-number-of-accepted-invitations/
 7 | // Author: github.com/lzl124631x
 8 | // Time: O(?)
 9 | // Space: O(N)
10 | class Solution {
11 | public:
12 |     int maximumInvitations(vector<vector<int>>& A) {
13 |         int M = A.size(), N = A[0].size(), ans = 0;
14 |         vector<int> match(N, -1);
15 |         vector<bool> seen;
16 |         function<bool(int)> dfs = [&](int u) {
17 |             for (int v = 0; v < N; ++v) {
18 |                 if (!A[u][v] || seen[v]) continue; // If there is no edge between (u, v), or this girl is visited already, skip
19 |                 seen[v] = true;
20 |                 if (match[v] == -1 || dfs(match[v])) {
21 |                     match[v] = u;
22 |                     return true;
23 |                 }
24 |             }
25 |             return false;
26 |         };
27 |         for (int i = 0; i < M; ++i) { // Try each node as the starting point of DFS
28 |             seen.assign(N, false);
29 |             if (dfs(i)) ++ans;
30 |         }
31 |         return ans;
32 |     }
33 | };
34 | ```
35 | 
36 | ## Problems
37 | 
38 | * [1820. Maximum Number of Accepted Invitations (Medium)](https://leetcode.com/problems/maximum-number-of-accepted-invitations/)
39 | 
40 | ## Reference
41 | 
42 | * [Kuhn's Algorithm for Maximum Bipartite Matching](https://cp-algorithms.com/graph/kuhn_maximum_bipartite_matching.html)
43 | * [二分图最大匹配](https://oi-wiki.org/graph/graph-matching/bigraph-match/)
44 | * [Hungarian Maximum Matching Algorithm](https://brilliant.org/wiki/hungarian-matching/)


--------------------------------------------------------------------------------
/graph/minimum-spanning-tree/README.md:
--------------------------------------------------------------------------------
 1 | # Minimum Spanning Tree
 2 | 
 3 | A minimum-spanning-tree is a tree (without cycles) connecting all the vertices and with the smallest cost.
 4 | 
 5 | ## Comparison of Kruskal's Algorithm and Prim's Algorithm 
 6 | 
 7 | Prim's (`O(ElogV)`) is more performant on dense graph. Kruskal's (`O(ElogE)`) is more performant on sparse graph.
 8 | 
 9 | | Aspect                   | Prim's Algorithm              | Kruskal's Algorithm           |
10 | |--------------------------|-------------------------------|--------------------------------|
11 | | **Algorithm Type**       | Greedy                        | Greedy                         |
12 | | **Edge Selection**       | Chooses the minimum-weight edge connected to the current MST. | Sorts all edges by weight and adds them to the MST if they don't form a cycle. |
13 | | **Data Structures Used** | Priority queue or min-heap (to efficiently select the minimum-weight edge). | Disjoint-set data structure (to check for cycles). |
14 | | **Complexity**           | O(V^2) using an adjacency matrix, O(E + V log V) using a binary heap for dense graphs. | O(E log E) to sort the edges, O(E log V) to process all edges and find MST using disjoint-set. |
15 | | **Suitability**          | More efficient for dense graphs (E is close to V^2). | Suitable for sparse graphs (E is much less than V^2). |
16 | | **Applications**         | Network design, clustering, road planning, maze generation, etc. | Network design, cluster analysis, image segmentation, etc. |
17 | | **Cycle Handling**       | Doesn't directly deal with cycles; relies on the connectedness of the graph. | Detects and avoids cycles explicitly. |
18 | | **Output**               | Yields a single MST rooted at a selected vertex. | Yields a forest of MSTs initially; they combine into a single MST as more edges are added. |
19 | 
20 | ## Problems
21 | 
22 | * [1584. Min Cost to Connect All Points (Medium)](https://leetcode.com/problems/min-cost-to-connect-all-points/) Dense Graph. Prim is better.
23 | * [1489. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree (Hard)](https://leetcode.com/problems/find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree/)


--------------------------------------------------------------------------------
/graph/minimum-spanning-tree/kruskal.md:
--------------------------------------------------------------------------------
  1 | # Kruskal
  2 | 
  3 | Kruskal's Algorithm is a minimum-spanning-tree algorithm which finds a minimal spanning tree for a connected weighted graph. 
  4 | 
  5 | It's a **greedy** algorithm.
  6 | 
  7 | It uses **UnionFind** \(aka Disjoint Set\).
  8 | 
  9 | ## Algorithm
 10 | 
 11 | **Summary: Try to include the edges one by one from smallest cost to greatest cost. Skip those causing cycles. Stop once all nodes are connected.**
 12 | 
 13 | * create a forest F \(a set of trees\), where each vertex in the graph is a separate tree
 14 | * create a set S containing all the edges in the graph
 15 | * while S is nonempty and F is not yet spanning
 16 |   * remove an edge with minimum weight from S
 17 |   * if the removed edge connects two different trees then add it to the forest F, combining two trees into a single tree
 18 | 
 19 | At the termination of the algorithm, the forest forms a minimum spanning forest of the graph. If the graph is connected, the forest has a single component and forms a minimum spanning tree
 20 | 
 21 | ## Implementation
 22 | 
 23 | ```cpp
 24 | // Time: O(ElogE)
 25 | // Space: O(V)
 26 | class UnionFind {
 27 |     vector<int> id;
 28 |     int size;
 29 | public:
 30 |     UnionFind(int N) : id(N), size(N) {
 31 |         iota(begin(id), end(id), 0);
 32 |     }
 33 |     int find(int a) {
 34 |         return id[a] == a ? a : (id[a] = find(id[a]));
 35 |     }
 36 |     void connect(int a, int b) {
 37 |         int p = find(a), q = find(b);
 38 |         if (p == q) return;
 39 |         id[p] = q;
 40 |         --size;
 41 |     }
 42 |     bool connected(int a, int b) {
 43 |         return find(a) == find(b);
 44 |     }
 45 |     int getSize() { return size; }
 46 | };
 47 | 
 48 | int kruskal(int N, vector<vector<int>> edges) {
 49 |     sort(begin(edges), end(edges), [](const vector<int> &a, const vector<int> &b) { return a[2] < b[2]; }); // Sort the edges in ascending order of weight.
 50 |     UnionFind uf(N);
 51 |     int cost = 0;
 52 |     for (auto &e : edges) { // try the edges from smallest weight to greatest weight
 53 |         int u = e[0], v = e[1], w = e[2];
 54 |         if (uf.connected(u, v)) continue; // If this edge will cause cycle, skip it.
 55 |         uf.connect(u, v); // otherwise, pick this edge, connect its vertices.
 56 |         cost += w; // add its weight to the minimum-spanning-tree's cost
 57 |         if (uf.getSize() == 1) break; // Once all nodes are connected, terminate.
 58 |     }
 59 |     return uf.getSize() == 1 ? cost : -1; // If all nodes are connected, return the cost; otherwise, this graph doesn't have minimum-spanning-tree.
 60 | }
 61 | ```
 62 | 
 63 | When the run time limitation is tight and it's a dense graph `E ~= V^2`, using `sort` might cause TLE. We need to use `heap` instead, which will reduce the time complexity from `V^2 * log(V^2)` to `K * log(V^2)` where `K` is the number of edges we need to scan to complete the tree. `K` is usually way smaller than `V^2`.
 64 | 
 65 | The following solution is for [1584. Min Cost to Connect All Points (Medium)](https://leetcode.com/problems/min-cost-to-connect-all-points/).
 66 | 
 67 | ```cpp
 68 | // OJ: https://leetcode.com/problems/min-cost-to-connect-all-points/
 69 | // Author: github.com/lzl124631x
 70 | // Time: O(K * log(N^2)) where K is the number of edged we need to scan to complete the tree
 71 | // Space: O(N^2)
 72 | class UnionFind {
 73 |     vector<int> id;
 74 |     int size;
 75 | public:
 76 |     UnionFind(int N) : id(N), size(N) {
 77 |         iota(begin(id), end(id), 0);
 78 |     }
 79 |     int find(int a) {
 80 |         return id[a] == a ? a : (id[a] = find(id[a]));
 81 |     }
 82 |     void connect(int a, int b) {
 83 |         int p = find(a), q = find(b);
 84 |         if (p == q) return;
 85 |         id[p] = q;
 86 |         --size;
 87 |     }
 88 |     bool connected(int a, int b) {
 89 |         return find(a) == find(b);
 90 |     }
 91 |     int getSize() { return size; }
 92 | };
 93 | class Solution {
 94 | public:
 95 |     int minCostConnectPoints(vector<vector<int>>& A) {
 96 |         int N = A.size(), ans = 0;
 97 |         vector<array<int, 3>> E;
 98 |         for (int i = 0; i < N; ++i) {
 99 |             for (int j = i + 1; j < N; ++j) E.push_back({ abs(A[i][0] - A[j][0]) + abs(A[i][1] - A[j][1]), i, j });
100 |         }
101 |         make_heap(begin(E), end(E), greater<array<int, 3>>());
102 |         UnionFind uf(N);
103 |         while (uf.getSize() > 1) {
104 |             pop_heap(begin(E), end(E), greater<array<int, 3>>());
105 |             auto [w, u, v] = E.back();
106 |             E.pop_back();
107 |             if (uf.connected(u, v)) continue;
108 |             uf.connect(u, v);
109 |             ans += w;
110 |         } 
111 |         return ans;
112 |     }
113 | };
114 | ```
115 | 
116 | ## Problems
117 | 
118 | * [1135. Connecting Cities With Minimum Cost (Medium)](https://leetcode.com/problems/connecting-cities-with-minimum-cost/)
119 | * [1584. Min Cost to Connect All Points (Medium)](https://leetcode.com/problems/min-cost-to-connect-all-points/)
120 | 
121 | ## Reference
122 | 
123 | * [https://en.wikipedia.org/wiki/Kruskal%27s\_algorithm](https://en.wikipedia.org/wiki/Kruskal%27s_algorithm)
124 | * [https://www.luogu.com.cn/problem/P3366](https://www.luogu.com.cn/problem/P3366)
125 | 
126 | 


--------------------------------------------------------------------------------
/graph/minimum-spanning-tree/prim.md:
--------------------------------------------------------------------------------
 1 | # Prim's Algorithm
 2 | 
 3 | Prim's algorithm is a **greedy** algorithm that finds a minimum spanning tree for a **weighted undirected** graph.
 4 | 
 5 | ## Algorithm
 6 | 
 7 | **Summary: Starting from a random node, pick its minimum outbound edge that doesn't form cicle, and add the node to the tree**
 8 | 
 9 | * Initialize the tree with a random single node.
10 | * Grow the tree by one edge: from the edges that connect the tree to nodes not yet in the tree, find the minimum-weight edge, and add it to the tree.
11 | * Repeat until all nodes are in the tree.
12 | 
13 | ## Implementation
14 | 
15 | Basic implementation without `heap`.
16 | 
17 | ```cpp
18 | // Time: O(V^2)
19 | // Space: O(V)
20 | int prim(int N, int M, vector<vector<int>> &edges) { // N nodes, M edges. edges is an array of `<u, v, w>` where u, v are from and to nodes, w is the weight.
21 |     vector<vector<pair<int, int>>> G(N);
22 |     for (auto &e : edges) {
23 |         int u = e[0] - 1, v = e[1] - 1, w = e[2];
24 |         G[u].emplace_back(v, w);
25 |         G[v].emplace_back(u, w);
26 |     }
27 |     int ans = 0, cur = 0; // start from a random node, say 0.
28 |     vector<int> dist(N, INT_MAX), seen(N);
29 |     for (int i = 0; i < N - 1; ++i) {
30 |         seen[cur] = 1; // add this node to the MST
31 |         for (auto &[v, w] : G[cur]) {
32 |             if (seen[v]) continue; // skip those neighbors that are already in the MST
33 |             dist[v] = min(dist[v], w); // Use the current node to update the distance of unvisited nodes.
34 |         }
35 |         cur = min_element(begin(dist), end(dist)) - begin(dist); // greedily pick an unconnected node with the minimum distance
36 |         ans += dist[cur];
37 |         dist[cur] = INT_MAX; // mark this distance as used
38 |     }
39 |     return ans;
40 | }
41 | ```
42 | 
43 | TODO: heap version prim
44 | 
45 | ## Reference
46 | 
47 | * https://en.wikipedia.org/wiki/Prim%27s_algorithm


--------------------------------------------------------------------------------
/graph/shortest-path/README.md:
--------------------------------------------------------------------------------
1 | # Shortest Path
2 | 
3 | Algorithm | Time Complexity | Usecase | Memo
4 | ---|---|---|---
5 | Bellman-Ford | O(VE) | Single Source to All | Use all the edges to relax `V-1` times
6 | Dijkstra | O(ElogE) with heap.<br/>O(E + VlogV) with Fabonacci Heap | Single Source to All | Heap with closest nodes
7 | Floyd-Warshall | O(V^3) | All to All | Use each node as a intermediate node to update `N^2` pairs of nodes


--------------------------------------------------------------------------------
/graph/shortest-path/bellman-ford.md:
--------------------------------------------------------------------------------
 1 | # Bellman Ford
 2 | 
 3 | * Computes shortest paths from **a single source vertex** to all of the other vertices in a weighted directed graph.
 4 | * Slower than Dijkstra's algorithm. Its time complexity is `O(VE)`.
 5 | * Can handle graph with negative weight edges.
 6 | * Works better \(than Dijkstra's\) for distributed system. Unlike Dijkstra's where we need to find minimum value of all vertices, Bellman-Force considers edges one by one.
 7 | 
 8 | ## Implementation
 9 | 
10 | Let `dist[u]` be the length of the shortest path from `src` to `u`.
11 | 
12 | Initially `dist[src] = 0` and `dist[u] = INF` for all other vertices.
13 | 
14 | Repeat `V - 1` times \(since the path in the graph is at most of length `V - 1`\):
15 | 
16 | * For each edge `E = (u, v, weight)`, try to use `E` to update the `dist[v]`: If `dist[u] + weight < dist[v]`, then `dist[v] = dist[u] + weight`.
17 | 
18 | ```cpp
19 | // Time: O(VE)
20 | // Space: O(V)
21 | vector<int> bellmanFord(vector<vector<int>>& edges, int V, int src) {
22 |     vector<int> dist(N, INT_MAX);
23 |     dist[src] = 0;
24 |     for (int i = 1; i < V; ++i) { // try to use all the edges to relax V-1 times.
25 |         for (auto &e : edges) {
26 |             int u = e[0], v = e[1], w = e[2];
27 |             if (dist[u] == INT_MAX) continue;
28 |             dist[v] = min(dist[v], dist[u] + w); // Try to use this edge to relax the cost of `v`.
29 |         }
30 |     }
31 |     return dist;
32 | }
33 | ```
34 | 
35 | ## Problems
36 | 
37 | * [743. Network Delay Time](https://leetcode.com/problems/network-delay-time/)
38 | * [787. Cheapest Flights Within K Stops \(Medium\)](https://leetcode.com/problems/cheapest-flights-within-k-stops)
39 | 
40 | ## Reference
41 | 
42 | * [Bellman–Ford algorithm](https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm)
43 | 
44 | 


--------------------------------------------------------------------------------
/graph/shortest-path/dijkstra.md:
--------------------------------------------------------------------------------
  1 | # Dijkstra
  2 | 
  3 | Dijkstra's original algorithm found the shortest path between two given nodes, but a more common variant fixes a single node as the "source" node and finds shortest paths from the source to all other nodes in the graph, producing a **shortest-path tree**.
  4 | 
  5 | It's a **greedy** BFS algorithm.
  6 | 
  7 | It does **NOT** support negative edge.
  8 | 
  9 | Note that we should only use this algorithm on a **weighted** graph. If it's an unweighted graph, just use BFS.
 10 | 
 11 | ## Algorithm
 12 | 
 13 | **Summary: Use heap to store the cost of nodes. Each time pop the heap top node, whose shortest path is determimed once popped, and use its outbound edges to relax its neighbors and push the relaxed neighbors into the heap.**
 14 | 
 15 | Given `V` vertices and `E` edges. The all weights of all edges are non-negative. Find the smallest distance from a source node `S` to all other nodes.
 16 | 
 17 | We split the `V` vertices into two sets:
 18 | 
 19 | - `A`, visited nodes, i.e. those whose shortest path is already determined.
 20 | - `B`, unvisited nodes.
 21 | 
 22 | Initially:
 23 | 
 24 | - `A` is empty and `B` contains all the vertices
 25 | - The distance of the source vertex is `0`, and `Infinity` for all other vertices.
 26 | 
 27 | Then we keep the following operations until all vertices are visited:
 28 | 
 29 | 1. Find the vertice with the smallest distance from `B`, say `u`. Move `u` from `B` to `A`.
 30 | 2. For each outbound edge from `u` `(u, v, w)` (`v` is the destination verte, `w` is the weight), try to relax `v` using `u` and `w` -- If `dist[v] > dist[u] + w`, then `dist[v] = dist[u] + w`.
 31 | 
 32 | ## Why no negative edge?
 33 | 
 34 | Dijkstra is a greedy algorithm. If all the edges are non-negative, once we find the node with the smallest cost from unvisited vertice set, say `u`, we are sure that it won't be updated later -- it's already the optimal path.
 35 | 
 36 | But if there are negative edges, this `u` can be updated again later using negative edge.
 37 | 
 38 | ## Implementation
 39 | 
 40 | Here I only talk about the solution using `priority_queue`.
 41 | 
 42 | Let `pq` be a `priority_queue` of pairs of the cost \(i.e. the length of the shortest path from `src`\) and the vertex index. The element with the smallest cost is at the top of the queue \(i.e. min-heap\). Initially `pq` only has `(0, src)` in it.
 43 | 
 44 | Let `dist[u]` be the cost of `u`. Initially `dist[src] = 0` and `dist[u] = INF` for all other vertices.
 45 | 
 46 | ```cpp
 47 | // Time: O(ElogE)
 48 | // Space: O(E)
 49 | typedef unordered_map<int, unordered_map<int, int>> Graph; // map from source node to <destination node, edge cost>
 50 | typedef pair<int, int> iPair;
 51 | vector<int> dijkstra(Graph &graph, int N, int source) {
 52 |     priority_queue<iPair, vector<iPair>, greater<iPair>> pq; // cost, nodeIndex. Min-heap -- the unvisited ndoe with the smallest distance is at the top
 53 |     vector<int> dists(N, INT_MAX), seen(N);
 54 |     dists[source] = 0;
 55 |     pq.emplace(0, source); // push the source node into heap
 56 |     while (pq.size()) {
 57 |         int u = pq.top().second; // greedily visit the unvisited node with smallest cost, and relax its neighbors
 58 |         pq.pop();
 59 |         if (seen[u]) continue; // `u` has been visited, skip
 60 |         seen[u] = 1; // mark `u` as visited
 61 |         for (auto &neighbor : graph[u]) { // try to use node `u` to relax its neighbors
 62 |             int v = neighbor.first, weight = neighbor.second;
 63 |             if (!seen[u] && dists[v] > dists[u] + weight) { // If `v` is not visited and can be relaxed
 64 |                 dists[v] = dists[u] + weight; // update the cost
 65 |                 pq.emplace(dists[v], v); // push the updated pair of <cost, index> into the heap
 66 |             }
 67 |         }
 68 |     }
 69 |     return dists;
 70 | }
 71 | ```
 72 | 
 73 | When the same node has been relaxed multiple times, we should delete the old relaxations from the priority queue. But with `priority_queue`, we don't have a way to do it. So we just push the entry of the same node and smaller cost into the priority queue.
 74 | 
 75 | When a node is popped from the queue and it's already visited, then we should skip it.
 76 | 
 77 | Time complexity analysis: In the worst case, each visited node will push new items into the priority queue using all its outbound edges. So there will be `O(E)` items in the priority queue in total. The overall time complexity is `Elog(E)`.
 78 | 
 79 | If we can use Fabonacci Heap, the time complexity will be reduced to `O(E + VlogV)`.
 80 | 
 81 | Another way to prevent visiting the same node twice is as follows:
 82 | 
 83 | ```cpp
 84 | // Time: O(ElogE)
 85 | // Space: O(E)
 86 | typedef unordered_map<int, unordered_map<int, int>> Graph;
 87 | typedef pair<int, int> PII;
 88 | vector<int> dijkstra(Graph &graph, int N, int source) {
 89 |     priority_queue<PII, vector<PII>, greater<PII>> pq;
 90 |     vector<int> dists(N, INT_MAX);
 91 |     dists[source] = 0;
 92 |     pq.emplace(0, source);
 93 |     while (pq.size()) {
 94 |         const [cost, u] = pq.top();
 95 |         pq.pop();
 96 |         if (cost > dists[u]) continue; // this is already not the optimal, skip
 97 |         for (auto &[v, w] : graph[u]) {
 98 |             if (dists[v] > dists[u] + w) {
 99 |                 dists[v] = dists[u] + w;
100 |                 pq.emplace(dists[v], v);
101 |             }
102 |         }
103 |     }
104 |     return dists;
105 | }
106 | ```
107 | 
108 | ## Problems
109 | 
110 | - [743. Network Delay Time](https://leetcode.com/problems/network-delay-time/)
111 | - [787. Cheapest Flights Within K Stops](https://leetcode.com/problems/cheapest-flights-within-k-stops/)
112 | - [1514. Path with Maximum Probability (Medium)](https://leetcode.com/problems/path-with-maximum-probability/)
113 | - [1368. Minimum Cost to Make at Least One Valid Path in a Grid (Hard)](https://leetcode.com/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid/)
114 | 
115 | ## Reference
116 | 
117 | - [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)
118 | 


--------------------------------------------------------------------------------
/graph/shortest-path/floyd-warshall.md:
--------------------------------------------------------------------------------
 1 | # Floyd Warshall
 2 | 
 3 | Floyd-Warshall algorithm is an algorithm for finding the shorted paths **between all pairs of vertices** in a weighted directed graph with positive or negative edge weights \(but no negative cycles\).
 4 | 
 5 | Floyd-Warshall algorithm and Bellman-Ford algorithm are both DP algorithms. Floyd-Warshall tries every **vertice** for each pair of vertices to find the shortest path between the vertice pair, while Bellman-Ford tries every **edge** `V-1` times to find the shortest path between a specific source node to all other nodes.
 6 | 
 7 | ## Algorithm
 8 | 
 9 | For each vertice `n`, try to use it to update the min distance between each vertice pair `u, v`.
10 | 
11 | The time complexity is `O(V^3)`. The space complexity is `O(V^2)`.
12 | 
13 | The following is the Floyd-Warshall algorithm application on [1334. Find the City With the Smallest Number of Neighbors at a Threshold Distance \(Medium\)](https://leetcode.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/).
14 | 
15 | The distances are initialized as `1e6` because there are at most 100 nodes and each edge at most weights `10^4`, so the maximum path weight won't exceed `10^6`.
16 | 
17 | ```cpp
18 | // OJ: https://leetcode.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/
19 | // Author: github.com/lzl124631x
20 | // Time: O(N^3)
21 | // Space: O(N^2)
22 | class Solution {
23 |     vector<vector<int>> floyd(int n, vector<vector<int>> &edges) {
24 |         vector<vector<int>> d(n, vector<int>(n, (int) 1e6));
25 |         for (int i = 0; i < n; ++i) d[i][i] = 0;
26 |         for (auto &e : edges) {
27 |             d[e[0]][e[1]] = d[e[1]][e[0]] = e[2];
28 |         }
29 |         for (int i = 0; i < n; ++i) 
30 |             for (int u = 0; u < n; ++u) 
31 |                 for (int v = 0; v < n; ++v) 
32 |                     d[u][v] = min(d[u][v], d[u][i] + d[i][v]);
33 |         return d;
34 |     }
35 | public:
36 |     int findTheCity(int n, vector<vector<int>>& E, int k) {
37 |         auto d = floyd(n, E);
38 |         int ans = 0, minCnt = n;
39 |         for (int i = 0; i < n; ++i) {
40 |             int cnt = 0;
41 |             for (int j = 0; j < n; ++j) {
42 |                 if (d[i][j] <= k) ++cnt;
43 |             }
44 |             if (cnt <= minCnt) {
45 |                 minCnt = cnt;
46 |                 ans = i;
47 |             }
48 |         }
49 |         return ans;
50 |     }
51 | };
52 | ```
53 | 
54 | ## Path reconstruction
55 | 
56 | The Floyd-Warshall algorithm typically only provides the lengths of the paths between all pairs of vertices. We can nodify it to reconstruct the path for between any two endpoint vertices.
57 | 
58 | ```text
59 | let dist be a |V| * |V| array of minimum distances initialized to Infinity
60 | let next be a |V| * |V| array of vertex indices initialized to null
61 | 
62 | procedure FloydWarshallWithPathReconstruction() is
63 |     for each edge (u, v) do
64 |         dist[u][v] ← w(u, v)  // The weight of the edge (u, v)
65 |         next[u][v] ← v
66 |     for each vertex v do
67 |         dist[v][v] ← 0
68 |         next[v][v] ← v
69 |     for k from 1 to |V| do // standard Floyd-Warshall implementation
70 |         for i from 1 to |V|
71 |             for j from 1 to |V|
72 |                 if dist[i][j] > dist[i][k] + dist[k][j] then
73 |                     dist[i][j] ← dist[i][k] + dist[k][j]
74 |                     next[i][j] ← next[i][k]
75 | procedure Path(u, v)
76 |     if next[u][v] = null then
77 |         return []
78 |     path = [u]
79 |     while u ≠ v
80 |         u ← next[u][v]
81 |         path.append(u)
82 |     return path
83 | ```
84 | 
85 | ## Problems
86 | 
87 | * [1462. Course Schedule IV \(Medium\)](https://leetcode.com/problems/course-schedule-iv/)
88 | * [1334. Find the City With the Smallest Number of Neighbors at a Threshold Distance \(Medium\)](https://leetcode.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/)
89 | 
90 | ## Reference
91 | 
92 | * [https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall\_algorithm](https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm)
93 | 
94 | 


--------------------------------------------------------------------------------
/graph/shortest-path/johnson.md:
--------------------------------------------------------------------------------
1 | # Johnson
2 | 
3 | ## Reference
4 | 
5 | * [https://en.wikipedia.org/wiki/Johnson%27s\_algorithm](https://en.wikipedia.org/wiki/Johnson's\_algorithm)
6 | * [https://oi-wiki.org/graph/shortest-path/](https://oi-wiki.org/graph/shortest-path/)
7 | 


--------------------------------------------------------------------------------
/graph/shortest-path/shortest-path-faster-algorithm.md:
--------------------------------------------------------------------------------
1 | # Shortest Path Faster Algorithm
2 | 
3 | Given a **directed weighted graph** with **V** vertices, **E** edges and a source vertex **S**. The task is to find the shortest path from the source vertex to all other vertices in the given graph.
4 | 
5 | ## Reference
6 | 
7 | * [https://www.geeksforgeeks.org/shortest-path-faster-algorithm/](https://www.geeksforgeeks.org/shortest-path-faster-algorithm/)
8 | 


--------------------------------------------------------------------------------
/graph/tarjan.md:
--------------------------------------------------------------------------------
 1 | # Tarjan
 2 | 
 3 | Tarjan's strongly connected components algorithm is an algorithm in graph theory for finding the **strongly connected components (SCCs)** of a directed graph. It runs in linear time, matching the time bound for alternative methods including Kosaraju's algorithm and the path-based strong component algorithm. The algorithm is named for its inventor, Robert Tarjan.
 4 | 
 5 | ![](../.gitbook/assets/scc.png)
 6 | 
 7 | ![](../.gitbook/assets/low-link-value.png)
 8 | 
 9 | ## References
10 | 
11 | * [https://en.wikipedia.org/wiki/Tarjan%27s\_strongly\_connected\_components\_algorithm](https://en.wikipedia.org/wiki/Tarjan's\_strongly\_connected\_components\_algorithm)
12 | *   \[Tarjans Strongly Connected Components algorithm | Graph Theory
13 | 
14 |     ]\([https://youtu.be/TyWtx7q2D7Y](https://youtu.be/TyWtx7q2D7Y))
15 | 
16 | ## Problems
17 | 
18 | * [1192. Critical Connections in a Network (Hard)](https://leetcode.com/problems/critical-connections-in-a-network/)
19 | 


--------------------------------------------------------------------------------
/graph/topological-sort.md:
--------------------------------------------------------------------------------
  1 | # Topological Sort
  2 | 
  3 | Topological sorting for Directed Acyclic Graph \(DAG\) is a linear ordering of vertices such that for every directed edge `uv`, vertex `u` comes before `v` in the ordering.
  4 | 
  5 | ## Implementation
  6 | 
  7 | We represent the graph `G` as `unordered_map<int, vector<int>>` which is a map from source node to a list of destination nodes.
  8 | 
  9 | If `u` must happens before `v`, or in other words, `v` is dependent on `u`, then there is a directed edge `u -> v`, where `u` is the source node, and `v` is the destination node.
 10 | 
 11 | ### Kahn Algorithm \(BFS\)
 12 | 
 13 | It requires additional space for storing the `indegree`s of the nodes.
 14 | 
 15 | 1. Put all the vertices with 0 in-degree in to a `queue q`.
 16 | 2. Get a vertex `u` at a time from `q`, and decrement the in-degree of all its neighbors.
 17 | 3. If a neighbor has 0 in-degree, add it to `q`.
 18 | 4. Keep repeating until we exhaust `q`.
 19 | 5. If the number of visited vertices equals the total number of vertices, it's a DAG; otherwise, there must be a circle in the graph.
 20 | 
 21 | ```cpp
 22 | // OJ: https://leetcode.com/problems/course-schedule-ii/
 23 | // Author: github.com/lzl124631x
 24 | // Time: O(V + E)
 25 | // Space: O(V + E)
 26 | class Solution {
 27 | public:
 28 |     vector<int> findOrder(int N, vector<vector<int>>& E) {
 29 |         unordered_map<int, vector<int>> G;
 30 |         vector<int> indegree(N);
 31 |         for (auto &e : E) {
 32 |             G[e[1]].push_back(e[0]);
 33 |             indegree[e[0]]++;
 34 |         }
 35 |         queue<int> q;
 36 |         for (int i = 0; i < N; ++i) {
 37 |             if (indegree[i] == 0) q.push(i);
 38 |         }
 39 |         vector<int> ans;
 40 |         while (q.size()) {
 41 |             int u = q.front();
 42 |             q.pop();
 43 |             ans.push_back(u);
 44 |             for (int v : G[u]) {
 45 |                 if (--indegree[v] == 0) q.push(v);
 46 |             }
 47 |         }
 48 |         return ans.size() == N ? ans : vector<int>{};
 49 |     }
 50 | };
 51 | ```
 52 | 
 53 | ### DFS (Post-order Traversal)
 54 | 
 55 | A DFS version topological sort must be a **Post-order DFS + Memoization**.
 56 | 
 57 | Each vertex has three states:
 58 | 
 59 | 1. -1 =  unvisited
 60 | 2. 0 = being visited in the current DFS session. If we visit a node with state 0, it means there is a circle in the graph.
 61 | 3. 1 = has been visited in a prevous DFS session and this vertex is not in a circle.
 62 | 
 63 | It's a post-order DFS -- the node is pushed into the answer after all its subsequent nodes are visited.
 64 | 
 65 | Don't forget to reverse the `ans` before returning.
 66 | 
 67 | ```cpp
 68 | // OJ: https://leetcode.com/problems/course-schedule-ii/
 69 | // Author: github.com/lzl124631x
 70 | // Time: O(V + E)
 71 | // Space: O(V + E)
 72 | class Solution {
 73 |     vector<vector<int>> G;
 74 |     vector<int> ans, state; // -1 unvisited, 0 visiting, 1 visited
 75 |     bool dfs(int u) {
 76 |         if (state[u] != -1) return state[u];
 77 |         state[u] = 0;
 78 |         for (int v : G[u]) {
 79 |             if (!dfs(v)) return false;
 80 |         }
 81 |         ans.push_back(u);
 82 |         return state[u] = 1;
 83 |     }
 84 | public:
 85 |     vector<int> findOrder(int n, vector<vector<int>>& E) {
 86 |         G.assign(n, {});
 87 |         state.assign(n, -1);
 88 |         for (auto &e : E) G[e[1]].push_back(e[0]);
 89 |         for (int i = 0; i < n; ++i) {
 90 |             if (!dfs(i)) return {};
 91 |         }
 92 |         reverse(begin(ans), end(ans));
 93 |         return ans;
 94 |     }
 95 | };
 96 | ```
 97 | 
 98 | ## Problems
 99 | 
100 | * [207. Course Schedule \(Medium\)](https://leetcode.com/problems/course-schedule/)
101 | * [210. Course Schedule II \(Medium\)](https://leetcode.com/problems/course-schedule-ii/)
102 | * [329. Longest Increasing Path in a Matrix \(Hard\)](https://leetcode.com/problems/longest-increasing-path-in-a-matrix/)
103 | * [Stable Wall](https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ff43/00000000003379bb)
104 | * [Fox And Names](https://codeforces.com/contest/510/problem/C)
105 | * [802. Find Eventual Safe States (Medium)](https://leetcode.com/problems/find-eventual-safe-states/)
106 | * [1857. Largest Color Value in a Directed Graph (Hard)](https://leetcode.com/problems/largest-color-value-in-a-directed-graph/)
107 | * [1462. Course Schedule IV (Medium)](https://leetcode.com/problems/course-schedule-iv/)
108 | * [2050. Parallel Courses III (Hard)](https://leetcode.com/problems/parallel-courses-iii/)


--------------------------------------------------------------------------------
/graph/tree-diameter.md:
--------------------------------------------------------------------------------
 1 | # Tree Diameter
 2 | 
 3 | ## DFS Twice
 4 | 
 5 | * Pick a random node `i`.
 6 | * DFS to find the furthest node `j` to node `i`.
 7 | * DFS to find the furthest node `k` to node `j`.
 8 | 
 9 | The distance between `j` and `k` is the tree's diameter.
10 | 
11 | See [proof](https://oi-wiki.org/graph/tree-diameter/)
12 | 
13 | ## Problems
14 | 
15 | * [1617. Count Subtrees With Max Distance Between Cities (Hard)](https://leetcode.com/problems/count-subtrees-with-max-distance-between-cities/)


--------------------------------------------------------------------------------
/graph/tree-ring-order-traversal.md:
--------------------------------------------------------------------------------
 1 | # Tree's Ring order traversal
 2 | 
 3 | If a connected graph doesn't have cycle, it's a tree.
 4 | 
 5 | Here by ring-order traversal, I mean visiting the leaf nodes first (i.e. 1st ring nodes), then the non-leaf nodes next to 1st ring nodes (i.e. 2nd ring nodes), and so on.
 6 | 
 7 | ## Algorithm
 8 | 
 9 | We keep track of indegrees of nodes. Remove those with indegrees 1 from the graph and update the indegrees of the remaining nodes. We keep doing this until exhausting all the nodes.
10 | 
11 | ## Implementation
12 | 
13 | The following solution is for [310. Minimum Height Trees (Medium)](https://leetcode.com/problems/minimum-height-trees/) which is asking for the nodes 
14 | 
15 | ```cpp
16 | // OJ: https://leetcode.com/problems/minimum-height-trees
17 | // Author: github.com/lzl124631x
18 | // Time: O(V + E)
19 | // Space: O(V + E)
20 | class Solution {
21 | public:
22 |     vector<int> findMinHeightTrees(int n, vector<vector<int>>& E) {
23 |         if (n == 1) return { 0 };
24 |         vector<int> indegree(n), ans;
25 |         vector<vector<int>> G(n);
26 |         for (auto &e : E) {
27 |             int u = e[0], v = e[1];
28 |             indegree[u]++;
29 |             indegree[v]++;
30 |             G[u].push_back(v);
31 |             G[v].push_back(u);
32 |         }
33 |         queue<int> q;
34 |         for (int i = 0; i < n; ++i) {
35 |             if (indegree[i] == 1) q.push(i);
36 |         }
37 |         while (n > 2) {
38 |             int cnt = q.size();
39 |             while (cnt--) {
40 |                 int u = q.front();
41 |                 q.pop();
42 |                 --n;
43 |                 for (int v : G[u]) {
44 |                     if (--indegree[v] == 1) q.push(v);
45 |                 }
46 |             }
47 |         }
48 |         while (q.size()) {
49 |             ans.push_back(q.front());
50 |             q.pop();
51 |         }
52 |         return ans;
53 |     }
54 | };
55 | ```
56 | 
57 | ## Problems
58 | 
59 | *  [310. Minimum Height Trees (Medium)](https://leetcode.com/problems/minimum-height-trees/)


--------------------------------------------------------------------------------
/gray-code.md:
--------------------------------------------------------------------------------
 1 | # Gray Code
 2 | 
 3 | Gray code is a binary numeral system where two successive values differ in only one bit.
 4 | 
 5 | For example, the sequence of Gray codes for 3-bit numbers is: `000, 001, 011, 010, 110, 111, 101, 100`, so `G(4)=6`.
 6 | 
 7 | This code was invented by Frank Gray in 1953.
 8 | 
 9 | ## Finding Gray Code
10 | 
11 | Let's look at the bits of number `n` and the bits of number `G(n)`. Notice that `i`-th bit of `G(n)` equals 1 only when `i`-th bit of `n` equals 1 and `i+1`-th bit equals 0 or the other way around (`i`-th bit equals 0 and `i+1`-th bit equals 1). Thus, `G(n) = n XOR (n>>1)`.
12 | 
13 | For example
14 | 
15 | ```
16 |       G(4) = 6
17 |     G(100) = 110
18 |          n = 0100
19 |       n>>1 = 0010
20 | n ^ (n>>1) = 0110
21 | ```
22 | 
23 | ```cpp
24 | int g (int n) {
25 |     return n ^ (n >> 1);
26 | }
27 | ```
28 | 
29 | ## Finding reverse Gray Code
30 | 
31 | Given Gray code `g`, restore the original number `n`.
32 | 
33 | We will move from the most significant bits to the least significant ones (the least significant bit has index 1 and the most significant bit has index k). The relation between the bits `n[i]` of number `n` and the bits `g[i]` of number `g`:
34 | 
35 | ```
36 | n[k] = g[k]
37 | n[k−1] = g[k−1] XOR n[k] = g[k] XOR g[k-1]
38 | n[k-2] = g[k-2] XOR n[k-1] = g[k] XOR g[k-1] XOR g[k-2]
39 | ...
40 | ```
41 | 
42 | The easiest way to write it in code is:
43 | 
44 | ```cpp
45 | int rev_g (int g) {
46 |     int n = 0;
47 |     for (; g; g >>= 1) n ^= g;
48 |     return n;
49 | }
50 | ```
51 | 
52 | ## Problems
53 | 
54 | * [1238. Circular Permutation in Binary Representation (Medium)](https://leetcode.com/problems/circular-permutation-in-binary-representation/)
55 | 
56 | ## References
57 | 
58 | * [https://cp-algorithms.com/algebra/gray-code.html](https://cp-algorithms.com/algebra/gray-code.html)
59 | 


--------------------------------------------------------------------------------
/great-problems-for-practice.md:
--------------------------------------------------------------------------------
 1 | # Great Problems For Practice
 2 | 
 3 | [215. Kth Largest Element in an Array (Medium)](https://leetcode.com/problems/kth-largest-element-in-an-array/): Quick Select; Manually Implement Heap; API usage of `nth_element`, `make_heap`, `push_heap`, `pop_heap`
 4 | 
 5 | [1235. Maximum Profit in Job Scheduling (Hard)](https://leetcode.com/problems/maximum-profit-in-job-scheduling/): DP + Binary search because of sparse value (compared to continuous indexes)
 6 | 
 7 | [1830. Minimum Number of Operations to Make String Sorted (Hard)](https://leetcode.com/problems/minimum-number-of-operations-to-make-string-sorted/): permutation rank with duplicates
 8 | 
 9 | [472. Concatenated Words (Hard)](https://leetcode.com/problems/concatenated-words/): Trie + DP
10 | 
11 | ## DP on Subsets OR Backtrack to Fill Buckets
12 | 
13 | * [698. Partition to K Equal Sum Subsets (Medium)](https://leetcode.com/problems/partition-to-k-equal-sum-subsets/)
14 | * [473. Matchsticks to Square (Medium)](https://leetcode.com/problems/matchsticks-to-square/)
15 | * [1723. Find Minimum Time to Finish All Jobs (Hard)](https://leetcode.com/problems/find-minimum-time-to-finish-all-jobs/)
16 | 
17 | ## Geometry
18 | 
19 | * [478. Generate Random Point in a Circle (Medium)](https://leetcode.com/problems/generate-random-point-in-a-circle/)
20 | 
21 | ## Trie + XOR
22 | 
23 | * [421. Maximum XOR of Two Numbers in an Array (Medium)](https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/)
24 | * [1707. Maximum XOR With an Element From Array (Hard)](https://leetcode.com/problems/maximum-xor-with-an-element-from-array/)
25 | * [1803. Count Pairs With XOR in a Range (Hard)](https://leetcode.com/problems/count-pairs-with-xor-in-a-range/)
26 | 
27 | ## BIT (Binary Index Tree) or Segment Tree
28 | 
29 | * [307. Range Sum Query - Mutable (Medium)](https://leetcode.com/problems/range-sum-query-mutable/)
30 | 
31 | ## Backtracking
32 | 
33 | * [51. N-Queens (Hard)](https://leetcode.com/problems/n-queens/)
34 | * [698. Partition to K Equal Sum Subsets (Medium)](https://leetcode.com/problems/partition-to-k-equal-sum-subsets/)
35 | * [473. Matchsticks to Square (Medium)](https://leetcode.com/problems/matchsticks-to-square/)
36 | 
37 | ## Stack operation on string
38 | 
39 | * [1003. Check If Word Is Valid After Substitutions (Medium)](https://leetcode.com/problems/check-if-word-is-valid-after-substitutions/)
40 | * [1209. Remove All Adjacent Duplicates in String II (Medium)](https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string-ii/)
41 | 
42 | ## Permutation
43 | 
44 | * [60. Permutation Sequence (Hard)](https://leetcode.com/problems/permutation-sequence/)
45 | * [31. Next Permutation (Medium)](https://leetcode.com/problems/next-permutation/)
46 | 
47 | ## Mono Stack / Mono Deque
48 | 
49 | * [907. Sum of Subarray Minimums (Medium)](https://leetcode.com/problems/sum-of-subarray-minimums/)
50 | 
51 | ## Sorting
52 | 
53 | * [912. Sort an Array (Medium)](https://leetcode.com/problems/sort-an-array/)
54 | 
55 | ## Binary Indexed Tree
56 | 
57 | * [307. Range Sum Query - Mutable (Medium)](https://leetcode.com/problems/range-sum-query-mutable)
58 | 


--------------------------------------------------------------------------------
/greedy/README.md:
--------------------------------------------------------------------------------
1 | # Greedy
2 | 
3 | 


--------------------------------------------------------------------------------
/greedy/greedy-scheduling.md:
--------------------------------------------------------------------------------
 1 | # Greedy Scheduling
 2 | 
 3 | ```cpp
 4 | // Sort by start time
 5 | priority_queue<int> pq; // Customized priority
 6 | int time = 0;
 7 | for (int i = 0; i < N && pq.size(); ) {
 8 |     if (pq.empty()) time = max(time, A[i][0]); // if no available task, take the starting time of the next task
 9 |     while (i < N && A[i][0] <= time) pq.push(A[i++][1]); // keep taking in tasks start before/at the current time.
10 |     // access the pq.top()
11 |     pq.pop();
12 |     // update time
13 |     while (pq.size() && pq.top() < time) pq.pop(); // evict the tasks that ends before the current time
14 | }
15 | ```
16 | 
17 | * [1834. Single-Threaded CPU (Medium)](https://leetcode.com/problems/single-threaded-cpu/)
18 | * [1353. Maximum Number of Events That Can Be Attended (Medium)](https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended/)


--------------------------------------------------------------------------------
/greedy/regret-greedy.md:
--------------------------------------------------------------------------------
1 | # Regret Greedy (反悔贪心)
2 | 
3 | ## Problems
4 | 
5 | * [300. Longest Increasing Subsequence (Medium)](https://leetcode.com/problems/longest-increasing-subsequence/)
6 | * [630. Course Schedule III (Hard)](https://leetcode.com/problems/course-schedule-iii/)


--------------------------------------------------------------------------------
/interval-scheduling-maximization.md:
--------------------------------------------------------------------------------
 1 | # Interval Scheduling Maximization (ISM)
 2 | 
 3 | The interval scheduling maximization (ISM) problem is to find a largest compatible set - a set of non-overlapping intervals of maximum size. The goal here is to execute as many tasks as possible.
 4 | 
 5 | ## Algorithm
 6 | 
 7 | Greedily select the interval with the **earliest ending time**.
 8 | 
 9 | 1. Sort the intervals in ascending order of the **end time**. (We don't care the start time)
10 | 2. Scan through the intervals and greedily collect non-overlapping intervals.
11 | 
12 | Memorize point 1: For all the intervals whose start times are not overlapping with earlier intervals, picking the one ending first must be optimal.
13 | 
14 | ## Implementation
15 | 
16 | ```cpp
17 | // OJ: https://leetcode.com/problems/non-overlapping-intervals/
18 | // Author: github.com/lzl124631x
19 | // Time: O(NlogN)
20 | // Space: O(1)
21 | class Solution {
22 | public:
23 |     int eraseOverlapIntervals(vector<vector<int>>& A) {
24 |         sort(begin(A), end(A), [](vector<int> &a, vector<int> &b) { return a[1] < b[1]; });
25 |         int end = INT_MIN, ans = 0; // `end` is the maximum ending time of selected intervals
26 |         for (auto &x : A) {
27 |             if (x[0] >= end) end = x[1]; // this interval doesn't have overlap with the previously selected interval, select it and update the `end`.
28 |             else ++ans; // otherwise, overlapped intervals are skipped.
29 |         }
30 |         return ans;
31 |     }
32 | };
33 | ```
34 | 
35 | ## Problem
36 | 
37 | * [435. Non-overlapping Intervals (Medium)](https://leetcode.com/problems/non-overlapping-intervals/)
38 | * [452. Minimum Number of Arrows to Burst Balloons (Medium)](https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/)
39 | * [646. Maximum Length of Pair Chain (Medium)](https://leetcode.com/problems/maximum-length-of-pair-chain/) **Direct Application**
40 | * [1520. Maximum Number of Non-Overlapping Substrings (Medium)](https://leetcode.com/problems/maximum-number-of-non-overlapping-substrings/)
41 | 
42 | ## Reference
43 | 
44 | * https://en.wikipedia.org/wiki/Interval_scheduling
45 | 


--------------------------------------------------------------------------------
/io-optimization.md:
--------------------------------------------------------------------------------
 1 | # IO Optimization
 2 | 
 3 | By prepending the following code, the execution time of problems with large input will be improved a lot.
 4 | 
 5 | ```cpp
 6 | // The following block might trivially improve the exec time.
 7 | static const auto __optimize__ = []() {
 8 |     std::ios::sync_with_stdio(false);
 9 |     std::cin.tie(NULL);
10 |     return 0;
11 | }();
12 | ```


--------------------------------------------------------------------------------
/k-subset-partitioning.md:
--------------------------------------------------------------------------------
 1 | # K Subset Partitioning
 2 | 
 3 | K Subset partitioning: partition the original array into `K` subsets and find the optimial result.
 4 | 
 5 | Candidate Solutions:
 6 | 
 7 | 1. DFS + Optimizations
 8 | 2. DP on Subsets
 9 | 
10 | 
11 | ## Problems
12 | 
13 | * [698. Partition to K Equal Sum Subsets (Medium)](https://leetcode.com/problems/partition-to-k-equal-sum-subsets/)
14 | * [473. Matchsticks to Square (Medium)](https://leetcode.com/problems/matchsticks-to-square/)
15 | * [1723. Find Minimum Time to Finish All Jobs (Hard)](https://leetcode.com/problems/find-minimum-time-to-finish-all-jobs/)
16 | 
17 | ### DFS + Optimizations
18 | 
19 | **Algorithm**
20 | 
21 | Create a `vector` of length `K` to store the subset values.
22 | 
23 | DFS to visit elements in the input array `A` one by one. In each DFS call, we traverse the `K` subsets and try to add `A[i]` to a subset.
24 | 
25 | **Tricks**
26 | 
27 | A important trick is to prevent visiting the same subset value again using `unordered_set`.
28 | 
29 | For example, if you get 4 subsets and each with sum `10`, and now you want to add `5` to one of them. Plain DFS will try adding `5` to each of these `10`s, but adding to which `10` actually makes no difference.
30 | 
31 | So we add the visited values into a `unordered_set` and skip visiting the same subset value when we see them again.
32 | 
33 | Another trick is sorting the `A`. Pick the order that can get a feasible partition as fast as possible.
34 | 
35 | ### DP on Subsets
36 | 
37 | For bit manipulation related to subsets, see the section "Bit Manipulation".
38 | 
39 | 


--------------------------------------------------------------------------------
/line-sweep.md:
--------------------------------------------------------------------------------
1 | # Line Sweep
2 | 
3 | ## Problems
4 | 
5 | * [1854. Maximum Population Year (Easy)](https://leetcode.com/problems/maximum-population-year/)
6 | * [1851. Minimum Interval to Include Each Query (Hard)](https://leetcode.com/problems/minimum-interval-to-include-each-query/)
7 | * [759. Employee Free Time (Hard)](https://leetcode.com/problems/employee-free-time/)
8 | * [1943. Describe the Painting (Medium)](https://leetcode.com/problems/describe-the-painting/)


--------------------------------------------------------------------------------
/longest-common-subsequence.md:
--------------------------------------------------------------------------------
 1 | # Longest Common Subsequence
 2 | 
 3 | Find the longest common subsequence (LCS) among to array of numbers/characters.
 4 | 
 5 | Example:
 6 | 
 7 | ```
 8 | a = "abcde", b = "acef"
 9 | LCS = "ace"
10 | ```
11 | 
12 | The optimal solution is a DP solution with time complexity `O(MN)` and space complexity `O(min(M, N))`.
13 | 
14 | ## Problems
15 | 
16 | * [1143. Longest Common Subsequence (Medium)](https://leetcode.com/problems/longest-common-subsequence/)
17 | 
18 | 


--------------------------------------------------------------------------------
/longest-increasing-subsequence.md:
--------------------------------------------------------------------------------
 1 | # Longest Increasing Subsequence
 2 | 
 3 | Find the longest increasing subsequence from an array of numbers.
 4 | 
 5 | Example: 
 6 | 
 7 | ```
 8 | A = [10,9,2,5,3,7,101,18]
 9 | LIS = [2,3,7,101]
10 | ```
11 | 
12 | The optimal solution is a DP + binary search solution with time complexity `O(NlogN)` and space complexity `O(N)`.
13 | 
14 | ## Problems
15 | 
16 | * [300. Longest Increasing Subsequence (Medium)](https://leetcode.com/problems/longest-increasing-subsequence/)
17 | * [1671. Minimum Number of Removals to Make Mountain Array (Hard)](https://leetcode.com/problems/minimum-number-of-removals-to-make-mountain-array/): a great bidirectional extension of this problem.


--------------------------------------------------------------------------------
/math/README.md:
--------------------------------------------------------------------------------
1 | # Math
2 | 
3 | 


--------------------------------------------------------------------------------
/math/catalan-number.md:
--------------------------------------------------------------------------------
 1 | # Catalan Number
 2 | 
 3 | The `n`th Catalan number is given directly in terms of binomial coefficients by
 4 | 
 5 | $
 6 | C_n = \dfrac{1}{n+1}{2n \choose n} = \dfrac{(2n)!}{(n+1)!n!}=\prod_{k=2}^{n}\dfrac{n+k}{k}\quad \text{for } n \ge 0
 7 | $
 8 | 
 9 | ```cpp
10 | // OJ: https://leetcode.com/problems/unique-binary-search-trees
11 | // Author: github.com/lzl124631x
12 | // Time: O(N)
13 | // Space: O(1)
14 | class Solution {
15 | public:
16 |     int numTrees(int n) {
17 |         long long ans = 1, i;
18 |         for (i = 1; i <= n; ++i) ans = ans * (i + n) / i;
19 |         return ans / i;
20 |     }
21 | };
22 | ```
23 | 
24 | ## Problems
25 | 
26 | * [96. Unique Binary Search Trees \(Medium\)](https://leetcode.com/problems/unique-binary-search-trees/)
27 | 
28 | Related:
29 | 
30 | * [241. Different Ways to Add Parentheses (Medium)](https://leetcode.com/problems/different-ways-to-add-parentheses/)
31 | 
32 | ## Reference
33 | 
34 | * [https://en.wikipedia.org/wiki/Catalan\_number](https://en.wikipedia.org/wiki/Catalan_number)
35 | 
36 | 
37 | 
38 | 


--------------------------------------------------------------------------------
/math/combinatorics.md:
--------------------------------------------------------------------------------
  1 | # Combinatorics
  2 | 
  3 | ## Counting Combinations
  4 | $ C_n^k = \frac{A_n^k}{k!} = \frac{n!}{k! \cdot (n - k)!} = \frac{(n-k+1)\cdot(n-k+2)\cdots n}{k!} $
  5 | 
  6 | ### When `n` is small -- Iteration
  7 | 
  8 | We can use the following equation:
  9 | 
 10 | $ C_n^k = \frac{(n-k+1)\cdot(n-k+2)\cdots n}{k!} = \frac{n-k+1}{1}\cdot\frac{n-k+2}{2}\cdots\frac{n}{k} $
 11 | 
 12 | We compute from **the smaller side** $\frac{n-k+1}{1}$ to avoid the potential non-divisible error caused by $\frac{n}{k}$.
 13 | 
 14 | ```cpp
 15 | // Author: github.com/lzl124631x
 16 | // Time: O(min(K, N - K))
 17 | // Space: O(1)
 18 | int combination(int n, int k) {
 19 |     k = min(k, n - k); // Since we loop in range [1, k], we make sure `k` is smaller than `n - k`
 20 |     long ans = 1;
 21 |     for (int i = 1; i <= k; ++i) {
 22 |         ans = ans * (n - k + i) / i; // compute from the smaller side
 23 |     }
 24 |     return ans;
 25 | }
 26 | ```
 27 | 
 28 | Try this in [62. Unique Paths (Medium)](https://leetcode.com/problems/unique-paths/)
 29 | 
 30 | ### When `n` is large -- Dynamic Programming
 31 | 
 32 | To avoid overflow, we will be asked to return the answer modulo some prime number (`1e9+7` on LeetCode).
 33 | 
 34 | We can't change the above solution to `ans = ans * (n - k + i) / i % mod` because after a previous modulo operation, `ans * (n - k + i)` might not be divisible by `i`.
 35 | 
 36 | We need to use this equation:
 37 | 
 38 | $ C_n^k = C_{n-1}^{k-1} + C_{n-1}^k $
 39 | 
 40 | Memo: Picking `k` elements from `n` elements is the same as the sum of the following:
 41 | 1. Pick the first element, and pick `k - 1` elements from the rest `n - 1` elements, i.e. $C_{n-1}^{k-1}$
 42 | 2. Skip the first element, and pick `k` elements from the rest `n - 1` elements, i.e. $C_{n-1}^k$
 43 | 
 44 | This can be computed using Pascal Triangle and Dynamic Programming.
 45 | 
 46 | ```
 47 |   k  0  1  2  3  4
 48 | n  _______________
 49 | 0 |  1  0  0  0  0
 50 | 1 |  1  1  0  0  0
 51 | 2 |  1  2  1  0  0
 52 | 3 |  1  3  3  1  0
 53 | 4 |  1  4  6  4  1
 54 | ```
 55 | 
 56 | ```
 57 | dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
 58 | dp[i][0] = 1
 59 | ```
 60 | And the answer is `dp[n][k]`.
 61 | 
 62 | ```cpp
 63 | // Author: github.com/lzl124631x
 64 | // Time: O(NK)
 65 | // Space: O(K * (N - K))
 66 | int combination(int n, int k, int mod) {
 67 |     k = min(k, n - k);
 68 |     vector<vector<int>> dp(n + 1, vector<int>(k + 1));
 69 |     for (int i = 0; i <= n; ++i) dp[i][0] = 1;
 70 |     for (int i = 1; i <= n; ++i) {
 71 |         for (int j = 1; j <= k; ++j) {
 72 |             dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
 73 |         }
 74 |     }
 75 |     return dp[n][k];
 76 | }
 77 | ```
 78 | 
 79 | Since `dp[i][j]` only depends on `dp[i-1][j-1]` and `dp[i-1][j]`, we can use 1D array to store the DP values. The answer is `dp[k]`.
 80 | 
 81 | ```cpp
 82 | // Author: github.com/lzl124631x
 83 | // Time: O(NK)
 84 | // Space: O(min(K, N - K))
 85 | int combination(int n, int k, int mod) {
 86 |     k = min(k, n - k);
 87 |     vector<int> dp(k + 1);
 88 |     dp[0] = 1;
 89 |     for (int i = 1; i <= n; ++i) {
 90 |         for (int j = min(i, k); j > 0; --j) {
 91 |             dp[j] = (dp[j] + dp[j - 1]) % mod;
 92 |         }
 93 |     }
 94 |     return dp[k];
 95 | }
 96 | ```
 97 | 
 98 | Try this in [1569. Number of Ways to Reorder Array to Get Same BST (Hard)](https://leetcode.com/problems/number-of-ways-to-reorder-array-to-get-same-bst/)
 99 | 
100 | ### Sum of combinations
101 | 
102 | We can use the following equation to get some useful conclusions:
103 | 
104 | $
105 | (a + b)^n = C_n^0\cdot a^0\cdot b^n + C_n^1\cdot a^1\cdot b^{n-1} + \dots + C_n^n\cdot a^n\cdot b^0
106 | $
107 | 
108 | Let `a = 1, b = 1`, we have
109 | 
110 | $
111 | C_n^0 + C_n^1 + C_n^2 + \dots + C_n^{n-1} + C_n^n = 2^n
112 | $
113 | 
114 | Let `a = 1, b = -1`, we have
115 | 
116 | $
117 | C_n^0 - C_n^1 + C_n^2 - C_n^3 + C_n^4 - C_n^5 + \dots = 0
118 | $
119 | 
120 | So 
121 | 
122 | $
123 | \sum_{p}C_n^p = \sum_{q}C_n^q = 2^{n-1}
124 | $
125 | where `p` and `q` represent all the even and odd numbers in `[0, n]`, respectively. 
126 | 
127 | We can use this trick in [1863. Sum of All Subset XOR Totals (Easy)](https://leetcode.com/problems/sum-of-all-subset-xor-totals/)
128 | 
129 | ### Problems
130 | 
131 | * [62. Unique Paths (Medium)](https://leetcode.com/problems/unique-paths/)
132 | * [1569. Number of Ways to Reorder Array to Get Same BST (Hard)](https://leetcode.com/problems/number-of-ways-to-reorder-array-to-get-same-bst/)
133 | * [1863. Sum of All Subset XOR Totals (Easy)](https://leetcode.com/problems/sum-of-all-subset-xor-totals/)
134 | * [2400. Number of Ways to Reach a Position After Exactly k Steps (Medium)](https://leetcode.com/problems/number-of-ways-to-reach-a-position-after-exactly-k-steps)
135 | * [2842. Count K-Subsequences of a String With Maximum Beauty (Hard)](https://leetcode.com/problems/count-k-subsequences-of-a-string-with-maximum-beauty)
136 | 
137 | ## Generating Combinations
138 | 
139 | ### Problems
140 | 
141 | * [77. Combinations (Medium)](https://leetcode.com/problems/combinations)
142 | * [1601. Maximum Number of Achievable Transfer Requests (Hard)](https://leetcode.com/problems/maximum-number-of-achievable-transfer-requests/)


--------------------------------------------------------------------------------
/math/factorial.md:
--------------------------------------------------------------------------------
 1 | # Factorial
 2 | 
 3 | $ n! = 1 \times 2 \times 3 \times \dots \times (n - 1) \times n $
 4 | 
 5 | ```cpp
 6 | typedef long long int64;
 7 | const int N = 1e5 + 10;
 8 | int fact[N], ifact[N], inv[N];
 9 | struct comb_init {
10 |     comb_init() {
11 |         inv[1] = 1;
12 |         for (int i = 2; i < N; ++i) {
13 |             inv[i] = (MOD - MOD / i) * (int64)inv[MOD % i] % MOD;
14 |         }
15 |         fact[0] = ifact[0] = 1;
16 |         for (int i = 1; i < N; ++i) {
17 |             fact[i] = (int64)fact[i - 1] * i % MOD;
18 |             ifact[i] = (int64)ifact[i - 1] * inv[i] % MOD;
19 |         }
20 |     }
21 | } comb_init_;
22 | 
23 | int64 comb(int n, int m) {
24 |     if (n < m || m < 0) return 0;
25 |     return (int64)fact[n] * ifact[m] % MOD * ifact[n - m] % MOD;
26 | }
27 | ```
28 | 
29 | ## Problems
30 | 
31 | * [1735. Count Ways to Make Array With Product (Hard)](https://leetcode.com/problems/count-ways-to-make-array-with-product/)


--------------------------------------------------------------------------------
/math/factorization.md:
--------------------------------------------------------------------------------
 1 | # Factorization
 2 | 
 3 | Get all the prime factors of `n`.
 4 | 
 5 | ## Implementation
 6 | 
 7 | ```cpp
 8 | vector<int> factors(int n) {
 9 |     vector<int> ans;
10 |     for (int d = 2; d * d <= n; ++d) { // This `d * d <= n` is key to reduce time complexity.
11 |         if (n % d == 0) ans.push_back(d); // if `n` is divisible by `d`, add `d` as a factor
12 |         while (n % d == 0) n /= d; // keep removing this factor from `n` until `n` is no longer divisible by `d`
13 |     }
14 |     if (n > 1) ans.push_back(n); // If `n` is still not `1`, then the remaining `n` is a prime factor.
15 |     return ans;
16 | }
17 | ```
18 | 
19 | ## Problems
20 | 
21 | * [952. Largest Component Size by Common Factor (Hard)](https://leetcode.com/problems/largest-component-size-by-common-factor/)
22 | 
23 | ## Reference
24 | 
25 | https://cp-algorithms.com/algebra/factorization.html


--------------------------------------------------------------------------------
/math/fast-pow.md:
--------------------------------------------------------------------------------
 1 | # Fast Pow
 2 | 
 3 | Take `2^5` for example, $2^5 = 2^{4+1} = 2^4 * 2^1$
 4 | 
 5 | Initially, `base = 2, ans = 1, exp = 5 = (101)`
 6 | 
 7 | Here, the rightmost `1` means that we should multiply `ans` by `2^1`.
 8 | 
 9 | The middle `0` means that we should NOT multiply `ans` by `2^2`.
10 | 
11 | The leftmost `1` means that we should multiply `ans` by `2^4`.
12 | 
13 | In sum, we can keep doing `exp >>= 1` and `base = (base * base)`. We only do `ans = (ans * base)` when `exp & 1 == 1`.
14 | 
15 | ## Implementation
16 | 
17 | ```cpp
18 | // Time: O(logE)
19 | // Space: O(1)
20 | int modpow(int base, int exp, int mod) {
21 |     base %= mod;
22 |     long ans = 1;
23 |     while (exp > 0) {
24 |         if (exp & 1) ans = ans * base % mod;
25 |         base = (long)base * base % mod;
26 |         exp >>= 1;
27 |     }
28 |     return ans;
29 | }
30 | ```
31 | 
32 | Or simply pre-compute those pows.
33 | 
34 | ```cpp
35 | vector<int> p(exp + 1, 1);
36 | for (int i = 1; i <= exp; ++i) p[i] = ((long long) p[i - 1] * base) % mod;
37 | ```
38 | 
39 | If we want to reuse the result across test cases, we can use `static vector`.
40 | 
41 | ```cpp
42 | static vector<int> p{1};
43 | while (p.size() <= exp) p.push_back(((long long) p.back() * base) % mod);
44 | ```
45 | 
46 | ## Problems
47 | 
48 | * [1498. Number of Subsequences That Satisfy the Given Sum Condition \(Medium\)](https://leetcode.com/problems/number-of-subsequences-that-satisfy-the-given-sum-condition/)
49 | 
50 | 


--------------------------------------------------------------------------------
/math/gcd.md:
--------------------------------------------------------------------------------
 1 | # Greatest Common Divisor (GCD)
 2 | 
 3 | ## Euclidean algorithm
 4 | 
 5 | ```text
 6 | gcd(a, 0) = a
 7 | gcd(a, b) = gcd(b, a % b)
 8 | ```
 9 | 
10 | Recursive:
11 | 
12 | ```cpp
13 | int gcd(int a, int b) {
14 |     return b ? gcd(b, a % b) : a;
15 | }
16 | ```
17 | 
18 | Iterative:
19 | 
20 | ```cpp
21 | int gcd(int a, int b) {
22 |     if (b) while ((a %= b) && (b %= a));
23 |     return a + b;
24 | }
25 | ```
26 | 
27 | ## C++ Built-in function
28 | 
29 | C++ has a built-in `__gcd` function.
30 | 
31 | ```cpp
32 | __gcd(6, 20); // 2
33 | ```
34 | 
35 | Since C++11, we can directly use `gcd`.
36 | 
37 | ## Time Complexity
38 | 
39 | https://www.geeksforgeeks.org/time-complexity-of-euclidean-algorithm/
40 | 
41 | It's `O(log(min(A, B)))`
42 | 
43 | ## Problems
44 | 
45 | * [858. Mirror Reflection (Medium)](https://leetcode.com/problems/mirror-reflection/)
46 | * [2183. Count Array Pairs Divisible by K (Hard)](https://leetcode.com/problems/count-array-pairs-divisible-by-k/)


--------------------------------------------------------------------------------
/math/geometry.md:
--------------------------------------------------------------------------------
 1 | # Geometry
 2 | 
 3 | ## Dot Product of Vectors
 4 | 
 5 | Dot product is also known as **scalar product** or **inner product**.
 6 | 
 7 | 
 8 | Algebraically, the dot product is the sum of the products of the corresponding entries of the two sequences of numbers.
 9 | 
10 | $
11 | \bm{a}\cdot \bm{b} = \sum_{i=1}^na_ib_i
12 | $
13 | 
14 | Geometrically, it is the product of the Euclidean magnitudes of the two vectors and the cosine of the angle between them.
15 | 
16 | $
17 | \bm{a}\cdot \bm{b}=\lvert \bm{a}\rvert\lvert \bm{b}\rvert\cos\theta
18 | $
19 | 
20 | ### Usage
21 | 
22 | 1. Calculate the angle between two vectors.
23 | 
24 | $
25 | \cos\theta
26 | =\frac{\bm{a}\cdot \bm{b}}{\lvert \bm{a}\rvert\lvert \bm{b}\rvert}$
27 | 
28 | 2. If two vectors are perpendicular, the dot product is `0`.
29 | 
30 | ### Problem
31 | 
32 | * [963. Minimum Area Rectangle II (Medium)](https://leetcode.com/problems/minimum-area-rectangle-ii/)
33 | 
34 | ## Cross Product of Vectors
35 | 
36 | Cross product is also known as **vector product** ((occasionally **directed area product**, to emphasize its geometric significance) )
37 | 
38 | The cross product $\bm{a}\times\bm{b}$ is defined as $\bm{a}$ vector $\bm{c}$ that is perpendicular (orthogonal) to both $\bm{a}$ and $\bm{b}$, with $\bm{a}$ direction given by the right-hand rule and a magnitude equal to the area of the parallelogram that the vectors span.
39 | 
40 | $
41 | \bm{a}\times\bm{b}=\lvert\bm{a}\rvert\lvert\bm{b}\rvert\sin(\theta)\bm{n}
42 | $
43 | 
44 | where $\bm{n}$ is a unit vector perpendicular to the plane containing $\bm{a}$ and $\bm{b}$.
45 | 
46 | ![Finding the direction of the cross product by the right-hand rule.](../.gitbook/assets/cross-product-right-hand-rule.png)
47 | 
48 | ## Check if three points are one te same line
49 | 
50 | Say we have 3 points, `(x1, y1)`, `(x2, y2)` and `(x3, y3)`. Check if they are on the same line.
51 | 
52 | Normally we can check if slopes are the same.
53 | 
54 | $
55 | \frac{y_2-y_1}{x_2-x_1} = \frac{y_3-y_2}{x_3-x_2}
56 | $
57 | 
58 | To avoid:
59 | 1. The precision error we might get from the divisions
60 | 2. Divide by zero issue
61 | 
62 | We can use the following equation:
63 | 
64 | $
65 | (y_2-y_1)\cdot(x_3-x_2) = (y_3-y_2)\cdot(x_2-x_1)
66 | $
67 | 
68 | Example question: [2280. Minimum Lines to Represent a Line Chart (Medium)](https://leetcode.com/problems/minimum-lines-to-represent-a-line-chart)
69 | 
70 | ## Get angle between two points
71 | 
72 | Assume we have two points `(x1, y1)` and `(x2, y2)`, we want to get the angle between these two points
73 | 
74 | ```cpp
75 | if ((x1 > x2) || (x1 == x2 && y1 < y2)) swap(x1, x2), swap(y1, y2); // make sure these two points are ordered
76 | atan2(x2 - x1, y2 - y1)
77 | ```
78 | 
79 | Example question: [149. Max Points on a Line (Hard)](https://leetcode.com/problems/max-points-on-a-line)


--------------------------------------------------------------------------------
/math/get-digits.md:
--------------------------------------------------------------------------------
1 | # Get Digits
2 | 
3 | When you want to get all the digits of a integer `n`, instead of doing `n /= 10, n % 10`, use `to_string(n)`. It's shorter and less error-prone. For example, you don't need to consider `n = 0`.
4 | 
5 | ## Problems
6 | 
7 | * [2191. Sort the Jumbled Numbers (Medium)](https://leetcode.com/problems/sort-the-jumbled-numbers/)


--------------------------------------------------------------------------------
/math/lcm.md:
--------------------------------------------------------------------------------
 1 | # Least Common Multiple (LCM)
 2 | 
 3 | ```cpp
 4 | lcm(a, b) = a * b / gcd(a, b)
 5 | lcm(a, b, c) = lcm(lcm(a, b), c)
 6 | ```
 7 | 
 8 | ## std::lcm
 9 | 
10 | In STL, there is a built-in `std::lcm`


--------------------------------------------------------------------------------
/math/median-minimizes-sum-of-absolute-deviations.md:
--------------------------------------------------------------------------------
 1 | # Any Median minimizes the sum of absolute deviations
 2 | 
 3 | https://math.stackexchange.com/questions/113270/the-median-minimizes-the-sum-of-absolute-deviations-the-ell-1-norm
 4 | 
 5 | If the array has odd number of elements, there is only a single median which minimizes the sum of absolute deviations.
 6 | 
 7 | If the array has even number of elements, any numbers between (including) the two median numbers minimizes the sum of absolute deviations.
 8 | 
 9 | 
10 | * mean minimizes total distance for euclidian distance
11 | * median minimzes total distance for absolute deviation
12 | * mode minimizes distance for indicator function
13 | 
14 | 
15 | ## Problems
16 | 
17 | * [296. Best Meeting Point (Hard)](https://leetcode.com/problems/best-meeting-point/)
18 | * [462. Minimum Moves to Equal Array Elements II (Medium)](https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/)
19 | * [2033. Minimum Operations to Make a Uni-Value Grid (Medium)](https://leetcode.com/problems/minimum-operations-to-make-a-uni-value-grid/)


--------------------------------------------------------------------------------
/math/mode.md:
--------------------------------------------------------------------------------
1 | # Mode
2 | 
3 | Mode is the most frequently occurred element.
4 | 
5 | ## Problems
6 | 
7 | * [501. Find Mode in Binary Search Tree (Easy)](https://leetcode.com/problems/find-mode-in-binary-search-tree/)


--------------------------------------------------------------------------------
/math/modular-multiplicative-inverse.md:
--------------------------------------------------------------------------------
 1 | # Modular Multiplicative Inverse
 2 | 
 3 | A \[modular multiplicative inverse]\[1] of an integer $a$ is an integer $x$ such that $a\cdot x$ is congruent to 1 modular some modulus $m$. To write it in a formal way: we want to find an integer $x$ so that
 4 | 
 5 | $a\cdot x\equiv1\;(mod\;m)$
 6 | 
 7 | We will also denote $x$ simply with $a^{−1}$.
 8 | 
 9 | For example, assume $a = 5, m = 13$, then $a^{-1} = 8$ because $5\cdot 8 \mod 13 = 1$.
10 | 
11 | We should note that the modular inverse does not always exist. For example, let $m=4, a=2$. By checking all possible values modulo $m$ is should become clear that we cannot find $a^{−1}$ satisfying the above equation. It can be proven that the modular inverse exists if and only if $a$ and $m$ are relatively prime (i.e. $gcd(a,m)=1$).
12 | 
13 | In this article, we present two methods for finding the modular inverse in case it exists, and one method for finding the modular inverse for all numbers in linear time.
14 | 
15 | ## Finding the Modular Inverse using Extended Euclidean algorithm
16 | 
17 | Consider the following equation (with unknown $x$ and $y$):
18 | 
19 | $a\cdot x+m\cdot y=1$
20 | 
21 | This is a [Linear Diophantine equation in two variables](https://cp-algorithms.com/algebra/linear-diophantine-equation.html). As shown in the linked article, when $gcd(a,m)=1$, the equation has a solution which can be found using the extended Euclidean algorithm. Note that $gcd(a,m)=1$ is also the condition for the modular inverse to exist.
22 | 
23 | > NOTE: [Diophantine equation](https://en.wikipedia.org/wiki/Diophantine\_equation) (丢番图方程, 不定方程)
24 | 
25 | Now, if we take modulo m of both sides, we can get rid of m⋅y, and the equation becomes:
26 | 
27 | a⋅x≡1modm Thus, the modular inverse of a is x.
28 | 
29 | The implementation is as follows:
30 | 
31 | ## Reference
32 | 
33 | * [https://oi-wiki.org/math/inverse/](https://oi-wiki.org/math/inverse/)
34 | 
35 | \[1]: [https://en.wikipedia.org/wiki/Modular\_multiplicative\_inverse](https://en.wikipedia.org/wiki/Modular\_multiplicative\_inverse)
36 | 


--------------------------------------------------------------------------------
/math/palindrome.md:
--------------------------------------------------------------------------------
 1 | # Palindrome
 2 | 
 3 | An integer is a palindrome if it reads the same from left to right as it does from right to left.
 4 | 
 5 | ## Check whether a number is a Palindrome
 6 | 
 7 | ```cpp
 8 | // Author: github.com/lzl124631x
 9 | // Time: O(lgN)
10 | // Space: O(1)
11 | bool isPalindrome(long n) {
12 |     long r = 0;
13 |     for (long tmp = n; tmp; tmp /= 10) r = r * 10 + tmp % 10;
14 |     return r == n;
15 | }
16 | ```
17 | 
18 | ## Generate Increasing Palindrome Numbers
19 | 
20 | [866. Prime Palindrome (Medium)](https://leetcode.com/problems/prime-palindrome/) is a good problem for testing the code for generating palindromes.
21 | 
22 | ```cpp
23 | // OJ: https://leetcode.com/problems/prime-palindrome/
24 | // Author: github.com/lzl124631x
25 | // Time: O(N)
26 | // Space: O(1)
27 | class Solution {
28 |     int getPalindrome(int half, bool odd) {
29 |         int pal = half;
30 |         if (odd) half /= 10;
31 |         for (; half; half /= 10) pal = pal * 10 + half % 10;
32 |         return pal;
33 |     }
34 |     bool isPrime(int n) {
35 |         if (n < 2) return false;
36 |         for (int d = 2; d * d <= n; ++d) {
37 |             if (n % d == 0) return false;
38 |         }
39 |         return true;
40 |     }
41 | public:
42 |     int primePalindrome(int n) {
43 |         for (int len = 1; true; ++len) {
44 |             int begin = pow(10, (len - 1) / 2), end = pow(10, (len + 1) / 2);
45 |             for (int half = begin; half < end; ++half) {
46 |                 int pal = getPalindrome(half, len % 2);
47 |                 if (pal >= n && isPrime(pal)) return pal;
48 |             }
49 |         }
50 |         return -1;
51 |     }
52 | };
53 | ```
54 | 
55 | ## Problems
56 | 
57 | * [479. Largest Palindrome Product (Hard)](https://leetcode.com/problems/largest-palindrome-product/)
58 | * [866. Prime Palindrome (Medium)](https://leetcode.com/problems/prime-palindrome/)
59 | * [906. Super Palindromes (Hard)](https://leetcode.com/problems/super-palindromes/)
60 | * [2081. Sum of k-Mirror Numbers (Hard)](https://leetcode.com/problems/sum-of-k-mirror-numbers/)
61 | * [2217. Find Palindrome With Fixed Length (Medium)](https://leetcode.com/problems/find-palindrome-with-fixed-length/)


--------------------------------------------------------------------------------
/math/prime-number.md:
--------------------------------------------------------------------------------
 1 | # Prime Number
 2 | 
 3 | An integer is prime if it has exactly two divisors: 1 and itself. Note that 1 is not a prime number.
 4 | 
 5 | ```cpp
 6 | // Author: github.com/lzl124631x
 7 | // Time: O(sqrt(N))
 8 | // Space: O(1)
 9 | bool isPrime(int n) {
10 |     if (n < 2) return false;
11 |     for (int d = 2; d * d <= n; ++d) {
12 |         if (n % d == 0) return false;
13 |     }
14 |     return true;
15 | }
16 | ```
17 | 
18 | ## Even-digit palindromes are not primes except 11
19 | 
20 | All even-digit palindromes, except for 11, are not primes because they are divisible by `11`. For example, `2332 / 11 = 212`
21 | 
22 | [866. Prime Palindrome (Medium)](https://leetcode.com/problems/prime-palindrome/)


--------------------------------------------------------------------------------
/math/round-up.md:
--------------------------------------------------------------------------------
1 | # Round Up
2 | 
3 | Assume `A > 0` and `B > 0` are two integers, `ceil((double)A / B)` can be written as `(A + B - 1) / B`.


--------------------------------------------------------------------------------
/math/sieve-of-eratosthenes.md:
--------------------------------------------------------------------------------
 1 | # Sieve Of Eratosthenes
 2 | 
 3 | The sieve of Eratosthenes is an algorithm for finding all prime numbers up to any given limit.
 4 | 
 5 | ## Algorithm
 6 | 
 7 | Start from the first prime `2`, mark all the multiples of `2` as composite (i.e. not prime). So we mark `2*2, 2*3, 2*4, ...` until we reach the greater number in consideration.
 8 | 
 9 | Then the next first number after `2` that is not marked as composite is a prime. It's `3`. Then we do the same thing, marking all the multiples of `3` as composite, `3*2, 3*3, 3*4, ...`. Note that since `2*3` has already been marked, so we shouldn't mark it again. Thus, instead of start marking from `2 * 3`, we should start from `3 * 3`, i.e. `sqrt(3)`.
10 | 
11 | Then the next prime is `5`, we mark all its multiples as composite. Again, we should start marking from `sqrt(5)` since `2*5, 3*5, 4*5` have all been marked already.
12 | 
13 | And so on. Until we've visited all the numbers within the maximum number.
14 | 
15 | ![](../.gitbook/assets/Sieve\_of\_Eratosthenes\_animation.gif)
16 | 
17 | ## Implementation
18 | 
19 | ```cpp
20 | // OJ: https://leetcode.com/problems/count-primes/
21 | // Author: github.com/lzl124631x
22 | // Time: O(NloglogN)
23 | // Space: O(N)
24 | // Ref: https://leetcode.com/problems/count-primes/solution/
25 | class Solution {
26 | public:
27 |     int countPrimes(int n) {
28 |         if (n <= 1) return 0;
29 |         vector<bool> prime(n, true);
30 |         int ans = 0, bound = sqrt(n);
31 |         for (int i = 2; i < n; ++i) {
32 |             if (!prime[i]) continue;
33 |             ++ans;
34 |             if (i > bound) continue; // If i > bound, then i * i must be greater than `n`, skip. This can prevent overflow caused by `i * i`.
35 |             for (int j = i * i; j < n; j += i) prime[j] = false; // note that we start from `i * i` instead of `2` because all multiples of `2, 3, ..., (i-1)` must be marked already
36 |         }
37 |         return ans;
38 |     }
39 | };
40 | ```
41 | 
42 | ## Problems
43 | 
44 | * [204. Count Primes (Easy)](https://leetcode.com/problems/count-primes/)
45 | * [1175. Prime Arrangements (Easy)](https://leetcode.com/problems/prime-arrangements/)
46 | * [1627. Graph Connectivity With Threshold (Hard)](https://leetcode.com/problems/graph-connectivity-with-threshold/)
47 | * [2523. Closest Prime Numbers in Range (Medium)](https://leetcode.com/problems/closest-prime-numbers-in-range)
48 | 
49 | ## Reference
50 | 
51 | * [https://en.wikipedia.org/wiki/Sieve\_of\_Eratosthenes](https://en.wikipedia.org/wiki/Sieve\_of\_Eratosthenes)
52 | 


--------------------------------------------------------------------------------
/math/stars-and-bars.md:
--------------------------------------------------------------------------------
 1 | # Stars And Bars
 2 | 
 3 | ## Problems
 4 | 
 5 | * [1735. Count Ways to Make Array With Product (Hard)](https://leetcode.com/problems/count-ways-to-make-array-with-product/)
 6 | 
 7 | ## Reference
 8 | 
 9 | * [https://en.wikipedia.org/wiki/Stars\_and\_bars\_%28combinatorics%29](https://en.wikipedia.org/wiki/Stars\_and\_bars\_\(combinatorics\))
10 | 


--------------------------------------------------------------------------------
/math/sum-of-sequence.md:
--------------------------------------------------------------------------------
 1 | # Sum Of Sequence
 2 | 
 3 | The series $\sum\limits\_{k=1}^n k^a = 1^a + 2^a + 3^a + \dots + n^a$ gives the sum of the $a^\text{th}$ powers of the first nn positive numbers, where aa and $n$ are positive integers. Each of these series can be calculated through a closed-form formula.
 4 | 
 5 | The case $a=1,n=100$ is famously said to have been solved by Gauss as a young schoolboy: given the tedious task of adding the first 100 positive integers, Gauss quickly used a formula to calculate the sum of 5050.
 6 | 
 7 | The formulas for the first few values of $a$ are as follows:
 8 | 
 9 | $\sum\limits_{k=1}^n k = \frac{n(n+1)}{2}$
10 | 
11 | $\sum\limits_{k=1}^n k^2 = \frac{n(n+1)(2n+1)}{6}$
12 | 
13 | $\sum\limits_{k=1}^n k^3 = \frac{n^2(n+1)^2}{4}$
14 | 
15 | ## Reference
16 | 
17 | * [https://brilliant.org/wiki/sum-of-n-n2-or-n3/](https://brilliant.org/wiki/sum-of-n-n2-or-n3/)
18 | 


--------------------------------------------------------------------------------
/meet-in-the-middle.md:
--------------------------------------------------------------------------------
1 | # Meet in the Middle
2 | 
3 | ## Problems
4 | 
5 | * [2035. Partition Array Into Two Arrays to Minimize Sum Difference (Hard)](https://leetcode.com/problems/partition-array-into-two-arrays-to-minimize-sum-difference/)


--------------------------------------------------------------------------------
/minmax.md:
--------------------------------------------------------------------------------
 1 | # Minmax
 2 | 
 3 | Minimax is a kind of backtracking algorithm that is used in decision making and game theory to find the optimal move for a player, assuming that your opponent also plays optimally. It is widely used in two player turn-based games such as Tic-Tac-Toe, Backgammon, Mancala, Chess, etc.
 4 | 
 5 | ## Problems
 6 | 
 7 | * [1406. Stone Game III \(Hard\)](https://leetcode.com/problems/stone-game-iii/)
 8 | 
 9 | ## Reference
10 | 
11 | * [https://www.geeksforgeeks.org/minimax-algorithm-in-game-theory-set-1-introduction/](https://www.geeksforgeeks.org/minimax-algorithm-in-game-theory-set-1-introduction/)
12 | 
13 | 


--------------------------------------------------------------------------------
/miscellaneous/README.md:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | 
3 | 


--------------------------------------------------------------------------------
/miscellaneous/bin-packing.md:
--------------------------------------------------------------------------------
1 | # Bin Packing
2 | 
3 | [https://developers.google.com/optimization/bin/bin](https://developers.google.com/optimization/bin/bin)
4 | 


--------------------------------------------------------------------------------
/miscellaneous/floyds-tortoise-and-hare.md:
--------------------------------------------------------------------------------
1 | # Floyd's Tortoise and Hare (Cycle Detection)
2 | 
3 | ## Problems
4 | 
5 | * [141. Linked List Cycle (Easy)](https://leetcode.com/problems/linked-list-cycle/)
6 | * [142. Linked List Cycle II (Medium)](https://leetcode.com/problems/linked-list-cycle-ii/)
7 | * [287. Find the Duplicate Number (Medium)](https://leetcode.com/problems/find-the-duplicate-number/)


--------------------------------------------------------------------------------
/miscellaneous/hungarian.md:
--------------------------------------------------------------------------------
1 | # Hungarian Algorithm
2 | 
3 | 匈牙利算法
4 | 
5 | https://leetcode.com/problems/minimum-moves-to-spread-stones-over-grid/solutions/4024777/python-hungarian-assignment-10-lines-o-n-3-beats-100/
6 | https://en.wikipedia.org/wiki/Hungarian_algorithm


--------------------------------------------------------------------------------
/miscellaneous/palindrome.md:
--------------------------------------------------------------------------------
 1 | # Palindrome
 2 | 
 3 | ## Common solutions
 4 | 
 5 | When we need to check whether a substring `s[i..j]` is a palindrome for all pairs of `i, j`, we can use the following solutions to reduce the time complexity from the brute force `O(N^3)` to `O(N^2)`.
 6 | 
 7 | ### Rolling Hash
 8 | 
 9 | Calculate the hash in both directions and then compare the hash.
10 | 
11 | Example: [1745. Palindrome Partitioning IV (Hard)](https://github.com/lzl124631x/LeetCode/tree/master/leetcode/1745.%20Palindrome%20Partitioning%20IV)
12 | 
13 | ### DP table
14 | 
15 | Let `dp[i][j]` be whether substring `s[i..j]` is a palindrome.
16 | 
17 | ```
18 | dp[i][j] = s[i] == s[j] && dp[i + 1][j - 1]
19 | dp[i][i] = true
20 | ```
21 | 
22 | Example: [1745. Palindrome Partitioning IV (Hard)](https://github.com/lzl124631x/LeetCode/tree/master/leetcode/1745.%20Palindrome%20Partitioning%20IV)
23 | 


--------------------------------------------------------------------------------
/mono-deque.md:
--------------------------------------------------------------------------------
 1 | # Mono-deque
 2 | 
 3 | One typical usage of mono-deque is to find the maximum/minimum value in a sliding window.
 4 | 
 5 | If we are looking for the **maximum** value, we can use a **descending** monoqueue. Example: [239. Sliding Window Maximum (Hard)](https://leetcode.com/problems/sliding-window-maximum/).
 6 | 
 7 | ## How to memorize?
 8 | 
 9 | If we are looking for the **maximum** values in a sliding window. When a large number goes into window, for all the smaller or equal numbers in front of this number, their eviction from the window won't affect the max value of the sliding window, so they can be discarded. In other words, the mono-deque will only contain the numbers that are greater than the current new number, so it's a **desending** mono-deque.
10 | 
11 | ## Problems
12 | 
13 | * [239. Sliding Window Maximum (Hard)](https://leetcode.com/problems/sliding-window-maximum/)
14 | * [862. Shortest Subarray with Sum at Least K \(Hard\)](https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/)
15 | * [1499. Max Value of Equation \(Hard\)](https://leetcode.com/problems/max-value-of-equation/)
16 | * [1696. Jump Game VI (Medium)](https://leetcode.com/problems/jump-game-vi/)
17 | 


--------------------------------------------------------------------------------
/monotonic-stack.md:
--------------------------------------------------------------------------------
 1 | # Monotonic Stack
 2 | 
 3 | A monotonic stack is a stack whose elements are monotonically increasing or descreasing.
 4 | 
 5 | Sometimes we store the index of the elements in the stack and make sure the elements corresponding to those indexes in the stack forms a mono-sequence.
 6 | 
 7 | ## Increasing or decreasing?
 8 | 
 9 | If we need to pop **smaller** elements from the stack before pushing a new element, the stack is **decreasing** from bottom to top.
10 | 
11 | Otherwise, it's **increasing** from bottom to top.
12 | 
13 | For example,
14 | 
15 | ```
16 | Mono-decreasing Stack
17 | 
18 | Before: [5,4,2,1]
19 | To push 3, we need to pop smaller (or equal) elements first
20 | After: [5,4,3]
21 | ```
22 | 
23 | ## Notes
24 | 
25 | For a mono-**decreasing** stack:
26 | * we need to pop **smaller** elements before pushing.
27 | * it keep tightening the result as lexigraphically **greater** as possible. (Because we keep popping smaller elements out and keep greater elements).
28 | 
29 | ![](.gitbook/assets/monostack.png)
30 | 
31 | Take [402. Remove K Digits (Medium)](https://leetcode.com/problems/remove-k-digits/) for example, since we are looking for lexigraphically **smallest** subsequence, we should use mono-**increasing** stack.
32 | 
33 | ## Both nextSmaller and prevSmaller
34 | 
35 | If we need to calculate both `nextSmaller` and `prevSmaller` arrays, we can do it using a mono-stack in one pass.
36 | 
37 | The following code is for [84. Largest Rectangle in Histogram (Hard)](https://leetcode.com/problems/largest-rectangle-in-histogram/)
38 | 
39 | ```cpp
40 | // OJ: https://leetcode.com/problems/largest-rectangle-in-histogram/
41 | // Author: github.com/lzl124631x
42 | // Time: O(N)
43 | // Space: O(N)
44 | class Solution {
45 | public:
46 |     int largestRectangleArea(vector<int>& A) {
47 |         A.push_back(0); // append a zero at the end so that we can pop all elements from the stack and calculate the corresponding areas
48 |         int N = A.size(), ans = 0;
49 |         stack<int> s; // strictly-increasing mono-stack
50 |         for (int i = 0; i < N; ++i) {
51 |             while (s.size() && A[i] <= A[s.top()]) { // Take `A[i]` as the right edge
52 |                 int height = A[s.top()]; // Take the popped element as the height
53 |                 s.pop();
54 |                 int left = s.size() ? s.top() : -1; // Take the element left on the stack as the left edge
55 |                 ans = max(ans, (i - left - 1) * height);
56 |             }
57 |             s.push(i);
58 |         }
59 |         return ans;
60 |     }
61 | };
62 | ```
63 | 
64 | ## Problems
65 | 
66 | * [402. Remove K Digits (Medium)](https://leetcode.com/problems/remove-k-digits/)
67 | * [496. Next Greater Element I \(Easy\)](https://leetcode.com/problems/next-greater-element-i/)
68 | * [1019. Next Greater Node In Linked List \(Medium\)](https://leetcode.com/problems/next-greater-node-in-linked-list/)
69 | * [503. Next Greater Element II \(Medium\)](https://leetcode.com/problems/next-greater-element-ii/)
70 | * [1475. Final Prices With a Special Discount in a Shop \(Easy\)](https://leetcode.com/problems/final-prices-with-a-special-discount-in-a-shop/)
71 | * [84. Largest Rectangle in Histogram \(Hard\)](https://leetcode.com/problems/largest-rectangle-in-histogram/)
72 | * [85. Maximal Rectangle \(Hard\)](https://leetcode.com/problems/maximal-rectangle/)
73 | * [456. 132 Pattern \(Medium\)](https://leetcode.com/problems/132-pattern/)
74 | * [1504. Count Submatrices With All Ones \(Medium\)](https://leetcode.com/problems/count-submatrices-with-all-ones/)
75 | * [1673. Find the Most Competitive Subsequence (Medium)](https://leetcode.com/problems/find-the-most-competitive-subsequence/)
76 | * [907. Sum of Subarray Minimums (Medium)](https://leetcode.com/problems/sum-of-subarray-minimums/)
77 | * [1856. Maximum Subarray Min-Product (Medium)](https://leetcode.com/problems/maximum-subarray-min-product/)
78 | * [1124. Longest Well-Performing Interval (Medium)](https://leetcode.com/problems/longest-well-performing-interval/)


--------------------------------------------------------------------------------
/offline-query.md:
--------------------------------------------------------------------------------
 1 | # Offline Query
 2 | 
 3 | A common trick for solving problems related to a series of queries. 
 4 | 
 5 | When we know all the queries upfront, we can sort the query and the original data in some order so that we can scan the query and the original data simultaneously (which takes `O(N + Q)` time), instead of scanning all original data for each query (which takes `O(N * Q)` time).
 6 | 
 7 | The name "offline" signifies the fact that we know all the queries upfront/offline. If the queries keep streaming in (i.e. online), we can't reorder the queries to get a better time complexity.
 8 | 
 9 | ## Problems
10 | 
11 | * [1707. Maximum XOR With an Element From Array (Hard)](https://leetcode.com/problems/maximum-xor-with-an-element-from-array/)
12 | * [1847. Closest Room (Hard)](https://leetcode.com/problems/closest-room/)
13 | * [2070. Most Beautiful Item for Each Query (Medium)](https://leetcode.com/problems/most-beautiful-item-for-each-query/)
14 | 
15 | ## Discuss
16 | 
17 | https://leetcode.com/problems/most-beautiful-item-for-each-query/discuss/1576065/C%2B%2B-Offline-Query


--------------------------------------------------------------------------------
/p-and-np.md:
--------------------------------------------------------------------------------
 1 | # P And Np
 2 | 
 3 | ## P
 4 | 
 5 | P is a complexity class that represents the set of all decision problems that can be solved in polynomial time.
 6 | 
 7 | That is, given an instance of the problem, the answer yes or no can be decided in polynomial time.
 8 | 
 9 | **Example**
10 | 
11 | Given a connected graph G, can its vertices be coloured using two colours so that no edge is monochromatic?
12 | 
13 | Algorithm: start with an arbitrary vertex, color it red and all of its neighbours blue and continue. Stop when you run out of vertices or you are forced to make an edge have both of its endpoints be the same color.
14 | 
15 | ## NP
16 | 
17 | NP (nondeterministic polynomial time) is a complexity class used to classify decision problems
18 | 
19 | TODO
20 | 
21 | ## NP Complete
22 | 
23 | ## NP Hard
24 | 
25 | ## What should we do if we know a problem is NP-hard/NP-complete?
26 | 
27 | We have to do searching, and think of ways to optimize the searching performance using tricks e.g. State Compression, Branch Pruning, Heuristic.
28 | 
29 | ## References
30 | 
31 | * [https://stackoverflow.com/questions/1857244/what-are-the-differences-between-np-np-complete-and-np-hard](https://stackoverflow.com/questions/1857244/what-are-the-differences-between-np-np-complete-and-np-hard)
32 | * [https://en.wikipedia.org/wiki/NP\_(complexity](https://en.wikipedia.org/wiki/NP\_\(complexity))
33 | * [https://en.wikipedia.org/wiki/NP-completeness](https://en.wikipedia.org/wiki/NP-completeness)
34 | 


--------------------------------------------------------------------------------
/prefix-state-map.md:
--------------------------------------------------------------------------------
 1 | # Prefix State Map
 2 | 
 3 | I haven't found an official name of this kind of problem. I just named it as "Prefix State Map".
 4 | 
 5 | This kind of problem is usually:
 6 | 
 7 | * about finding the longest/shortest subarray which satisfies some condition.
 8 | * the state of the subarray can be deduced using the the states of the prefix array. For example, to get the state of `A[i..j]`, you can use the state of two prefix array, `A[0..(i-1)]` and `A[0..j]`.
 9 | 
10 | ## Algorithm
11 | 
12 | Let `m` be a map from the state `state[i]` of a prefix subarray `A[0..i]` to the index of the first/last occurrence of the state `state[i]`.
13 | 
14 | For the current index `i` and its state `state[i]`, assume we want to get a subarray which ends at `i` and has a `target_state` and has the longest/shortest length.
15 | 
16 | Then we can use `state[i]` and `target_state` to compute a `prefix_state`. `j = m[prefix_state]` is the corresponding index of the prefix array. `A[(j+1) .. i]` is the longest/shortest optimal subarray.
17 | 
18 | ## Pseudo Code
19 | 
20 | ```cpp
21 | int ans = 0; // the length of the optimal subarray
22 | int state = 0; // assume the initial state is 0
23 | unordered_map<int, int> m{{0, -1}}; // let -1 be the index of state `0`.
24 | for (int i = 0; i < A.size(); ++i) {
25 |     state = nextState(state, A[i]); // update state using A[i]
26 |     int prefixState = getPrefixState(state); // based on problem description, we can compute a prefix state using the current state.
27 |     ans = max(ans, i - m[prefixState]); // Use `min` if we are looking for the shortest subarray.
28 |     m[state] = min(m[state], i); // Use `max` if we are looking for the shortest subarray.
29 | }
30 | ```
31 | 
32 | ## Problems
33 | 
34 | * [325. Maximum Size Subarray Sum Equals k (Medium)](https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/)
35 | * [525. Contiguous Array \(Medium\)](https://leetcode.com/problems/contiguous-array/)
36 | * [974. Subarray Sums Divisible by K (Medium)](https://leetcode.com/problems/subarray-sums-divisible-by-k/)
37 | * [1371. Find the Longest Substring Containing Vowels in Even Counts \(Medium\)](https://leetcode.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/)
38 | * [1542. Find Longest Awesome Substring (Hard)](https://leetcode.com/problems/find-longest-awesome-substring/)
39 | * [1590. Make Sum Divisible by P (Medium)](https://leetcode.com/problems/make-sum-divisible-by-p)


--------------------------------------------------------------------------------
/prefix-sum.md:
--------------------------------------------------------------------------------
1 | # Prefix Sum
2 | 
3 | ## One-dimensional
4 | 
5 | ## Two-dimensional
6 | 
7 | * [1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold (Medium)](https://leetcode.com/problems/maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold/)


--------------------------------------------------------------------------------
/random.md:
--------------------------------------------------------------------------------
 1 | # Random
 2 | 
 3 | ## Random Integer
 4 | 
 5 | ```cpp
 6 | int randomInt(int mn, int mx) {
 7 |     return mn + rand() % (mx - mn);
 8 | }
 9 | ```
10 | 
11 | ## Random Double
12 | 
13 | ```cpp
14 | double randomDouble(double mn, double mx) {
15 |     double d = (double)rand() / RAND_MAX;
16 |     return mn + d * (mx - mn);
17 | }
18 | ```
19 | 
20 | ## Problems
21 | 
22 | * [478. Generate Random Point in a Circle (Medium)](https://leetcode.com/problems/generate-random-point-in-a-circle/)
23 | 


--------------------------------------------------------------------------------
/reservoir-sampling.md:
--------------------------------------------------------------------------------
1 | # Reservoir Sampling
2 | 
3 | ## Problems
4 | 
5 | * [382. Linked List Random Node (Medium)](https://leetcode.com/problems/linked-list-random-node/)


--------------------------------------------------------------------------------
/reverse-polish-notation.md:
--------------------------------------------------------------------------------
1 | # Reverse Polish Notation
2 | 
3 | 


--------------------------------------------------------------------------------
/sort/README.md:
--------------------------------------------------------------------------------
1 | # Sort
2 | 
3 | 


--------------------------------------------------------------------------------
/sort/bubble-sort.md:
--------------------------------------------------------------------------------
 1 | # Bubble Sort
 2 | 
 3 | ## Algorithm
 4 | 
 5 | ```cpp
 6 | // OJ: https://leetcode.com/problems/sort-an-array/
 7 | // Author: github.com/lzl124631x
 8 | // Time: O(N^2)
 9 | // Space: O(1)
10 | class Solution {
11 | public:
12 |     vector<int> sortArray(vector<int>& nums) {
13 |         for (int i = 0, N = nums.size(); i < N; ++i) {
14 |             for (int j = N - 1; j > i; --j) {
15 |                 if (nums[j] < nums[j - 1]) swap(nums[j], nums[j - 1]);
16 |             }
17 |         }
18 |         return nums;
19 |     }
20 | };
21 | ```


--------------------------------------------------------------------------------
/sort/cycle-sort.md:
--------------------------------------------------------------------------------
1 | # Cycle Sort
2 | 
3 | ## Problems
4 | 
5 | * [287. Find the Duplicate Number (Medium)](https://leetcode.com/problems/find-the-duplicate-number)
6 | 
7 | ## Reference
8 | 
9 | * https://www.geeksforgeeks.org/cycle-sort/


--------------------------------------------------------------------------------
/sort/heap-sort.md:
--------------------------------------------------------------------------------
 1 | # Heap Sort
 2 | 
 3 | ## Heap Sort
 4 | 
 5 | ## Algorithm
 6 | 
 7 | ```cpp
 8 | // OJ: https://leetcode.com/problems/sort-an-array/
 9 | // Author: github.com/lzl124631x
10 | // Time: O(NlogN)
11 | // Space: O(1)
12 | class Solution {
13 |     void heapify(vector<int> &A) {
14 |         for (int i = A.size() / 2 - 1; i >= 0; --i) { // The parent node with the greatest index is `A[N / 2 - 1]`
15 |             siftDown(A, i, A.size()); // Keep sifting down all the parent nodes from bottom up
16 |         }
17 |     }
18 |     void siftDown(vector<int> &A, int hole, int end) {
19 |         int next = 2 * hole + 1; // `next` is the left child of `hole`
20 |         while (next < end) {
21 |             if (next + 1 < end && A[next + 1] > A[next]) ++next; // if the right child is greater than left child, use right child instead.
22 |             if (A[hole] > A[next]) break; // if the parent node is already greater than its greatest child, we don't need to sift it down.
23 |             swap(A[hole], A[next]); // otherwise, keep sifting it down until the parent node `hole` doesn't have any child, i.e. `next >= end`
24 |             hole = next;
25 |             next = 2 * hole + 1;
26 |         }
27 |     }
28 | public:
29 |     vector<int> sortArray(vector<int>& A) {
30 |         heapify(A); // max heap. Heap top at `A[0]`
31 |         for (int i = A.size() - 1; i > 0; --i) {
32 |             swap(A[0], A[i]); // keep swapping heap top to the tail of the heap
33 |             siftDown(A, 0, i); // For the new `A[0]`, sift it down.
34 |         }
35 |         return A;
36 |     }
37 | };
38 | ```
39 | 


--------------------------------------------------------------------------------
/sort/merge-sort.md:
--------------------------------------------------------------------------------
 1 | # Merge Sort
 2 | 
 3 | ## Algorithm
 4 | 
 5 | ```cpp
 6 | // OJ: https://leetcode.com/problems/sort-an-array/
 7 | // Author: github.com/lzl124631x
 8 | // Time: O(NlogN)
 9 | // Space: O(N)
10 | class Solution {
11 |     vector<int> tmp;
12 |     void mergeSort(vector<int> &A, int begin, int end) {
13 |         if (begin + 1 >= end) return;
14 |         int mid = (begin + end) / 2, i = begin, j = mid, k = begin;
15 |         mergeSort(A, begin, mid);
16 |         mergeSort(A, mid, end);
17 |         while (i < mid || j < end) {
18 |             if (j >= end || (i < mid && A[i] < A[j])) tmp[k++] = A[i++];
19 |             else tmp[k++] = A[j++];
20 |         }
21 |         for (i = begin; i < end; ++i) A[i] = tmp[i];
22 |     }
23 | public:
24 |     vector<int> sortArray(vector<int>& A) {
25 |         tmp.assign(A.size(), 0);
26 |         mergeSort(A, 0, A.size());
27 |         return A;
28 |     }
29 | };
30 | ```


--------------------------------------------------------------------------------
/sort/quick-sort.md:
--------------------------------------------------------------------------------
  1 | # Quick Sort
  2 | 
  3 | Core algorithm
  4 | * `M = partition(L, R)`
  5 | * `quickSort(L, M - 1)`
  6 | * `quickSort(M + 1, R)`
  7 | 
  8 | ## Why do we need to randomly select a pivot?
  9 | 
 10 | The performance of quick sort is highly dependent on the selection of the pivot element.
 11 | 
 12 | Imagine we want to sort `A = [5,2,3,1,4]`.
 13 | 
 14 | If we always choose a bad pivot element, we can only reduce the scale by one each time. The time complexity degrades to `O(N^2)`.
 15 | 
 16 | ```
 17 | pivot = 1, A = [(1),5,2,3,4]
 18 | pivot = 2, A = [(1,2),5,3,4]
 19 | pivot = 3, A = [(1,2,3),5,4]
 20 | pivot = 4, A = [(1,2,3,4,5)]
 21 | ```
 22 | 
 23 | If we always choose a good pivot element, we reduce the scale exponentially. The time complexity is `O(NlogN)`.
 24 | 
 25 | ```
 26 | pivot = 2, A = [2,1,(3),5,4]
 27 | pivot = 1, A = [(1,2,3),5,4]
 28 | pivot = 4, A = [(1,2,3,4,5)]
 29 | ```
 30 | 
 31 | As you can see, Quick Select performs better if we can approximately partition around the median.
 32 | 
 33 | ## Algorithm
 34 | 
 35 | **Lomuto's partition**:
 36 | * Easy to implement
 37 | * Less efficient than Hoare's partition.
 38 | 
 39 | The logic is very similar to [283. Move Zeroes (Easy)](https://leetcode.com/problems/move-zeroes/).
 40 | 
 41 | ```cpp
 42 | // OJ: https://leetcode.com/problems/sort-an-array/
 43 | // Author: github.com/lzl124631x
 44 | // Time: O(NlogN) on average, O(N^2) in the worst case
 45 | // Space: O(logN) on average, O(N) in the worst case
 46 | class Solution {
 47 |     int partition(vector<int> &A, int L, int R, int pivot) {
 48 |         swap(A[pivot], A[R]);
 49 |         for (int i = L; i < R; ++i) { // `i` is the read pointer, `L` is the write pointer. The scanned range doesn't include the pivot, A[R]
 50 |             if (A[i] >= A[R]) continue; // we are looking for numbers < A[R]. So skipping those `>= A[R]`.
 51 |             swap(A[i], A[L++]); // once found, swap it to `A[L]` and move `L` forward.
 52 |         }
 53 |         swap(A[L], A[R]); // swap the pivot value to `A[L]`.
 54 |         return L;
 55 |     }
 56 |     void quickSort(vector<int> &A, int L, int R) {
 57 |         if (L >= R) return;
 58 |         int M = partition(A, L, R, rand() % (R - L + 1) + L);
 59 |         quickSort(A, L, M - 1);
 60 |         quickSort(A, M + 1, R);
 61 |     }
 62 | public:
 63 |     vector<int> sortArray(vector<int>& A) {
 64 |         srand(NULL);
 65 |         quickSort(A, 0, A.size() - 1);
 66 |         return A;
 67 |     }
 68 | };
 69 | ```
 70 | 
 71 | Or
 72 | 
 73 | **Hoare's partition**:
 74 | * Trickier to implement
 75 | * More efficient than Lomuto's partition because it does **three** times fewer swaps on average, and it creates efficient partitions even when all values are equal.
 76 | 
 77 | ```cpp
 78 | // OJ: https://leetcode.com/problems/sort-an-array/
 79 | // Author: github.com/lzl124631x
 80 | // Time: O(NlogN) on average, O(N^2) in the worst case
 81 | // Space: O(logN) on average, O(N) in the worst case
 82 | class Solution {
 83 | private:
 84 |     int partition(vector<int> &A, int L, int R, int pivot) {
 85 |         swap(A[pivot], A[R]);
 86 |         int i = L, j = R; // the initial range covers the pivot A[R]
 87 |         while (i < j) {
 88 |             while (i < j && A[i] < A[R]) ++i; // we must start from the other side of the pivot. Since we use A[R] as pivot, we need to start from the left side.
 89 |             while (i < j && A[j] >= A[R]) --j;
 90 |             swap(A[i], A[j]);
 91 |         }
 92 |         swap(A[i], A[R]);
 93 |         return i;
 94 |     }
 95 |     void quickSort(vector<int> &A, int L, int R) {
 96 |         if (L >= R) return;
 97 |         int M = partition(A, L, R, rand() % (R - L + 1) + L);
 98 |         quickSort(A, L, M - 1);
 99 |         quickSort(A, M + 1, R);
100 |     }
101 | public:
102 |     vector<int> sortArray(vector<int>& A) {
103 |         srand (time(NULL));
104 |         quickSort(A, 0, A.size() - 1);
105 |         return A;
106 |     }
107 | };
108 | ```
109 | 
110 | ## Bentley-McIlroy 3-way parititioning
111 | 
112 | TODO
113 | 
114 | 
115 | ## Reference
116 | 
117 | * https://sedgewick.io/wp-content/themes/sedgewick/talks/2002QuicksortIsOptimal.pdf


--------------------------------------------------------------------------------
/sort/sorting.md:
--------------------------------------------------------------------------------
 1 | # Sorting
 2 | 
 3 | <figure><img src="../.gitbook/assets/image (3).png" alt=""><figcaption></figcaption></figure>
 4 | 
 5 | Which algorithm works best for largely sorted array?
 6 | 
 7 | * Insertion Sort
 8 | * Bubble Sort
 9 | 
10 | [https://stackoverflow.com/a/4276118/3127828](https://stackoverflow.com/a/4276118/3127828)
11 | 
12 | Only a few items => INSERTION SORT
13 | 
14 | Items are mostly sorted already => INSERTION SORT
15 | 
16 | Concerned about worst-case scenarios => HEAP SORT
17 | 
18 | Interested in a good average-case result => QUICKSORT
19 | 
20 | Items are drawn from a dense universe => BUCKET SORT
21 | 
22 | Desire to write as little code as possible => INSERTION SORT
23 | 


--------------------------------------------------------------------------------
/sqrt-decomposition.md:
--------------------------------------------------------------------------------
1 | # Sqrt Decomposition
2 | 
3 | Break the input into batches, each of which is of scale `O(sqrt(N))` and handle each batch individually.
4 | 
5 | ## Problems
6 | 
7 | * [307. Range Sum Query - Mutable \(Medium\)](https://leetcode.com/problems/range-sum-query-mutable/)
8 | * [1265. Print Immutable Linked List in Reverse (Medium)](https://leetcode.com/problems/print-immutable-linked-list-in-reverse/)
9 | 


--------------------------------------------------------------------------------
/stl/README.md:
--------------------------------------------------------------------------------
1 | # Stl
2 | 
3 | 


--------------------------------------------------------------------------------
/stl/istringstream.md:
--------------------------------------------------------------------------------
 1 | # istringstream
 2 | 
 3 | ## Read string with a special delimiter
 4 | 
 5 | ```cpp
 6 | istream& getline (istream& is, string& str, char delim);
 7 | ```
 8 | 
 9 | By default `delim` is `\n`. See [more](http://www.cplusplus.com/reference/string/string/getline/).
10 | 
11 | Take [165. Compare Version Numbers (Medium)](https://leetcode.com/problems/compare-version-numbers/) for example, we can read the string segment using:
12 | 
13 | ```cpp
14 | getline(version1, segment, '.')
15 | ```
16 | 
17 | ## Detect EOF
18 | 
19 | ```cpp
20 | iss.eof(); // returns true if it has reached EOF.
21 | iss.good(); // returns true if none of the error state flags (eofbit, failbit and badbit) is set.
22 | ```


--------------------------------------------------------------------------------
/stl/lower_bound-upper_bound.md:
--------------------------------------------------------------------------------
  1 | # lower_bound and upper_bound
  2 | 
  3 | ## lower_bound + comparator
  4 | 
  5 | ```cpp
  6 | struct Item {
  7 |     int start, end;
  8 |     string string() { return "(" + to_string(start) + "," + to_string(end) + ")"; }
  9 | };
 10 | int main() {
 11 |     /*
 12 |     <=
 13 |     0   F F F F => A[0] = (10,60)        
 14 |     20  T T F F => A[2] = (30,35)
 15 |     40  T T T T => not found
 16 |     50  T T T T => not found
 17 | 
 18 |     <
 19 |     0   F F F F => A[0] = (10,60)        
 20 |     20  T F F F => A[1] = (20,40)
 21 |     40  T T T F => A[3] = (40,50)
 22 |     50  T T T T => not found
 23 | 
 24 |     >=  (Note that we shouldn't use this operator because this comparator doesn't split the array into TRUE then FALSE parts)
 25 |     0   T T T T => not found
 26 |     20  F T T T => not found
 27 |     40  F F F T => A[0] = (10,60)
 28 |     50  F F F F => A[0] = (10,60)
 29 |     */
 30 |     vector<Item> A = {{10,60},{20,40},{30,35},{40,50}};
 31 |     for (int target : {0, 20, 40, 50}) {
 32 |         int j = lower_bound(begin(A), end(A), target, [](auto &val, int target) {
 33 |             cout << "comparing " << val.string() << " and " << target << endl;
 34 |             return val.start >= target; // change this operator to see the above results
 35 |         }) - begin(A);
 36 |         cout << target << " => ";
 37 |         if (j == A.size()) {
 38 |             cout << "NOT FOUND" << endl;
 39 |         } else {
 40 |             cout << "A[" << j << "] = " << A[j].string() << endl;
 41 |         }
 42 |     }
 43 | }
 44 | ```
 45 | 
 46 | **Summary**:
 47 | 
 48 | * `comparator` is in form `(element, target)`.
 49 | * The comparator returns `true` if the first argument (`element`) is ordered **before** the second argument (`target`). It separates the array into `TRUE` segment followed by `FALSE` segment.
 50 | * `lower_bound` returns the first element returning `false`.
 51 | 
 52 | ```
 53 |                  ┌-- the returned index
 54 |                  |
 55 |       true       v         false
 56 | [--------------] [----------------------]
 57 | ```
 58 | 
 59 | ## upper_bound + comparator
 60 | 
 61 | ```cpp
 62 | struct Item {
 63 |     int start, end;
 64 |     string string() { return "(" + to_string(start) + "," + to_string(end) + ")"; }
 65 | };
 66 | int main() {
 67 |     /*
 68 |     <=
 69 |     0   T T T T => A[0] = (10,60)        
 70 |     20  F T T T => A[1] = (20,40)
 71 |     40  F F F T => A[3] = (40,50)
 72 |     50  F F F F => not found
 73 | 
 74 |     <
 75 |     0   T T T T => A[0] = (10,60)        
 76 |     20  F F T T => A[2] = (30,35)
 77 |     40  F F F F => not found
 78 |     50  F F F F => not found
 79 | 
 80 |     >= (Note that we shouldn't use this operator because this comparator doesn't split the array into FALSE then TRUE parts)
 81 |     0   F F F F => not found
 82 |     20  T T F F => not found
 83 |     40  T T T T => A[0] = (10,60)
 84 |     50  T T T T => A[0] = (10,60)
 85 |     */
 86 |     vector<Item> A = {{10,60},{20,40},{30,35},{40,50}};
 87 |     for (int target : {0, 20, 40, 50}) {
 88 |         int j = upper_bound(begin(A), end(A), target, [](int target, auto &val) {
 89 |             cout << "comparing " << val.string() << " and " << target << endl;
 90 |             return target >= val.start;
 91 |         }) - begin(A);
 92 |         cout << target << " => ";
 93 |         if (j == A.size()) {
 94 |             cout << "NOT FOUND" << endl;
 95 |         } else {
 96 |             cout << "A[" << j << "] = " << A[j].string() << endl;
 97 |         }
 98 |     }
 99 | }
100 | ```
101 | **Summary**
102 | 
103 | * `comparator` is in form `(target, element)`.
104 | * The comparator returns `true` if the first argument (`target`) is ordered **before** the second argument (`element`). It separates the array into `FALSE` segment followed by `TRUE` segment.
105 | * `upper_bound` returns the first element returning `TRUE`.
106 | 
107 | ```
108 |                  ┌-- the returned index
109 |                  |
110 |       false      v        true 
111 | [--------------] [----------------------]
112 | ```
113 | 
114 | # Problems
115 | 
116 | * [1751. Maximum Number of Events That Can Be Attended II (Hard)](https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended-ii/)


--------------------------------------------------------------------------------
/stl/priority_queue.md:
--------------------------------------------------------------------------------
  1 | # Priority Queue
  2 | 
  3 | By default:
  4 | 
  5 | * `priority_queue` is a **Max-heap**. The element with the highest priority is at the top.
  6 | * `priority_queue` uses `less` as comparator. \(In fact, STL always use `less` as the default comparator whenever it needs comparison.\)
  7 | 
  8 | If you want to get a Min-heap, use `priority_queue<int, vector<int>, greater<int>>`.
  9 | 
 10 | It uses `make_heap`, `push_heap` and `pop_heap` algorithm functions under the hood.
 11 | 
 12 | ## Why is it Max-heap by default?
 13 | 
 14 | > The elements are compared using operator`<` \(by default\), or `comp` \(custom comparator\): The element with the highest value is an element for which this would return `false` when compared to every other element in the range.
 15 | 
 16 | [http://www.cplusplus.com/reference/algorithm/make\_heap](http://www.cplusplus.com/reference/algorithm/make_heap)
 17 | 
 18 | In priority queue, the element with the highest priority is the one which gets `false` when comparing with every other element using the comparator. The comparator is by default `less`. So the element that is not less than any other elements, i.e. the largest one, is at the top.
 19 | 
 20 | ```text
 21 |            front                           back 
 22 |              v                               v
 23 | vector: [   10,              ...             2  ]
 24 |              ^
 25 |           heap top
 26 | ```
 27 | 
 28 | After poping the top
 29 | 
 30 | ```text
 31 |            front                        back     popped element
 32 |              v                           v              v
 33 | vector: [    8,              ...         2  ]        [ 10 ]
 34 |              ^
 35 |           heap top
 36 | ```
 37 | 
 38 | ## Related functions
 39 | 
 40 | Note: try to solve [215. Kth Largest Element in an Array \(Medium\)](https://leetcode.com/problems/kth-largest-element-in-an-array/) using the following functions.
 41 | 
 42 | ### `make_heap`
 43 | 
 44 | Rearranges the elements in the range `[first,last)` in such a way that they form a _heap_.
 45 | 
 46 | The element with the highest value is always pointed by _first_.
 47 | 
 48 | ```cpp
 49 | // range heap example
 50 | #include <iostream>     // std::cout
 51 | #include <algorithm>    // std::make_heap, std::pop_heap, std::push_heap, std::sort_heap
 52 | #include <vector>       // std::vector
 53 | 
 54 | int main () {
 55 |     int myints[] = {10,20,30,5,15};
 56 |     std::vector<int> v(myints,myints+5);
 57 | 
 58 |     std::make_heap (v.begin(),v.end());
 59 |     std::cout << "initial max heap   : " << v.front() << '\n';
 60 | 
 61 |     std::pop_heap (v.begin(),v.end()); v.pop_back();
 62 |     std::cout << "max heap after pop : " << v.front() << '\n';
 63 | 
 64 |     v.push_back(99); std::push_heap (v.begin(),v.end());
 65 |     std::cout << "max heap after push: " << v.front() << '\n';
 66 | 
 67 |     std::sort_heap (v.begin(),v.end());
 68 | 
 69 |     std::cout << "final sorted range :";
 70 |     for (unsigned i=0; i<v.size(); i++)
 71 |         std::cout << ' ' << v[i];
 72 | 
 73 |     std::cout << '\n';
 74 | 
 75 |     return 0;
 76 | }
 77 | ```
 78 | 
 79 | Output:
 80 | 
 81 | ```text
 82 | initial max heap   : 30
 83 | max heap after pop : 20
 84 | max heap after push: 99
 85 | final sorted range : 5 10 15 20 99
 86 | ```
 87 | 
 88 | ### `push_heap`
 89 | 
 90 | Given a heap in the range `[first,last-1)`, this function extends the range considered a heap to `[first,last)` by placing the value in `(last-1)` into its corresponding location within it.
 91 | 
 92 | ### `pop_heap`
 93 | 
 94 | Rearranges the elements in the heap range `[first,last)` in such a way that the part considered a heap is shortened by one: The element with the highest value is moved to `(last-1)`.
 95 | 
 96 | ### `sort_heap`
 97 | 
 98 | Sorts the elements in the heap range `[first,last)` into ascending order.
 99 | 
100 | The range loses its properties as a heap.
101 | 
102 | ## Custom Comparator
103 | 
104 | ```cpp
105 | // Assume there is a `m` variable in the context and `m[a]` is the frequency of `a`
106 | // In following code, the element with the highest frequency is the root.
107 | auto cmp = [&](int a, int b) { return m[a] < m[b]; };
108 | priority_queue<int, vector<int>, decltype(cmp)> q(cmp);
109 | ```
110 | 
111 | Another way
112 | 
113 | ```cpp
114 | class Cmp {
115 | public:
116 |     bool operator() (const pair<int, int>& a, const pair<int, int>& b) const {
117 |         return a.second < b.second;
118 |     }
119 | };
120 | 
121 | priority_queue<pair<int, int>, vector<pair<int, int>>, Cmp> q(m.begin(), m.end()); // Assume there is an `m` storing pairs of `value, frequency`.
122 | ```


--------------------------------------------------------------------------------
/string/README.md:
--------------------------------------------------------------------------------
1 | # String
2 | 
3 | 


--------------------------------------------------------------------------------
/string/kmp.md:
--------------------------------------------------------------------------------
  1 | # KMP
  2 | 
  3 | KMP \(Knuth-Morris-Pratt\) algorithm is a substring search algorithm.
  4 | 
  5 | LPS: Longest proper Prefix which is also Suffix. For example, `"abcdeabc"` has the LPS `"abc"`. Note that the string itself can't be an LPS of itself.
  6 | 
  7 | ## Algorithm
  8 | 
  9 | 1. Generate the LPS array.
 10 | 2. Take advantage of the LPS array so that once we find a mismatch, we can efficiently jump to an earlier point and continue searching.
 11 | 
 12 | For the pattern string `t` we are searching, the `lps` array is of the same length as `t`. `lps[i]` is the length of LPS of `t[0..i]`.
 13 | 
 14 | Example:
 15 | 
 16 | ```
 17 | t   = a b a b x a b a b x g
 18 | lps = 0 0 1 2 0 1 2 3 4 5 0
 19 | ```
 20 | 
 21 | ## Implementation
 22 | 
 23 | ```cpp
 24 | // OJ: https://leetcode.com/problems/implement-strstr/
 25 | // Author: github.com/lzl124631x
 26 | // Time: O(M+N)
 27 | // Space: O(N)
 28 | class Solution {
 29 |     vector<int> getLps(string &s) {
 30 |         int N = s.size(), i = 0;
 31 |         vector<int> lps(N); // lps[0] is always 0
 32 |         for (int j = 1; j < N; ++j) {
 33 |             while (i > 0 && s[i] != s[j]) i = lps[i - 1]; // when s[i] can't match s[j], keep moving `i` backwards to `lps[i-1]`
 34 |             i += s[i] == s[j]; // Move `i` if s[j] matches s[i]
 35 |             lps[j] = i; // Assign the matched length to lps[j]
 36 |         }
 37 |         return lps;
 38 |     }
 39 | public:
 40 |     int strStr(string s, string t) {
 41 |         if (t.empty()) return 0;
 42 |         int M = s.size(), N = t.size(), i = 0, j = 0;
 43 |         auto lps = getLps(t);
 44 |         while (i < M) {
 45 |             if (s[i] == t[j]) { // if match, move i and j once
 46 |                 ++i;
 47 |                 ++j;
 48 |                 if (j == N) return i - N; // Full match found. 
 49 |             } else {
 50 |                 if (j) j = lps[j - 1]; // The first lps[j-1] charaters are already matched. Start the next match from lps[j-1]
 51 |                 else ++i; // The first character is not matched, move i.
 52 |             }
 53 |         }
 54 |         return -1;
 55 |     }
 56 | };
 57 | ```
 58 | 
 59 | ## Problems
 60 | 
 61 | * [28. Implement strStr\(\) \(Easy\)](https://leetcode.com/problems/implement-strstr/)
 62 | * [214. Shortest Palindrome \(Hard\)](https://leetcode.com/problems/shortest-palindrome/)
 63 | * [1392. Longest Happy Prefix \(Hard\)](https://leetcode.com/problems/longest-happy-prefix/)
 64 | * [459. Repeated Substring Pattern (Easy)](https://leetcode.com/problems/repeated-substring-pattern/)
 65 | 
 66 | 
 67 | ## KMP Count
 68 | 
 69 | Count the occurrence of `t` in string `s`.
 70 | 
 71 | ```cpp
 72 | // OJ: https://leetcode.com/problems/number-of-subarrays-that-match-a-pattern-ii
 73 | // Author: github.com/lzl124631x
 74 | // Time: O(M + N)
 75 | // Space: O(M + N)
 76 | class Solution {
 77 |     vector<int> getLps(string &s) {
 78 |         int N = s.size(), i = 0;
 79 |         vector<int> lps(N); // lps[0] is always 0
 80 |         for (int j = 1; j < N; ++j) {
 81 |             while (i > 0 && s[i] != s[j]) i = lps[i - 1]; // when s[i] can't match s[j], keep moving `i` backwards to `lps[i-1]`
 82 |             i += s[i] == s[j]; // Move `i` if s[j] matches s[i]
 83 |             lps[j] = i; // Assign the matched length to lps[j]
 84 |         }
 85 |         return lps;
 86 |     }
 87 |     int KMPCount(string s, string t) {
 88 |         if (t.empty()) return 0;
 89 |         int M = s.size(), N = t.size(), i = 0, j = 0, ans = 0;
 90 |         auto lps = getLps(t);
 91 |         while (i < M) {
 92 |             if (s[i] == t[j]) {
 93 |                 ++i;
 94 |                 ++j;
 95 |                 if (j == N) {
 96 |                     ++ans;
 97 |                     j = lps[j - 1]; // Full match found. Move `j` back to `lps[j-1]` to skip matched prefix
 98 |                 }
 99 |             } else {
100 |                 if (j) j = lps[j - 1];
101 |                 else ++i;
102 |             }
103 |         }
104 |         return ans;
105 |     }
106 | public:
107 |     int countMatchingSubarrays(vector<int>& A, vector<int>& P) {
108 |         int N = A.size(), M = P.size();
109 |         string s, p;
110 |         for (int i = 1; i < N; ++i) {
111 |             s.push_back(A[i] > A[i - 1] ? 'a' : (A[i] == A[i - 1] ? 'b' : 'c'));
112 |         }
113 |         for (auto &n : P) {
114 |             p.push_back(n == 1 ? 'a' : (n == 0 ? 'b' : 'c'));
115 |         }
116 |         return KMPCount(s, p);
117 |     }
118 | };
119 | ```
120 | 
121 | ## Problems
122 | * [3036. Number of Subarrays That Match a Pattern II (Hard)](https://leetcode.com/problems/number-of-subarrays-that-match-a-pattern-ii)
123 | 
124 | ## Reference
125 | 
126 | * [https://youtu.be/GTJr8OvyEVQ](https://youtu.be/GTJr8OvyEVQ)
127 | * [https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/](https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/)
128 | 
129 | 


--------------------------------------------------------------------------------
/string/string-processing.md:
--------------------------------------------------------------------------------
1 | # String Processing
2 | 
3 | ## Problems
4 | 
5 | * [1096. Brace Expansion II \(Hard\)](https://leetcode.com/problems/brace-expansion-ii/)
6 | * [1106. Parsing A Boolean Expression \(Hard\)](https://leetcode.com/problems/parsing-a-boolean-expression/)
7 | 
8 | 


--------------------------------------------------------------------------------
/string/z.md:
--------------------------------------------------------------------------------
1 | # Z
2 | 
3 | ## Reference
4 | 
5 | * [KMP Algorithm VS Z Algorithm](https://kaizhang.me/note/2019/01/kmp-vs-z-algorithm/)
6 | 
7 | 


--------------------------------------------------------------------------------
/summary.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # npm install -g gitbook-summary
3 | book sm -t "Algorithm"


--------------------------------------------------------------------------------