From 5f816331b26c69b035d48da51be3b6712212cb72 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Wed, 11 Dec 2024 00:40:43 +0530 Subject: [PATCH] Batch-3/Neetcode-All/Added-articles --- articles/buy-and-sell-crypto-with-cooldown.md | 6 +- articles/champagne-tower.md | 562 +++++++++++++++++ ...ing-contains-all-binary-codes-of-size-k.md | 497 +++++++++++++++ articles/contiguous-array.md | 341 ++++++++++ ...n-array-into-a-2d-array-with-conditions.md | 317 ++++++++++ ...e-array-into-arrays-with-max-difference.md | 238 +++++++ articles/encode-and-decode-tinyurl.md | 312 +++++++++ articles/find-the-difference-of-two-arrays.md | 467 ++++++++++++++ articles/first-missing-positive.md | 536 ++++++++++++++++ articles/insert-delete-getrandom-o1.md | 300 +++++++++ articles/majority-element-ii.md | 597 ++++++++++++++++++ ...umber-of-operations-to-make-array-empty.md | 563 +++++++++++++++++ articles/minimum-penalty-for-a-shop.md | 497 +++++++++++++++ articles/non-decreasing-array.md | 105 +++ articles/number-of-zero-filled-subarrays.md | 338 ++++++++++ articles/optimal-partition-of-string.md | 250 ++++++++ articles/range-sum-query-2d-immutable.md | 369 +++++++++++ articles/repeated-dna-sequences.md | 470 ++++++++++++++ articles/sign-of-the-product-of-an-array.md | 158 +++++ articles/sort-an-array.md | 2 +- articles/sort-characters-by-frequency.md | 340 ++++++++++ ...-absolute-differences-in-a-sorted-array.md | 430 +++++++++++++ articles/wiggle-sort.md | 293 +++++++++ 23 files changed, 7982 insertions(+), 6 deletions(-) create mode 100644 articles/champagne-tower.md create mode 100644 articles/check-if-a-string-contains-all-binary-codes-of-size-k.md create mode 100644 articles/contiguous-array.md create mode 100644 articles/convert-an-array-into-a-2d-array-with-conditions.md create mode 100644 articles/divide-array-into-arrays-with-max-difference.md create mode 100644 articles/encode-and-decode-tinyurl.md create mode 100644 articles/find-the-difference-of-two-arrays.md create mode 100644 articles/first-missing-positive.md create mode 100644 articles/insert-delete-getrandom-o1.md create mode 100644 articles/majority-element-ii.md create mode 100644 articles/minimum-number-of-operations-to-make-array-empty.md create mode 100644 articles/minimum-penalty-for-a-shop.md create mode 100644 articles/non-decreasing-array.md create mode 100644 articles/number-of-zero-filled-subarrays.md create mode 100644 articles/optimal-partition-of-string.md create mode 100644 articles/range-sum-query-2d-immutable.md create mode 100644 articles/repeated-dna-sequences.md create mode 100644 articles/sign-of-the-product-of-an-array.md create mode 100644 articles/sort-characters-by-frequency.md create mode 100644 articles/sum-of-absolute-differences-in-a-sorted-array.md create mode 100644 articles/wiggle-sort.md diff --git a/articles/buy-and-sell-crypto-with-cooldown.md b/articles/buy-and-sell-crypto-with-cooldown.md index 3c4ff367b..366028454 100644 --- a/articles/buy-and-sell-crypto-with-cooldown.md +++ b/articles/buy-and-sell-crypto-with-cooldown.md @@ -634,7 +634,7 @@ class Solution: for i in range(n - 1, -1, -1): dp_buy = max(dp1_sell - prices[i], dp1_buy) dp_sell = max(dp2_buy + prices[i], dp1_sell) - dp2_buy, dp1_sell = dp1_buy, dp1_sell + dp2_buy = dp1_buy dp1_buy, dp1_sell = dp_buy, dp_sell return dp1_buy @@ -651,7 +651,6 @@ public class Solution { int dp_buy = Math.max(dp1_sell - prices[i], dp1_buy); int dp_sell = Math.max(dp2_buy + prices[i], dp1_sell); dp2_buy = dp1_buy; - dp1_sell = dp1_sell; dp1_buy = dp_buy; dp1_sell = dp_sell; } @@ -673,7 +672,6 @@ public: int dp_buy = max(dp1_sell - prices[i], dp1_buy); int dp_sell = max(dp2_buy + prices[i], dp1_sell); dp2_buy = dp1_buy; - dp1_sell = dp1_sell; dp1_buy = dp_buy; dp1_sell = dp_sell; } @@ -698,7 +696,6 @@ class Solution { let dp_buy = Math.max(dp1_sell - prices[i], dp1_buy); let dp_sell = Math.max(dp2_buy + prices[i], dp1_sell); dp2_buy = dp1_buy; - dp1_sell = dp1_sell; dp1_buy = dp_buy; dp1_sell = dp_sell; } @@ -719,7 +716,6 @@ public class Solution { int dp_buy = Math.Max(dp1_sell - prices[i], dp1_buy); int dp_sell = Math.Max(dp2_buy + prices[i], dp1_sell); dp2_buy = dp1_buy; - dp1_sell = dp1_sell; dp1_buy = dp_buy; dp1_sell = dp_sell; } diff --git a/articles/champagne-tower.md b/articles/champagne-tower.md new file mode 100644 index 000000000..d2f36a28e --- /dev/null +++ b/articles/champagne-tower.md @@ -0,0 +1,562 @@ +## 1. Recursion + +::tabs-start + +```python +class Solution: + def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float: + def rec(row, glass): + if row < 0 or glass < 0 or glass > row: + return 0 + + if row == 0 and glass == 0: + return poured + + left_parent = max(0, rec(row - 1, glass - 1) - 1) + right_parent = max(0, rec(row - 1, glass) - 1) + + return (left_parent + right_parent) / 2 + + return min(1, rec(query_row, query_glass)) +``` + +```java +public class Solution { + public double champagneTower(int poured, int query_row, int query_glass) { + return Math.min(1, rec(poured, query_row, query_glass)); + } + + private double rec(int poured, int row, int glass) { + if (row < 0 || glass < 0 || glass > row) { + return 0; + } + + if (row == 0 && glass == 0) { + return poured; + } + + double leftParent = Math.max(0, rec(poured, row - 1, glass - 1) - 1); + double rightParent = Math.max(0, rec(poured, row - 1, glass) - 1); + + return (leftParent + rightParent) / 2; + } +} +``` + +```cpp +class Solution { +public: + double champagneTower(int poured, int query_row, int query_glass) { + return min(1.0, rec(poured, query_row, query_glass)); + } + +private: + double rec(int poured, int row, int glass) { + if (row < 0 || glass < 0 || glass > row) { + return 0; + } + + if (row == 0 && glass == 0) { + return poured; + } + + double leftParent = max(0.0, rec(poured, row - 1, glass - 1) - 1); + double rightParent = max(0.0, rec(poured, row - 1, glass) - 1); + + return (leftParent + rightParent) / 2; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} poured + * @param {number} query_row + * @param {number} query_glass + * @return {number} + */ + champagneTower(poured, query_row, query_glass) { + const rec = (row, glass) => { + if (row < 0 || glass < 0 || glass > row) { + return 0; + } + + if (row === 0 && glass === 0) { + return poured; + } + + const leftParent = Math.max(0, rec(row - 1, glass - 1) - 1); + const rightParent = Math.max(0, rec(row - 1, glass) - 1); + + return (leftParent + rightParent) / 2; + }; + + return Math.min(1, rec(query_row, query_glass)); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(2 ^ n)$ +* Space complexity: $O(n)$ + +> Where $n$ is the given $queryRow$. + +--- + +## 2. Dynamic Programming (Top-Down) + +::tabs-start + +```python +class Solution: + def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float: + memo = { (0, 0) : poured } + + def rec(row, glass): + if row < 0 or glass < 0 or glass > row: + return 0 + if (row, glass) in memo: + return memo[(row, glass)] + + left_parent = max(0, rec(row - 1, glass - 1) - 1) + right_parent = max(0, rec(row - 1, glass) - 1) + + memo[(row, glass)] = (left_parent + right_parent) / 2 + return memo[(row, glass)] + + return min(1, rec(query_row, query_glass)) +``` + +```java +public class Solution { + public double champagneTower(int poured, int query_row, int query_glass) { + double[][] memo = new double[query_row + 5][]; + for (int i = 0; i < query_row + 5; i++) { + memo[i] = new double[i + 1]; + Arrays.fill(memo[i], -1); + } + memo[0][0] = poured; + + return Math.min(1, rec(memo, query_row, query_glass)); + } + + private double rec(double[][] memo, int row, int glass) { + if (row < 0 || glass < 0 || glass > row) { + return 0; + } + + if (memo[row][glass] != -1) { + return memo[row][glass]; + } + + double leftParent = Math.max(0, rec(memo, row - 1, glass - 1) - 1); + double rightParent = Math.max(0, rec(memo, row - 1, glass) - 1); + + memo[row][glass] = (leftParent + rightParent) / 2; + return memo[row][glass]; + } +} +``` + +```cpp +class Solution { +public: + double champagneTower(int poured, int query_row, int query_glass) { + vector> memo(query_row + 5); + for (int i = 0; i <= query_row + 4; i++) { + memo[i].resize(i + 1, -1); + } + + memo[0][0] = poured; + return min(1.0, rec(memo, query_row, query_glass)); + } + +private: + double rec(vector>& memo, int row, int glass) { + if (row < 0 || glass < 0 || glass > row) { + return 0; + } + + if (memo[row][glass] != -1) { + return memo[row][glass]; + } + + double leftParent = max(0.0, rec(memo, row - 1, glass - 1) - 1); + double rightParent = max(0.0, rec(memo, row - 1, glass) - 1); + + memo[row][glass] = (leftParent + rightParent) / 2; + return memo[row][glass]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} poured + * @param {number} query_row + * @param {number} query_glass + * @return {number} + */ + champagneTower(poured, query_row, query_glass) { + const memo = Array.from({ length: query_row + 5 }, (_, i) => Array(i + 1).fill(-1)); + memo[0][0] = poured; + + const rec = (row, glass) => { + if (row < 0 || glass < 0 || glass > row) { + return 0; + } + + if (memo[row][glass] != -1) { + return memo[row][glass]; + } + + const leftParent = Math.max(0, rec(row - 1, glass - 1) - 1); + const rightParent = Math.max(0, rec(row - 1, glass) - 1); + + memo[row][glass] = (leftParent + rightParent) / 2; + return memo[row][glass]; + + return (leftParent + rightParent) / 2; + }; + + return Math.min(1, rec(query_row, query_glass)); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: $O(n * m)$ + +> Where $n$ is the given $queryRow$ and $m$ is the given $queryGlass$. + +--- + +## 3. Dynamic Programming (Bottom-Up) + +::tabs-start + +```python +class Solution: + def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float: + dp = [[0] * (i + 1) for i in range(query_row + 5)] + dp[0][0] += poured + + for row in range(min(99, query_row + 1)): + for glass in range(row + 1): + excess = (dp[row][glass] - 1.0) / 2.0 + if excess > 0: + dp[row + 1][glass] += excess + dp[row + 1][glass + 1] += excess + + return min(1.0, dp[query_row][query_glass]) +``` + +```java +public class Solution { + public double champagneTower(int poured, int query_row, int query_glass) { + double[][] dp = new double[query_row + 5][]; + for (int i = 0; i < query_row + 5; i++) { + dp[i] = new double[i + 1]; + } + + dp[0][0] += poured; + + for (int row = 0; row < Math.min(99, query_row + 1); row++) { + for (int glass = 0; glass <= row; glass++) { + double excess = (dp[row][glass] - 1.0) / 2.0; + if (excess > 0) { + dp[row + 1][glass] += excess; + dp[row + 1][glass + 1] += excess; + } + } + } + + return Math.min(1.0, dp[query_row][query_glass]); + } +} +``` + +```cpp +class Solution { +public: + double champagneTower(int poured, int query_row, int query_glass) { + vector> dp(query_row + 5); + for (int i = 0; i <= query_row + 4; i++) { + dp[i].resize(i + 1, 0); + } + + dp[0][0] += poured; + + for (int row = 0; row < min(99, query_row + 1); row++) { + for (int glass = 0; glass <= row; glass++) { + double excess = (dp[row][glass] - 1.0) / 2.0; + if (excess > 0) { + dp[row + 1][glass] += excess; + dp[row + 1][glass + 1] += excess; + } + } + } + + return min(1.0, dp[query_row][query_glass]); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} poured + * @param {number} query_row + * @param {number} query_glass + * @return {number} + */ + champagneTower(poured, query_row, query_glass) { + const dp = Array.from({ length: query_row + 5 }, (_, i) => Array(i + 1).fill(0)); + dp[0][0] += poured; + + for (let row = 0; row < Math.min(99, query_row + 1); row++) { + for (let glass = 0; glass <= row; glass++) { + const excess = (dp[row][glass] - 1.0) / 2.0; + if (excess > 0) { + dp[row + 1][glass] += excess; + dp[row + 1][glass + 1] += excess; + } + } + } + + return Math.min(1.0, dp[query_row][query_glass]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: $O(n * m)$ + +> Where $n$ is the given $queryRow$ and $m$ is the given $queryGlass$. + +--- + +## 4. Dynamic Programming (Space Optimized) + +::tabs-start + +```python +class Solution: + def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float: + prev_row = [poured] # Flow + + for row in range(1, query_row + 1): + cur_row = [0] * (row + 1) + for i in range(row): + extra = prev_row[i] - 1 + if extra > 0: + cur_row[i] += 0.5 * extra + cur_row[i + 1] += 0.5 * extra + prev_row = cur_row + + return min(1, prev_row[query_glass]) +``` + +```java +public class Solution { + public double champagneTower(int poured, int query_row, int query_glass) { + double[] prev_row = new double[] { poured }; // Flow + + for (int row = 1; row <= query_row; row++) { + double[] cur_row = new double[row + 1]; + for (int i = 0; i < row; i++) { + double extra = prev_row[i] - 1; + if (extra > 0) { + cur_row[i] += 0.5 * extra; + cur_row[i + 1] += 0.5 * extra; + } + } + prev_row = cur_row; + } + + return Math.min(1.0, prev_row[query_glass]); + } +} +``` + +```cpp +class Solution { +public: + double champagneTower(int poured, int query_row, int query_glass) { + vector prev_row = {double(poured)}; // Flow + + for (int row = 1; row <= query_row; row++) { + vector cur_row(row + 1, 0); + for (int i = 0; i < row; i++) { + double extra = prev_row[i] - 1; + if (extra > 0) { + cur_row[i] += 0.5 * extra; + cur_row[i + 1] += 0.5 * extra; + } + } + prev_row = cur_row; + } + + return min(1.0, prev_row[query_glass]); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} poured + * @param {number} query_row + * @param {number} query_glass + * @return {number} + */ + champagneTower(poured, query_row, query_glass) { + let prev_row = [poured]; // Flow + + for (let row = 1; row <= query_row; row++) { + let cur_row = new Array(row + 1).fill(0); + for (let i = 0; i < row; i++) { + let extra = prev_row[i] - 1; + if (extra > 0) { + cur_row[i] += 0.5 * extra; + cur_row[i + 1] += 0.5 * extra; + } + } + prev_row = cur_row; + } + + return Math.min(1, prev_row[query_glass]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: $O(n)$ + +> Where $n$ is the given $queryRow$ and $m$ is the given $queryGlass$. + +--- + +## 5. Dynamic Programming (Optimal) + +::tabs-start + +```python +class Solution: + def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float: + dp = [poured] + [0] * query_row + + for row in range(1, query_row + 1): + for i in range(row - 1, -1, -1): + extra = dp[i] - 1 + if extra > 0: + dp[i] = 0.5 * extra + dp[i + 1] += 0.5 * extra + else: + dp[i] = 0 + + return min(1, dp[query_glass]) +``` + +```java +public class Solution { + public double champagneTower(int poured, int query_row, int query_glass) { + double[] dp = new double[query_row + 1]; + dp[0] = poured; + + for (int row = 1; row <= query_row; row++) { + for (int i = row - 1; i >= 0; i--) { + double extra = dp[i] - 1; + if (extra > 0) { + dp[i] = 0.5 * extra; + dp[i + 1] += 0.5 * extra; + } else { + dp[i] = 0; + } + } + } + + return Math.min(1, dp[query_glass]); + } +} +``` + +```cpp +class Solution { +public: + double champagneTower(int poured, int query_row, int query_glass) { + vector dp(query_row + 1, 0); + dp[0] = poured; + + for (int row = 1; row <= query_row; row++) { + for (int i = row - 1; i >= 0; i--) { + double extra = dp[i] - 1; + if (extra > 0) { + dp[i] = 0.5 * extra; + dp[i + 1] += 0.5 * extra; + } else { + dp[i] = 0; + } + } + } + + return min(1.0, dp[query_glass]); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} poured + * @param {number} query_row + * @param {number} query_glass + * @return {number} + */ + champagneTower(poured, query_row, query_glass) { + let dp = new Array(query_row + 1).fill(0); + dp[0] = poured; + + for (let row = 1; row <= query_row; row++) { + for (let i = row - 1; i >= 0; i--) { + let extra = dp[i] - 1; + if (extra > 0) { + dp[i] = 0.5 * extra; + dp[i + 1] += 0.5 * extra; + } else { + dp[i] = 0; + } + } + } + + return Math.min(1, dp[query_glass]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: $O(n)$ + +> Where $n$ is the given $queryRow$ and $m$ is the given $queryGlass$. \ No newline at end of file diff --git a/articles/check-if-a-string-contains-all-binary-codes-of-size-k.md b/articles/check-if-a-string-contains-all-binary-codes-of-size-k.md new file mode 100644 index 000000000..917412238 --- /dev/null +++ b/articles/check-if-a-string-contains-all-binary-codes-of-size-k.md @@ -0,0 +1,497 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def hasAllCodes(self, s: str, k: int) -> bool: + n = len(s) + if n < (1 << k): + return False + + for num in range(1 << k): + binaryCode = format(num, f'0{k}b') + if binaryCode not in s: + return False + + return True +``` + +```java +public class Solution { + public boolean hasAllCodes(String s, int k) { + int n = s.length(); + if (n < (1 << k)) { + return false; + } + + for (int num = 0; num < (1 << k); num++) { + String binaryCode = String.format("%" + k + "s", Integer.toBinaryString(num)).replace(' ', '0'); + if (!s.contains(binaryCode)) { + return false; + } + } + + return true; + } +} +``` + +```cpp +class Solution { +public: + bool hasAllCodes(string s, int k) { + int n = s.size(); + if (n < (1 << k)) { + return false; + } + + for (int num = 0; num < (1 << k); num++) { + string binaryCode = bitset<20>(num).to_string().substr(20 - k); + if (s.find(binaryCode) == string::npos) { + return false; + } + } + + return true; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @param {number} k + * @return {boolean} + */ + hasAllCodes(s, k) { + const n = s.length; + if (n < (1 << k)) { + return false; + } + + for (let num = 0; num < (1 << k); num++) { + const binaryCode = num.toString(2).padStart(k, '0'); + if (!s.includes(binaryCode)) { + return false; + } + } + + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * 2 ^ k)$ +* Space complexity: $O(k)$ + +> Where $n$ is the length of the string $s$ and $k$ is the length of the binary code. + +--- + +## 2. Hash Set + +::tabs-start + +```python +class Solution: + def hasAllCodes(self, s: str, k: int) -> bool: + if len(s) < 2 ** k: + return False + + codeSet = set() + for i in range(len(s) - k + 1): + codeSet.add(s[i:i + k]) + + return len(codeSet) == 2 ** k +``` + +```java +public class Solution { + public boolean hasAllCodes(String s, int k) { + if (s.length() < (1 << k)) { + return false; + } + + HashSet codeSet = new HashSet<>(); + for (int i = 0; i <= s.length() - k; i++) { + codeSet.add(s.substring(i, i + k)); + } + + return codeSet.size() == (1 << k); + } +} +``` + +```cpp +class Solution { +public: + bool hasAllCodes(std::string s, int k) { + if (s.size() < (1 << k)) { + return false; + } + + std::unordered_set codeSet; + for (int i = 0; i <= s.size() - k; i++) { + codeSet.insert(s.substr(i, k)); + } + + return codeSet.size() == (1 << k); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @param {number} k + * @return {boolean} + */ + hasAllCodes(s, k) { + if (s.length < (1 << k)) { + return false; + } + + const codeSet = new Set(); + for (let i = 0; i <= s.length - k; i++) { + codeSet.add(s.substring(i, i + k)); + } + + return codeSet.size === (1 << k); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * k)$ +* Space complexity: $O(2 ^ k)$ + +> Where $n$ is the length of the string $s$ and $k$ is the length of the binary code. + +--- + +## 3. Sliding Window + +::tabs-start + +```python +class Solution: + def hasAllCodes(self, s: str, k: int) -> bool: + n = len(s) + if n < (1 << k): + return False + + codeSet = [False] * (1 << k) + cur = 0 + i = j = 0 + bit = k - 1 + while j < k: + if s[j] == '1': + cur |= (1 << bit) + bit -= 1 + j += 1 + + have = 1 + codeSet[cur] = True + while j < n: + if s[i] == '1': + cur ^= (1 << (k - 1)) + i += 1 + + cur <<= 1 + if s[j] == '1': + cur |= 1 + j += 1 + + if not codeSet[cur]: + have += 1 + codeSet[cur] = True + + return have == (1 << k) +``` + +```java +public class Solution { + public boolean hasAllCodes(String s, int k) { + int n = s.length(); + if (n < (1 << k)) { + return false; + } + + boolean[] codeSet = new boolean[1 << k]; + int cur = 0; + int i = 0, j = 0, bit = k - 1; + + while (j < k) { + if (s.charAt(j) == '1') { + cur |= (1 << bit); + } + bit--; + j++; + } + + int have = 1; + codeSet[cur] = true; + + while (j < n) { + if (s.charAt(i) == '1') { + cur ^= (1 << (k - 1)); + } + i++; + + cur <<= 1; + if (s.charAt(j) == '1') { + cur |= 1; + } + j++; + + if (!codeSet[cur]) { + have++; + codeSet[cur] = true; + } + } + + return have == (1 << k); + } +} +``` + +```cpp +class Solution { +public: + bool hasAllCodes(string s, int k) { + int n = s.size(); + if (n < (1 << k)) { + return false; + } + + vector codeSet(1 << k, false); + int cur = 0; + int i = 0, j = 0, bit = k - 1; + + while (j < k) { + if (s[j] == '1') { + cur |= (1 << bit); + } + bit--; + j++; + } + + int have = 1; + codeSet[cur] = true; + + while (j < n) { + if (s[i] == '1') { + cur ^= (1 << (k - 1)); + } + i++; + + cur <<= 1; + if (s[j] == '1') { + cur |= 1; + } + j++; + + if (!codeSet[cur]) { + have++; + codeSet[cur] = true; + } + } + + return have == (1 << k); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @param {number} k + * @return {boolean} + */ + hasAllCodes(s, k) { + const n = s.length; + if (n < (1 << k)) { + return false; + } + + const codeSet = new Array(1 << k).fill(false); + let cur = 0; + let i = 0, j = 0, bit = k - 1; + + while (j < k) { + if (s[j] === '1') { + cur |= (1 << bit); + } + bit--; + j++; + } + + let have = 1; + codeSet[cur] = true; + + while (j < n) { + if (s[i] === '1') { + cur ^= (1 << (k - 1)); + } + i++; + + cur <<= 1; + if (s[j] === '1') { + cur |= 1; + } + j++; + + if (!codeSet[cur]) { + have++; + codeSet[cur] = true; + } + } + + return have === (1 << k); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(2 ^ k)$ + +> Where $n$ is the length of the string $s$ and $k$ is the length of the binary code. + +--- + +## 4. Sliding Window (Optimal) + +::tabs-start + +```python +class Solution: + def hasAllCodes(self, s: str, k: int) -> bool: + n = len(s) + if n < (1 << k): + return False + + codeSet = [False] * (1 << k) + cur = 0 + have = 0 + + for i in range(n): + cur = ((cur << 1) & ((1 << k) - 1)) | (ord(s[i]) - ord('0')) + + if i >= k - 1: + if not codeSet[cur]: + codeSet[cur] = True + have += 1 + + return have == (1 << k) +``` + +```java +public class Solution { + public boolean hasAllCodes(String s, int k) { + int n = s.length(); + if (n < (1 << k)) { + return false; + } + + boolean[] codeSet = new boolean[1 << k]; + int cur = 0, have = 0; + + for (int i = 0; i < n; i++) { + cur = ((cur << 1) & ((1 << k) - 1)) | (s.charAt(i) - '0'); + + if (i >= k - 1) { + if (!codeSet[cur]) { + codeSet[cur] = true; + have++; + } + } + } + + return have == (1 << k); + } +} +``` + +```cpp +class Solution { +public: + bool hasAllCodes(string s, int k) { + int n = s.size(); + if (n < (1 << k)) { + return false; + } + + vector codeSet(1 << k, false); + int cur = 0, have = 0; + + for (int i = 0; i < n; i++) { + cur = ((cur << 1) & ((1 << k) - 1)) | (s[i] - '0'); + + if (i >= k - 1) { + if (!codeSet[cur]) { + codeSet[cur] = true; + have++; + } + } + } + + return have == (1 << k); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @param {number} k + * @return {boolean} + */ + hasAllCodes(s, k) { + const n = s.length; + if (n < (1 << k)) { + return false; + } + + const codeSet = new Array(1 << k).fill(false); + let cur = 0, have = 0; + + for (let i = 0; i < n; i++) { + cur = ((cur << 1) & ((1 << k) - 1)) | (s[i] - '0'); + + if (i >= k - 1) { + if (!codeSet[cur]) { + codeSet[cur] = true; + have++; + } + } + } + + return have === (1 << k); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(2 ^ k)$ + +> Where $n$ is the length of the string $s$ and $k$ is the length of the binary code. \ No newline at end of file diff --git a/articles/contiguous-array.md b/articles/contiguous-array.md new file mode 100644 index 000000000..f13825744 --- /dev/null +++ b/articles/contiguous-array.md @@ -0,0 +1,341 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def findMaxLength(self, nums: List[int]) -> int: + n, res = len(nums), 0 + + for i in range(n): + zeros = ones = 0 + for j in range(i, n): + if nums[j] == 1: + ones += 1 + else: + zeros += 1 + + if ones == zeros and res < (j - i + 1): + res = j - i + 1 + + return res +``` + +```java +public class Solution { + public int findMaxLength(int[] nums) { + int n = nums.length, res = 0; + + for (int i = 0; i < n; i++) { + int zeros = 0, ones = 0; + for (int j = i; j < n; j++) { + if (nums[j] == 1) { + ones++; + } else { + zeros++; + } + if (ones == zeros && res < (j - i + 1)) { + res = j - i + 1; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int findMaxLength(vector& nums) { + int n = nums.size(), res = 0; + + for (int i = 0; i < n; i++) { + int zeros = 0, ones = 0; + for (int j = i; j < n; j++) { + if (nums[j] == 1) { + ones++; + } else { + zeros++; + } + if (ones == zeros && res < (j - i + 1)) { + res = j - i + 1; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + findMaxLength(nums) { + let n = nums.length, res = 0; + + for (let i = 0; i < n; i++) { + let zeros = 0, ones = 0; + for (let j = i; j < n; j++) { + if (nums[j] === 1) { + ones++; + } else { + zeros++; + } + if (ones === zeros && res < (j - i + 1)) { + res = j - i + 1; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Array + +::tabs-start + +```python +class Solution: + def findMaxLength(self, nums: List[int]) -> int: + n = len(nums) + res = 0 + diff_index = [None] * (2 * n + 1) + count = 0 + + for i in range(n): + count += 1 if nums[i] == 1 else -1 + if count == 0: + res = i + 1 + if diff_index[count + n] is not None: + res = max(res, i - diff_index[count + n]) + else: + diff_index[count + n] = i + + return res +``` + +```java +public class Solution { + public int findMaxLength(int[] nums) { + int n = nums.length, res = 0, count = 0; + int[] diffIndex = new int[2 * n + 1]; + Arrays.fill(diffIndex, -2); + diffIndex[n] = -1; + + for (int i = 0; i < n; i++) { + count += nums[i] == 1 ? 1 : -1; + if (diffIndex[count + n] != -2) { + res = Math.max(res, i - diffIndex[count + n]); + } else { + diffIndex[count + n] = i; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int findMaxLength(vector& nums) { + int n = nums.size(), res = 0, count = 0; + vector diffIndex(2 * n + 1, -2); + diffIndex[n] = -1; + + for (int i = 0; i < n; i++) { + count += nums[i] == 1 ? 1 : -1; + if (diffIndex[count + n] != -2) { + res = max(res, i - diffIndex[count + n]); + } else { + diffIndex[count + n] = i; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + findMaxLength(nums) { + const n = nums.length; + let res = 0, count = 0; + const diffIndex = new Array(2 * n + 1).fill(-2); + diffIndex[n] = -1; + + for (let i = 0; i < n; i++) { + count += nums[i] === 1 ? 1 : -1; + if (diffIndex[count + n] !== -2) { + res = Math.max(res, i - diffIndex[count + n]); + } else { + diffIndex[count + n] = i; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Hash Map + +::tabs-start + +```python +class Solution: + def findMaxLength(self, nums: List[int]) -> int: + zero = one = res = 0 + diff_index = {} + + for i, n in enumerate(nums): + if n == 0: + zero += 1 + else: + one += 1 + + if one - zero not in diff_index: + diff_index[one - zero] = i + + if one == zero: + res = one + zero + else: + idx = diff_index[one - zero] + res = max(res, i - idx) + + return res +``` + +```java +public class Solution { + public int findMaxLength(int[] nums) { + int zero = 0, one = 0, res = 0; + HashMap diffIndex = new HashMap<>(); + + for (int i = 0; i < nums.length; i++) { + if (nums[i] == 0) { + zero++; + } else { + one++; + } + + int diff = one - zero; + if (!diffIndex.containsKey(diff)) { + diffIndex.put(diff, i); + } + + if (one == zero) { + res = one + zero; + } else { + res = Math.max(res, i - diffIndex.get(diff)); + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int findMaxLength(vector& nums) { + int zero = 0, one = 0, res = 0; + unordered_map diffIndex; + + for (int i = 0; i < nums.size(); i++) { + if (nums[i] == 0) { + zero++; + } else { + one++; + } + + int diff = one - zero; + if (diffIndex.find(diff) == diffIndex.end()) { + diffIndex[diff] = i; + } + + if (one == zero) { + res = one + zero; + } else { + res = max(res, i - diffIndex[diff]); + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + findMaxLength(nums) { + let zero = 0, one = 0, res = 0; + const diffIndex = new Map(); + + for (let i = 0; i < nums.length; i++) { + if (nums[i] === 0) { + zero++; + } else { + one++; + } + + const diff = one - zero; + if (!diffIndex.has(diff)) { + diffIndex.set(diff, i); + } + + if (one === zero) { + res = one + zero; + } else { + res = Math.max(res, i - diffIndex.get(diff)); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/convert-an-array-into-a-2d-array-with-conditions.md b/articles/convert-an-array-into-a-2d-array-with-conditions.md new file mode 100644 index 000000000..7f5906f0d --- /dev/null +++ b/articles/convert-an-array-into-a-2d-array-with-conditions.md @@ -0,0 +1,317 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def findMatrix(self, nums: List[int]) -> List[List[int]]: + res = [] + + for num in nums: + r = 0 + while r < len(res): + if num not in res[r]: + break + r += 1 + if r == len(res): + res.append([]) + res[r].append(num) + + return res +``` + +```java +public class Solution { + public List> findMatrix(int[] nums) { + List> res = new ArrayList<>(); + + for (int num : nums) { + int r = 0; + while (r < res.size()) { + if (!res.get(r).contains(num)) { + break; + } + r++; + } + if (r == res.size()) { + res.add(new ArrayList<>()); + } + res.get(r).add(num); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector> findMatrix(vector& nums) { + vector> res; + + for (int num : nums) { + int r = 0; + while (r < res.size()) { + if (find(res[r].begin(), res[r].end(), num) == res[r].end()) { + break; + } + r++; + } + if (r == res.size()) { + res.push_back({}); + } + res[r].push_back(num); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[][]} + */ + findMatrix(nums) { + const res = []; + + for (const num of nums) { + let r = 0; + while (r < res.length) { + if (!res[r].includes(num)) { + break; + } + r++; + } + if (r === res.length) { + res.push([]); + } + res[r].push(num); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: $O(n)$ for the output array. + +> Where $n$ is the size of the array $nums$ and $m$ is the frequency of the most frequent element in the given array. + +--- + +## 2. Sorting + +::tabs-start + +```python +class Solution: + def findMatrix(self, nums: List[int]) -> List[List[int]]: + nums.sort() + res = [] + + i = 0 + while i < len(nums): + j = i + r = 0 + while j < len(nums) and nums[i] == nums[j]: + if r == len(res): + res.append([]) + res[r].append(nums[i]) + r += 1 + j += 1 + i = j + + return res +``` + +```java +public class Solution { + public List> findMatrix(int[] nums) { + Arrays.sort(nums); + List> res = new ArrayList<>(); + + int i = 0; + while (i < nums.length) { + int j = i; + int r = 0; + while (j < nums.length && nums[i] == nums[j]) { + if (r == res.size()) { + res.add(new ArrayList<>()); + } + res.get(r).add(nums[i]); + r++; + j++; + } + i = j; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector> findMatrix(vector& nums) { + sort(nums.begin(), nums.end()); + vector> res; + + int i = 0; + while (i < nums.size()) { + int j = i, r = 0; + while (j < nums.size() && nums[i] == nums[j]) { + if (r == res.size()) { + res.push_back({}); + } + res[r].push_back(nums[i]); + r++; + j++; + } + i = j; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[][]} + */ + findMatrix(nums) { + nums.sort((a, b) => a - b); + const res = []; + + let i = 0; + while (i < nums.length) { + let j = i; + let r = 0; + while (j < nums.length && nums[i] === nums[j]) { + if (r === res.length) { + res.push([]); + } + res[r].push(nums[i]); + r++; + j++; + } + i = j; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ for the output array. + +--- + +## 3. Frequency Count + +::tabs-start + +```python +class Solution: + def findMatrix(self, nums: List[int]) -> List[List[int]]: + count = defaultdict(int) + res = [] + + for num in nums: + row = count[num] + if len(res) == row: + res.append([]) + res[row].append(num) + count[num] += 1 + + return res +``` + +```java +public class Solution { + public List> findMatrix(int[] nums) { + Map count = new HashMap<>(); + List> res = new ArrayList<>(); + + for (int num : nums) { + int row = count.getOrDefault(num, 0); + if (res.size() == row) { + res.add(new ArrayList<>()); + } + res.get(row).add(num); + count.put(num, row + 1); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector> findMatrix(vector& nums) { + unordered_map count; + vector> res; + + for (int num : nums) { + int row = count[num]; + if (res.size() == row) { + res.push_back({}); + } + res[row].push_back(num); + count[num]++; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[][]} + */ + findMatrix(nums) { + const count = new Map(); + const res = []; + + for (const num of nums) { + const row = count.get(num) || 0; + if (res.length === row) { + res.push([]); + } + res[row].push(num); + count.set(num, row + 1); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/divide-array-into-arrays-with-max-difference.md b/articles/divide-array-into-arrays-with-max-difference.md new file mode 100644 index 000000000..d969ca851 --- /dev/null +++ b/articles/divide-array-into-arrays-with-max-difference.md @@ -0,0 +1,238 @@ +## 1. Sorting + +::tabs-start + +```python +class Solution: + def divideArray(self, nums: List[int], k: int) -> List[List[int]]: + nums.sort() + res = [] + + for i in range(0, len(nums), 3): + if nums[i + 2] - nums[i] > k: + return [] + res.append(nums[i: i + 3]) + + return res +``` + +```java +public class Solution { + public int[][] divideArray(int[] nums, int k) { + Arrays.sort(nums); + int[][] res = new int[nums.length / 3][3]; + + for (int i = 0, idx = 0; i < nums.length; i += 3, idx++) { + if (nums[i + 2] - nums[i] > k) { + return new int[][]{}; + } + res[idx][0] = nums[i]; + res[idx][1] = nums[i + 1]; + res[idx][2] = nums[i + 2]; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector> divideArray(vector& nums, int k) { + sort(nums.begin(), nums.end()); + vector> res; + + for (int i = 0; i < nums.size(); i += 3) { + if (nums[i + 2] - nums[i] > k) { + return {}; + } + res.push_back({nums[i], nums[i + 1], nums[i + 2]}); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @param {number} k + * @return {number[][]} + */ + divideArray(nums, k) { + nums.sort((a, b) => a - b); + const res = []; + + for (let i = 0; i < nums.length; i += 3) { + if (nums[i + 2] - nums[i] > k) { + return []; + } + res.push([nums[i], nums[i + 1], nums[i + 2]]); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ for the output array. + +--- + +## 2. Counting Sort + +::tabs-start + +```python +class Solution: + def divideArray(self, nums: List[int], k: int) -> List[List[int]]: + max_num = max(nums) + count = [0] * (max_num + 1) + for num in nums: + count[num] += 1 + + res = [] + group = [] + + for num in range(max_num + 1): + while count[num] > 0: + group.append(num) + count[num] -= 1 + + if len(group) == 3: + if group[2] - group[0] > k: + return [] + res.append(group) + group = [] + + return res +``` + +```java +public class Solution { + public int[][] divideArray(int[] nums, int k) { + int max = 0; + for (int num : nums) { + max = Math.max(max, num); + } + + int[] count = new int[max + 1]; + for (int num : nums) { + count[num]++; + } + + int[][] res = new int[nums.length / 3][3]; + int[] group = new int[3]; + int i = 0; + + for (int num = 0, idx = 0; num <= max; num++) { + while (count[num] > 0) { + group[i++] = num; + count[num]--; + + if (i == 3) { + if (group[2] - group[0] > k) { + return new int[][]{}; + } + for (int j = 0; j < 3; j++) { + res[idx][j] = group[j]; + } + i = 0; + idx++; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector> divideArray(vector& nums, int k) { + int maxNum = *max_element(nums.begin(), nums.end()); + vector count(maxNum + 1, 0); + + for (int& num : nums) { + count[num]++; + } + + vector> res; + vector group; + + for (int num = 0; num <= maxNum; num++) { + while (count[num] > 0) { + group.push_back(num); + count[num]--; + + if (group.size() == 3) { + if (group[2] - group[0] > k) { + return {}; + } + res.push_back(group); + group.clear(); + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @param {number} k + * @return {number[][]} + */ + divideArray(nums, k) { + const max = Math.max(...nums); + const count = new Array(max + 1).fill(0); + + for (const num of nums) { + count[num]++; + } + + const res = []; + let group = []; + + for (let num = 0; num <= max; num++) { + while (count[num] > 0) { + group.push(num); + count[num]--; + + if (group.length === 3) { + if (group[2] - group[0] > k) { + return []; + } + res.push(group); + group = []; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ is the size of the array $nums$ and $m$ is the maximum element in $nums$. \ No newline at end of file diff --git a/articles/encode-and-decode-tinyurl.md b/articles/encode-and-decode-tinyurl.md new file mode 100644 index 000000000..0da60014f --- /dev/null +++ b/articles/encode-and-decode-tinyurl.md @@ -0,0 +1,312 @@ +## 1. List + +::tabs-start + +```python +class Codec: + + def __init__(self): + self.urls = [] + + def encode(self, longUrl: str) -> str: + self.urls.append(longUrl) + return 'http://tinyurl.com/' + str(len(self.urls) - 1) + + def decode(self, shortUrl: str) -> str: + return self.urls[int(shortUrl.split('/')[-1])] +``` + +```java +public class Codec { + private List urls; + + public Codec() { + urls = new ArrayList<>(); + } + + public String encode(String longUrl) { + urls.add(longUrl); + return "http://tinyurl.com/" + (urls.size() - 1); + } + + public String decode(String shortUrl) { + int index = Integer.parseInt(shortUrl.substring(shortUrl.lastIndexOf('/') + 1)); + return urls.get(index); + } +} +``` + +```cpp +class Solution { +public: + vector urls; + + string encode(string longUrl) { + urls.push_back(longUrl); + return "http://tinyurl.com/" + to_string(urls.size() - 1); + } + + string decode(string shortUrl) { + int index = stoi(shortUrl.substr(shortUrl.find_last_of('/') + 1)); + return urls[index]; + } +}; +``` + +```javascript +class Codec { + constructor() { + this.urls = []; + } + + /** + * Encodes a URL to a shortened URL. + * + * @param {string} longUrl + * @return {string} + */ + encode(longUrl) { + this.urls.push(longUrl); + return 'http://tinyurl.com/' + (this.urls.length - 1); + } + + /** + * Decodes a shortened URL to its original URL. + * + * @param {string} shortUrl + * @return {string} + */ + decode(shortUrl) { + const index = parseInt(shortUrl.split('/').pop()); + return this.urls[index]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(1)$ for $encode()$ and $decode()$. +* Space complexity: $O(n * m)$ + +> Where $n$ is the number of $longUrls$, $m$ is the average length of the URLs. + +--- + +## 2. Hash Map - I + +::tabs-start + +```python +class Codec: + + def __init__(self): + self.url_map = {} + self.id = 0 + + def encode(self, longUrl: str) -> str: + self.url_map[self.id] = longUrl + short_url = f"http://tinyurl.com/%7Bself.id%7D" + self.id += 1 + return short_url + + def decode(self, shortUrl: str) -> str: + url_id = int(shortUrl.split('/')[-1]) + return self.url_map[url_id] +``` + +```java +public class Codec { + private HashMap urlMap; + private int id; + + public Codec() { + urlMap = new HashMap<>(); + id = 0; + } + + public String encode(String longUrl) { + urlMap.put(id, longUrl); + return "http://tinyurl.com/" + id++; + } + + public String decode(String shortUrl) { + int urlId = Integer.parseInt(shortUrl.substring(shortUrl.lastIndexOf('/') + 1)); + return urlMap.get(urlId); + } +} +``` + +```cpp +class Solution { + unordered_map urlMap; + int id; + +public: + Solution() : id(0) {} + + string encode(string longUrl) { + urlMap[id] = longUrl; + return "http://tinyurl.com/" + to_string(id++); + } + + string decode(string shortUrl) { + int urlId = stoi(shortUrl.substr(shortUrl.find_last_of('/') + 1)); + return urlMap[urlId]; + } +}; +``` + +```javascript +class Codec { + constructor() { + this.urlMap = {}; + this.id = 0; + } + + /** + * Encodes a URL to a shortened URL. + * + * @param {string} longUrl + * @return {string} + */ + encode(longUrl) { + this.urlMap[this.id] = longUrl; + return `http://tinyurl.com/${this.id++}`; + } + + /** + * Decodes a shortened URL to its original URL. + * + * @param {string} shortUrl + * @return {string} + */ + decode(shortUrl) { + const urlId = parseInt(shortUrl.split('/').pop(), 10); + return this.urlMap[urlId]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(1)$ for $encode()$ and $decode()$. +* Space complexity: $O(n * m)$ + +> Where $n$ is the number of $longUrls$, $m$ is the average length of the URLs. + +--- + +## 3. Hash Map - II + +::tabs-start + +```python +class Codec: + + def __init__(self): + self.encodeMap = {} + self.decodeMap = {} + self.base = "http://tinyurl.com/" + + def encode(self, longUrl: str) -> str: + if longUrl not in self.encodeMap: + shortUrl = self.base + str(len(self.encodeMap) + 1) + self.encodeMap[longUrl] = shortUrl + self.decodeMap[shortUrl] = longUrl + return self.encodeMap[longUrl] + + def decode(self, shortUrl: str) -> str: + return self.decodeMap[shortUrl] +``` + +```java +public class Codec { + private HashMap encodeMap = new HashMap<>(); + private HashMap decodeMap = new HashMap<>(); + private String base = "http://tinyurl.com/"; + + public String encode(String longUrl) { + if (!encodeMap.containsKey(longUrl)) { + String shortUrl = base + (encodeMap.size() + 1); + encodeMap.put(longUrl, shortUrl); + decodeMap.put(shortUrl, longUrl); + } + return encodeMap.get(longUrl); + } + + public String decode(String shortUrl) { + return decodeMap.get(shortUrl); + } +} +``` + +```cpp +class Solution { +private: + unordered_map encodeMap; + unordered_map decodeMap; + string base = "http://tinyurl.com/"; + +public: + string encode(string longUrl) { + if (encodeMap.find(longUrl) == encodeMap.end()) { + string shortUrl = base + to_string(encodeMap.size() + 1); + encodeMap[longUrl] = shortUrl; + decodeMap[shortUrl] = longUrl; + } + return encodeMap[longUrl]; + } + + string decode(string shortUrl) { + return decodeMap[shortUrl]; + } +}; +``` + +```javascript +class Codec { + constructor() { + this.encodeMap = new Map(); + this.decodeMap = new Map(); + this.base = "http://tinyurl.com/"; + } + + /** + * Encodes a URL to a shortened URL. + * + * @param {string} longUrl + * @return {string} + */ + encode(longUrl) { + if (!this.encodeMap.has(longUrl)) { + const shortUrl = this.base + (this.encodeMap.size + 1); + this.encodeMap.set(longUrl, shortUrl); + this.decodeMap.set(shortUrl, longUrl); + } + return this.encodeMap.get(longUrl); + } + + /** + * Decodes a shortened URL to its original URL. + * + * @param {string} shortUrl + * @return {string} + */ + decode(shortUrl) { + return this.decodeMap.get(shortUrl); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(1)$ for $encode()$ and $decode()$. +* Space complexity: $O(n * m)$ + +> Where $n$ is the number of $longUrls$, $m$ is the average length of the URLs. \ No newline at end of file diff --git a/articles/find-the-difference-of-two-arrays.md b/articles/find-the-difference-of-two-arrays.md new file mode 100644 index 000000000..853638267 --- /dev/null +++ b/articles/find-the-difference-of-two-arrays.md @@ -0,0 +1,467 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def findDifference(self, nums1: list[int], nums2: list[int]) -> list[list[int]]: + res = [set(), set()] + + for num1 in nums1: + found = False + for num2 in nums2: + if num1 == num2: + found = True + break + if not found: + res[0].add(num1) + + for num2 in nums2: + found = False + for num1 in nums1: + if num1 == num2: + found = True + break + if not found: + res[1].add(num2) + + return [list(res[0]), list(res[1])] +``` + +```java +public class Solution { + public List> findDifference(int[] nums1, int[] nums2) { + Set res1 = new HashSet<>(); + Set res2 = new HashSet<>(); + + for (int num1 : nums1) { + boolean found = false; + for (int num2 : nums2) { + if (num1 == num2) { + found = true; + break; + } + } + if (!found) { + res1.add(num1); + } + } + + for (int num2 : nums2) { + boolean found = false; + for (int num1 : nums1) { + if (num1 == num2) { + found = true; + break; + } + } + if (!found) { + res2.add(num2); + } + } + + List> result = new ArrayList<>(); + result.add(new ArrayList<>(res1)); + result.add(new ArrayList<>(res2)); + return result; + } +} +``` + +```cpp +class Solution { +public: + vector> findDifference(vector& nums1, vector& nums2) { + set res1, res2; + + for (int num1 : nums1) { + bool found = false; + for (int num2 : nums2) { + if (num1 == num2) { + found = true; + break; + } + } + if (!found) { + res1.insert(num1); + } + } + + for (int num2 : nums2) { + bool found = false; + for (int num1 : nums1) { + if (num1 == num2) { + found = true; + break; + } + } + if (!found) { + res2.insert(num2); + } + } + + return {vector(res1.begin(), res1.end()), + vector(res2.begin(), res2.end())}; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[][]} + */ + findDifference(nums1, nums2) { + const res1 = new Set(); + const res2 = new Set(); + + for (const num1 of nums1) { + let found = false; + for (const num2 of nums2) { + if (num1 === num2) { + found = true; + break; + } + } + if (!found) { + res1.add(num1); + } + } + + for (const num2 of nums2) { + let found = false; + for (const num1 of nums1) { + if (num1 === num2) { + found = true; + break; + } + } + if (!found) { + res2.add(num2); + } + } + + return [Array.from(res1), Array.from(res2)]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ is the size of the array $nums1$ and $m$ is the size of the array $nums2$. + +--- + +## 2. Sorting + +::tabs-start + +```python +class Solution: + def findDifference(self, nums1: list[int], nums2: list[int]) -> list[list[int]]: + nums1.sort() + nums2.sort() + + def helper(A, B): + n, m = len(A), len(B) + res = [] + + j = 0 + prev = float('-inf') + for num in A: + if prev == num: + continue + while j < m and B[j] < num: + j += 1 + if j == m or B[j] != num: + res.append(num) + prev = num + return res + + return [helper(nums1, nums2), helper(nums2, nums1)] +``` + +```java +public class Solution { + public List> findDifference(int[] nums1, int[] nums2) { + Arrays.sort(nums1); + Arrays.sort(nums2); + + List diff1 = helper(nums1, nums2); + List diff2 = helper(nums2, nums1); + + List> result = new ArrayList<>(); + result.add(diff1); + result.add(diff2); + + return result; + } + + private List helper(int[] A, int[] B) { + int n = A.length, m = B.length, j = 0; + List res = new ArrayList<>(); + int prev = Integer.MIN_VALUE; + + for (int num : A) { + if (num == prev) continue; + while (j < m && B[j] < num) j++; + if (j == m || B[j] != num) res.add(num); + prev = num; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector> findDifference(vector& nums1, vector& nums2) { + sort(nums1.begin(), nums1.end()); + sort(nums2.begin(), nums2.end()); + + return {helper(nums1, nums2), helper(nums2, nums1)}; + } + +private: + vector helper(vector& A, vector& B) { + vector res; + int n = A.size(), m = B.size(), j = 0, prev = INT_MIN; + + for (int num : A) { + if (num == prev) continue; + while (j < m && B[j] < num) j++; + if (j == m || B[j] != num) res.push_back(num); + prev = num; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[][]} + */ + findDifference(nums1, nums2) { + nums1.sort((a, b) => a - b); + nums2.sort((a, b) => a - b); + + const helper = (A, B) => { + const res = []; + let j = 0; + let prev = -Infinity; + + for (const num of A) { + if (num === prev) continue; + while (j < B.length && B[j] < num) j++; + if (j === B.length || B[j] !== num) res.push(num); + prev = num; + } + + return res; + }; + + return [helper(nums1, nums2), helper(nums2, nums1)]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n + m \log m)$ +* Space complexity: $O(1)$ or $O(n + m)$ depending on the sorting algorithm. + +> Where $n$ is the size of the array $nums1$ and $m$ is the size of the array $nums2$. + +--- + +## 3. Hash Set + +::tabs-start + +```python +class Solution: + def findDifference(self, nums1: List[int], nums2: List[int]) -> List[List[int]]: + num1Set, num2Set = set(nums1), set(nums2) + res1, res2 = [], [] + + for num in num1Set: + if num not in num2Set: + res1.append(num) + + for num in num2Set: + if num not in num1Set: + res2.append(num) + + return [res1, res2] +``` + +```java +public class Solution { + public List> findDifference(int[] nums1, int[] nums2) { + Set num1Set = new HashSet<>(); + Set num2Set = new HashSet<>(); + for (int num : nums1) num1Set.add(num); + for (int num : nums2) num2Set.add(num); + + List res1 = new ArrayList<>(); + List res2 = new ArrayList<>(); + + for (int num : num1Set) { + if (!num2Set.contains(num)) res1.add(num); + } + + for (int num : num2Set) { + if (!num1Set.contains(num)) res2.add(num); + } + + return Arrays.asList(res1, res2); + } +} +``` + +```cpp +class Solution { +public: + vector> findDifference(vector& nums1, vector& nums2) { + unordered_set num1Set(nums1.begin(), nums1.end()); + unordered_set num2Set(nums2.begin(), nums2.end()); + vector res1, res2; + + for (int num : num1Set) { + if (num2Set.find(num) == num2Set.end()) res1.push_back(num); + } + + for (int num : num2Set) { + if (num1Set.find(num) == num1Set.end()) res2.push_back(num); + } + + return {res1, res2}; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[][]} + */ + findDifference(nums1, nums2) { + const num1Set = new Set(nums1); + const num2Set = new Set(nums2); + const res1 = []; + const res2 = []; + + for (const num of num1Set) { + if (!num2Set.has(num)) res1.push(num); + } + + for (const num of num2Set) { + if (!num1Set.has(num)) res2.push(num); + } + + return [res1, res2]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ is the size of the array $nums1$ and $m$ is the size of the array $nums2$. + +--- + +## 4. Hash Set Difference + +::tabs-start + +```python +class Solution: + def findDifference(self, nums1: List[int], nums2: List[int]) -> List[List[int]]: + numSet1, numSet2 = set(nums1), set(nums2) + return [list(numSet1 - numSet2), list(numSet2 - numSet1)] +``` + +```java +public class Solution { + public List> findDifference(int[] nums1, int[] nums2) { + Set numSet1 = new HashSet<>(); + Set numSet2 = new HashSet<>(); + for (int num : nums1) numSet1.add(num); + for (int num : nums2) numSet2.add(num); + + List res1 = new ArrayList<>(numSet1); + res1.removeAll(numSet2); + + List res2 = new ArrayList<>(numSet2); + res2.removeAll(numSet1); + + return Arrays.asList(res1, res2); + } +} +``` + +```cpp +class Solution { +public: + vector> findDifference(vector& nums1, vector& nums2) { + vector res1, res2; + set numSet1(begin(nums1), end(nums1)), numSet2(begin(nums2), end(nums2)); + + set_difference(begin(numSet1), end(numSet1), begin(numSet2), end(numSet2), back_inserter(res1)); + set_difference(begin(numSet2), end(numSet2), begin(numSet1), end(numSet1), back_inserter(res2)); + + return {res1, res2}; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[][]} + */ + findDifference(nums1, nums2) { + const numSet1 = new Set(nums1); + const numSet2 = new Set(nums2); + + const res1 = Array.from(numSet1).filter(num => !numSet2.has(num)); + const res2 = Array.from(numSet2).filter(num => !numSet1.has(num)); + + return [res1, res2]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ is the size of the array $nums1$ and $m$ is the size of the array $nums2$. \ No newline at end of file diff --git a/articles/first-missing-positive.md b/articles/first-missing-positive.md new file mode 100644 index 000000000..f0bef0643 --- /dev/null +++ b/articles/first-missing-positive.md @@ -0,0 +1,536 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def firstMissingPositive(self, nums: List[int]) -> int: + missing = 1 + while True: + flag = True + for num in nums: + if missing == num: + flag = False + break + + if flag: + return missing + missing += 1 +``` + +```java +public class Solution { + public int firstMissingPositive(int[] nums) { + int missing = 1; + while (true) { + boolean flag = true; + for (int num : nums) { + if (missing == num) { + flag = false; + break; + } + } + if (flag) return missing; + missing++; + } + } +} +``` + +```cpp +class Solution { +public: + int firstMissingPositive(vector& nums) { + int missing = 1; + while (true) { + bool flag = true; + for (int& num : nums) { + if (missing == num) { + flag = false; + break; + } + } + if (flag) return missing; + missing++; + } + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + firstMissingPositive(nums) { + let missing = 1; + while (true) { + let flag = true; + for (let num of nums) { + if (missing === num) { + flag = false; + break; + } + } + if (flag) return missing; + missing++; + } + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Boolean Array + +::tabs-start + +```python +class Solution: + def firstMissingPositive(self, nums: list[int]) -> int: + n = len(nums) + seen = [False] * n + for num in nums: + if num > 0 and num <= n: + seen[num - 1] = True + + for num in range(1, n + 1): + if not seen[num - 1]: + return num + + return n + 1 +``` + +```java +public class Solution { + public int firstMissingPositive(int[] nums) { + int n = nums.length; + boolean[] seen = new boolean[n]; + + for (int num : nums) { + if (num > 0 && num <= n) { + seen[num - 1] = true; + } + } + + for (int i = 0; i < n; i++) { + if (!seen[i]) { + return i + 1; + } + } + + return n + 1; + } +} +``` + +```cpp +class Solution { +public: + int firstMissingPositive(vector& nums) { + int n = nums.size(); + vector seen(n, false); + + for (int num : nums) { + if (num > 0 && num <= n) { + seen[num - 1] = true; + } + } + + for (int i = 0; i < n; i++) { + if (!seen[i]) { + return i + 1; + } + } + + return n + 1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + firstMissingPositive(nums) { + const n = nums.length; + const seen = new Array(n).fill(false); + + for (const num of nums) { + if (num > 0 && num <= n) { + seen[num - 1] = true; + } + } + + for (let i = 0; i < n; i++) { + if (!seen[i]) { + return i + 1; + } + } + + return n + 1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Sorting + +::tabs-start + +```python +class Solution: + def firstMissingPositive(self, nums: list[int]) -> int: + nums.sort() + missing = 1 + for num in nums: + if num > 0 and missing == num: + missing += 1 + return missing +``` + +```java +public class Solution { + public int firstMissingPositive(int[] nums) { + Arrays.sort(nums); + int missing = 1; + for (int num : nums) { + if (num > 0 && missing == num) { + missing++; + } + } + return missing; + } +} +``` + +```cpp +class Solution { +public: + int firstMissingPositive(vector& nums) { + sort(nums.begin(), nums.end()); + int missing = 1; + for (int num : nums) { + if (num > 0 && missing == num) { + missing++; + } + } + return missing; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + firstMissingPositive(nums) { + nums.sort((a, b) => a - b); + let missing = 1; + for (const num of nums) { + if (num > 0 && missing === num) { + missing++; + } + } + return missing; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. + +--- + +## 4. Negative Marking + +::tabs-start + +```python +class Solution: + def firstMissingPositive(self, nums: list[int]) -> int: + for i in range(len(nums)): + if nums[i] < 0: + nums[i] = 0 + + for i in range(len(nums)): + val = abs(nums[i]) + if 1 <= val <= len(nums): + if nums[val - 1] > 0: + nums[val - 1] *= -1 + elif nums[val - 1] == 0: + nums[val - 1] = -1 * (len(nums) + 1) + + for i in range(1, len(nums) + 1): + if nums[i - 1] >= 0: + return i + + return len(nums) + 1 +``` + +```java +public class Solution { + public int firstMissingPositive(int[] nums) { + int n = nums.length; + + for (int i = 0; i < n; i++) { + if (nums[i] < 0) { + nums[i] = 0; + } + } + + for (int i = 0; i < n; i++) { + int val = Math.abs(nums[i]); + if (val >= 1 && val <= n) { + if (nums[val - 1] > 0) { + nums[val - 1] *= -1; + } else if (nums[val - 1] == 0) { + nums[val - 1] = -1 * (n + 1); + } + } + } + + for (int i = 1; i <= n; i++) { + if (nums[i - 1] >= 0) { + return i; + } + } + + return n + 1; + } +} +``` + +```cpp +class Solution { +public: + int firstMissingPositive(vector& nums) { + int n = nums.size(); + + for (int i = 0; i < n; i++) { + if (nums[i] < 0) { + nums[i] = 0; + } + } + + for (int i = 0; i < n; i++) { + int val = abs(nums[i]); + if (val >= 1 && val <= n) { + if (nums[val - 1] > 0) { + nums[val - 1] *= -1; + } else if (nums[val - 1] == 0) { + nums[val - 1] = -1 * (n + 1); + } + } + } + + for (int i = 1; i <= n; i++) { + if (nums[i - 1] >= 0) { + return i; + } + } + + return n + 1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + firstMissingPositive(nums) { + const n = nums.length; + + for (let i = 0; i < n; i++) { + if (nums[i] < 0) { + nums[i] = 0; + } + } + + for (let i = 0; i < n; i++) { + const val = Math.abs(nums[i]); + if (val >= 1 && val <= n) { + if (nums[val - 1] > 0) { + nums[val - 1] *= -1; + } else if (nums[val - 1] === 0) { + nums[val - 1] = -1 * (n + 1); + } + } + } + + for (let i = 1; i <= n; i++) { + if (nums[i - 1] >= 0) { + return i; + } + } + + return n + 1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ extra space. + +--- + +## 5. Cycle Sort + +::tabs-start + +```python +class Solution: + def firstMissingPositive(self, nums: list[int]) -> int: + n = len(nums) + i = 0 + while i < n: + if nums[i] <= 0 or nums[i] > n: + i += 1 + continue + + index = nums[i] - 1 + if nums[i] != nums[index]: + nums[i], nums[index] = nums[index], nums[i] + else: + i += 1 + + for i in range(n): + if nums[i] != i + 1: + return i + 1 + + return n + 1 +``` + +```java +public class Solution { + public int firstMissingPositive(int[] nums) { + int n = nums.length; + int i = 0; + + while (i < n) { + if (nums[i] <= 0 || nums[i] > n) { + i++; + continue; + } + int index = nums[i] - 1; + if (nums[i] != nums[index]) { + int temp = nums[i]; + nums[i] = nums[index]; + nums[index] = temp; + } else { + i++; + } + } + + for (i = 0; i < n; i++) { + if (nums[i] != i + 1) { + return i + 1; + } + } + + return n + 1; + } +} +``` + +```cpp +class Solution { +public: + int firstMissingPositive(vector& nums) { + int n = nums.size(); + int i = 0; + + while (i < n) { + if (nums[i] <= 0 || nums[i] > n) { + i++; + continue; + } + int index = nums[i] - 1; + if (nums[i] != nums[index]) { + swap(nums[i], nums[index]); + } else { + i++; + } + } + + for (i = 0; i < n; i++) { + if (nums[i] != i + 1) { + return i + 1; + } + } + + return n + 1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + firstMissingPositive(nums) { + let n = nums.length; + let i = 0; + while (i < n) { + if (nums[i] <= 0 || nums[i] > n) { + i++; + continue; + } + let index = nums[i] - 1; + if (nums[i] != nums[index]) { + [nums[i], nums[index]] = [nums[index], nums[i]]; + } else { + i++; + } + } + + for (let i = 0; i < n; i++) { + if (nums[i] != i + 1) { + return i + 1; + } + } + + return n + 1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ extra space. \ No newline at end of file diff --git a/articles/insert-delete-getrandom-o1.md b/articles/insert-delete-getrandom-o1.md new file mode 100644 index 000000000..000979641 --- /dev/null +++ b/articles/insert-delete-getrandom-o1.md @@ -0,0 +1,300 @@ +## 1. Hash Map + +::tabs-start + +```python +class RandomizedSet: + + def __init__(self): + self.numMap = {} + self.size = 0 + + def insert(self, val: int) -> bool: + if val in self.numMap: + return False + self.numMap[val] = 1 + self.size += 1 + return True + + def remove(self, val: int) -> bool: + if val not in self.numMap: + return False + del self.numMap[val] + self.size -= 1 + return True + + def getRandom(self) -> int: + idx = random.randint(0, self.size - 1) + return list(self.numMap.keys())[idx] +``` + +```java +public class RandomizedSet { + private HashMap numMap; + private int size; + + public RandomizedSet() { + numMap = new HashMap<>(); + size = 0; + } + + public boolean insert(int val) { + if (numMap.containsKey(val)) { + return false; + } + numMap.put(val, 1); + size++; + return true; + } + + public boolean remove(int val) { + if (!numMap.containsKey(val)) { + return false; + } + numMap.remove(val); + size--; + return true; + } + + public int getRandom() { + int idx = new Random().nextInt(size); + Iterator it = numMap.keySet().iterator(); + while (idx-- > 0) { + it.next(); + } + return it.next(); + } +} +``` + +```cpp +class RandomizedSet { +private: + unordered_map numMap; + int size; + +public: + RandomizedSet() : size(0) {} + + bool insert(int val) { + if (numMap.count(val)) return false; + numMap[val] = 1; + size++; + return true; + } + + bool remove(int val) { + if (!numMap.count(val)) return false; + numMap.erase(val); + size--; + return true; + } + + int getRandom() { + int idx = rand() % size; + auto it = numMap.begin(); + advance(it, idx); + return it->first; + } +}; +``` + +```javascript +class RandomizedSet { + constructor() { + this.numMap = new Map(); + this.size = 0; + } + + /** + * @param {number} val + * @return {boolean} + */ + insert(val) { + if (this.numMap.has(val)) return false; + this.numMap.set(val, 1); + this.size++; + return true; + } + + /** + * @param {number} val + * @return {boolean} + */ + remove(val) { + if (!this.numMap.has(val)) return false; + this.numMap.delete(val); + this.size--; + return true; + } + + /** + * @return {number} + */ + getRandom() { + const keys = Array.from(this.numMap.keys()); + const idx = Math.floor(Math.random() * this.size); + return keys[idx]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ for $getRandom()$, $O(1)$ for other function calls. +* Space complexity: $O(n)$ + +--- + +## 2. Hash Map + List + +::tabs-start + +```python +class RandomizedSet: + + def __init__(self): + self.numMap = {} + self.nums = [] + + def insert(self, val: int) -> bool: + if val in self.numMap: + return False + self.numMap[val] = len(self.nums) + self.nums.append(val) + return True + + def remove(self, val: int) -> bool: + if val not in self.numMap: + return False + idx = self.numMap[val] + last = self.nums[-1] + self.nums[idx] = last + self.numMap[last] = idx + self.nums.pop() + del self.numMap[val] + return True + + def getRandom(self) -> int: + return random.choice(self.nums) +``` + +```java +public class RandomizedSet { + private Map numMap; + private List nums; + private Random rand; + + public RandomizedSet() { + numMap = new HashMap<>(); + nums = new ArrayList<>(); + rand = new Random(); + } + + public boolean insert(int val) { + if (numMap.containsKey(val)) return false; + numMap.put(val, nums.size()); + nums.add(val); + return true; + } + + public boolean remove(int val) { + if (!numMap.containsKey(val)) return false; + int idx = numMap.get(val); + int last = nums.get(nums.size() - 1); + nums.set(idx, last); + numMap.put(last, idx); + nums.remove(nums.size() - 1); + numMap.remove(val); + return true; + } + + public int getRandom() { + return nums.get(rand.nextInt(nums.size())); + } +} +``` + +```cpp +class RandomizedSet { +private: + unordered_map numMap; + vector nums; + +public: + RandomizedSet() {} + + bool insert(int val) { + if (numMap.count(val)) return false; + numMap[val] = nums.size(); + nums.push_back(val); + return true; + } + + bool remove(int val) { + if (!numMap.count(val)) return false; + int idx = numMap[val]; + int last = nums.back(); + nums[idx] = last; + numMap[last] = idx; + nums.pop_back(); + numMap.erase(val); + return true; + } + + int getRandom() { + return nums[rand() % nums.size()]; + } +}; +``` + +```javascript +class RandomizedSet { + constructor() { + this.numMap = new Map(); + this.nums = []; + } + + /** + * @param {number} val + * @return {boolean} + */ + insert(val) { + if (this.numMap.has(val)) return false; + this.numMap.set(val, this.nums.length); + this.nums.push(val); + return true; + } + + /** + * @param {number} val + * @return {boolean} + */ + remove(val) { + if (!this.numMap.has(val)) return false; + const idx = this.numMap.get(val); + const last = this.nums[this.nums.length - 1]; + this.nums[idx] = last; + this.numMap.set(last, idx); + this.nums.pop(); + this.numMap.delete(val); + return true; + } + + /** + * @return {number} + */ + getRandom() { + return this.nums[Math.floor(Math.random() * this.nums.length)]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(1)$ for each function call. +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/majority-element-ii.md b/articles/majority-element-ii.md new file mode 100644 index 000000000..6ba0f2fd1 --- /dev/null +++ b/articles/majority-element-ii.md @@ -0,0 +1,597 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def majorityElement(self, nums: List[int]) -> List[int]: + res = set() + for num in nums: + count = sum(1 for i in nums if i == num) + if count > len(nums) // 3: + res.add(num) + return list(res) +``` + +```java +public class Solution { + public List majorityElement(int[] nums) { + Set res = new HashSet<>(); + for (int num : nums) { + int count = 0; + for (int i : nums) { + if (i == num) count++; + } + if (count > nums.length / 3) { + res.add(num); + } + } + return new ArrayList<>(res); + } +} +``` + +```cpp +class Solution { +public: + vector majorityElement(vector& nums) { + unordered_set res; + for (int num : nums) { + int count = 0; + for (int i : nums) { + if (i == num) count++; + } + if (count > nums.size() / 3) { + res.insert(num); + } + } + return vector(res.begin(), res.end()); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + majorityElement(nums) { + const res = new Set(); + for (const num of nums) { + let count = 0; + for (const i of nums) { + if (i === num) count++; + } + if (count > Math.floor(nums.length / 3)) { + res.add(num); + } + } + return Array.from(res); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ since output array size will be at most $2$. + +--- + +## 2. Sorting + +::tabs-start + +```python +class Solution: + def majorityElement(self, nums: List[int]) -> List[int]: + nums.sort() + res, n = [], len(nums) + + i = 0 + while i < n: + j = i + 1 + while j < n and nums[i] == nums[j]: + j += 1 + if (j - i) > n // 3: + res.append(nums[i]) + i = j + + return res +``` + +```java +public class Solution { + public List majorityElement(int[] nums) { + Arrays.sort(nums); + List res = new ArrayList<>(); + int n = nums.length; + + int i = 0; + while (i < n) { + int j = i + 1; + while (j < n && nums[i] == nums[j]) { + j++; + } + if (j - i > n / 3) { + res.add(nums[i]); + } + i = j; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector majorityElement(vector& nums) { + sort(nums.begin(), nums.end()); + vector res; + int n = nums.size(); + + int i = 0; + while (i < n) { + int j = i + 1; + while (j < n && nums[i] == nums[j]) { + j++; + } + if (j - i > n / 3) { + res.push_back(nums[i]); + } + i = j; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + majorityElement(nums) { + nums.sort((a, b) => a - b); + const res = []; + const n = nums.length; + + let i = 0; + while (i < n) { + let j = i + 1; + while (j < n && nums[i] === nums[j]) { + j++; + } + if (j - i > Math.floor(n / 3)) { + res.push(nums[i]); + } + i = j; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. + +--- + +## 3. Frequency Count + +::tabs-start + +```python +class Solution: + def majorityElement(self, nums: List[int]) -> List[int]: + count = Counter(nums) + res = [] + + for key in count: + if count[key] > len(nums) // 3: + res.append(key) + + return res +``` + +```java +public class Solution { + public List majorityElement(int[] nums) { + Map count = new HashMap<>(); + for (int num : nums) { + count.put(num, count.getOrDefault(num, 0) + 1); + } + + List res = new ArrayList<>(); + for (int key : count.keySet()) { + if (count.get(key) > nums.length / 3) { + res.add(key); + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector majorityElement(vector& nums) { + unordered_map count; + for (int num : nums) { + count[num]++; + } + + vector res; + for (auto& pair : count) { + if (pair.second > nums.size() / 3) { + res.push_back(pair.first); + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + majorityElement(nums) { + const count = new Map(); + for (const num of nums) { + count.set(num, (count.get(num) || 0) + 1); + } + + const res = []; + for (const [key, value] of count.entries()) { + if (value > Math.floor(nums.length / 3)) { + res.push(key); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. Boyer-Moore Voting Algorithm + +::tabs-start + +```python +class Solution: + def majorityElement(self, nums: List[int]) -> List[int]: + n = len(nums) + num1 = num2 = -1 + cnt1 = cnt2 = 0 + + for num in nums: + if num == num1: + cnt1 += 1 + elif num == num2: + cnt2 += 1 + elif cnt1 == 0: + cnt1 = 1 + num1 = num + elif cnt2 == 0: + cnt2 = 1 + num2 = num + else: + cnt1 -= 1 + cnt2 -= 1 + + cnt1 = cnt2 = 0 + for num in nums: + if num == num1: + cnt1 += 1 + elif num == num2: + cnt2 += 1 + + res = [] + if cnt1 > n // 3: + res.append(num1) + if cnt2 > n // 3: + res.append(num2) + + return res +``` + +```java +public class Solution { + public List majorityElement(int[] nums) { + int n = nums.length; + int num1 = -1, num2 = -1, cnt1 = 0, cnt2 = 0; + + for (int num : nums) { + if (num == num1) { + cnt1++; + } else if (num == num2) { + cnt2++; + } else if (cnt1 == 0) { + cnt1 = 1; + num1 = num; + } else if (cnt2 == 0) { + cnt2 = 1; + num2 = num; + } else { + cnt1--; + cnt2--; + } + } + + cnt1 = cnt2 = 0; + for (int num : nums) { + if (num == num1) { + cnt1++; + } else if (num == num2) { + cnt2++; + } + } + + List res = new ArrayList<>(); + if (cnt1 > n / 3) res.add(num1); + if (cnt2 > n / 3) res.add(num2); + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector majorityElement(vector& nums) { + int n = nums.size(); + int num1 = -1, num2 = -1, cnt1 = 0, cnt2 = 0; + + for (int num : nums) { + if (num == num1) { + cnt1++; + } else if (num == num2) { + cnt2++; + } else if (cnt1 == 0) { + num1 = num; + cnt1 = 1; + } else if (cnt2 == 0) { + num2 = num; + cnt2 = 1; + } else { + cnt1--; + cnt2--; + } + } + + cnt1 = cnt2 = 0; + for (int num : nums) { + if (num == num1) cnt1++; + else if (num == num2) cnt2++; + } + + vector res; + if (cnt1 > n / 3) res.push_back(num1); + if (cnt2 > n / 3) res.push_back(num2); + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + majorityElement(nums) { + const n = nums.length; + let num1 = -1, num2 = -1, cnt1 = 0, cnt2 = 0; + + for (const num of nums) { + if (num === num1) { + cnt1++; + } else if (num === num2) { + cnt2++; + } else if (cnt1 === 0) { + cnt1 = 1; + num1 = num; + } else if (cnt2 === 0) { + cnt2 = 1; + num2 = num; + } else { + cnt1--; + cnt2--; + } + } + + cnt1 = cnt2 = 0; + for (const num of nums) { + if (num === num1) cnt1++; + else if (num === num2) cnt2++; + } + + const res = []; + if (cnt1 > Math.floor(n / 3)) res.push(num1); + if (cnt2 > Math.floor(n / 3)) res.push(num2); + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ since output array size will be at most $2$. + +--- + +## 5. Boyer-Moore Voting Algorithm (Hash Map) + +::tabs-start + +```python +class Solution: + def majorityElement(self, nums: List[int]) -> List[int]: + count = defaultdict(int) + + for num in nums: + count[num] += 1 + + if len(count) <= 2: + continue + + new_count = defaultdict(int) + for num, c in count.items(): + if c > 1: + new_count[num] = c - 1 + count = new_count + + res = [] + for num in count: + if nums.count(num) > len(nums) // 3: + res.append(num) + + return res +``` + +```java +public class Solution { + public List majorityElement(int[] nums) { + Map count = new HashMap<>(); + + for (int num : nums) { + count.put(num, count.getOrDefault(num, 0) + 1); + + if (count.size() > 2) { + Map newCount = new HashMap<>(); + for (Map.Entry entry : count.entrySet()) { + if (entry.getValue() > 1) { + newCount.put(entry.getKey(), entry.getValue() - 1); + } + } + count = newCount; + } + } + + List res = new ArrayList<>(); + for (int key : count.keySet()) { + int frequency = 0; + for (int num : nums) { + if (num == key) frequency++; + } + if (frequency > nums.length / 3) { + res.add(key); + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector majorityElement(vector& nums) { + unordered_map count; + + for (int num : nums) { + count[num]++; + + if (count.size() > 2) { + unordered_map newCount; + for (auto& entry : count) { + if (entry.second > 1) { + newCount[entry.first] = entry.second - 1; + } + } + count = newCount; + } + } + + vector res; + for (auto& entry : count) { + int frequency = 0; + for (int num : nums) { + if (num == entry.first) frequency++; + } + if (frequency > nums.size() / 3) { + res.push_back(entry.first); + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + majorityElement(nums) { + let count = new Map(); + + for (const num of nums) { + count.set(num, (count.get(num) || 0) + 1); + + if (count.size > 2) { + const newCount = new Map(); + for (const [key, value] of count.entries()) { + if (value > 1) { + newCount.set(key, value - 1); + } + } + count = newCount; + } + } + + const res = []; + for (const [key] of count.entries()) { + const frequency = nums.filter(num => num === key).length; + if (frequency > Math.floor(nums.length / 3)) { + res.push(key); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ since output array size will be at most $2$. \ No newline at end of file diff --git a/articles/minimum-number-of-operations-to-make-array-empty.md b/articles/minimum-number-of-operations-to-make-array-empty.md new file mode 100644 index 000000000..fbb2aa367 --- /dev/null +++ b/articles/minimum-number-of-operations-to-make-array-empty.md @@ -0,0 +1,563 @@ +## 1. Recursion + +::tabs-start + +```python +class Solution: + def minOperations(self, nums: List[int]) -> int: + def dfs(cur): + if cur < 0: + return float('inf') + if cur == 0: + return 0 + + ops = min(dfs(cur - 2), dfs(cur - 3)) + return 1 + ops + + count = Counter(nums) + res = 0 + for num, cnt in count.items(): + op = dfs(cnt) + if op == float("inf"): + return -1 + res += op + + return res +``` + +```java +public class Solution { + public int minOperations(int[] nums) { + Map count = new HashMap<>(); + for (int num : nums) { + count.put(num, count.getOrDefault(num, 0) + 1); + } + + int res = 0; + for (int cnt : count.values()) { + int op = dfs(cnt); + if (op == Integer.MAX_VALUE) { + return -1; + } + res += op; + } + + return res; + } + + private int dfs(int cur) { + if (cur < 0) { + return Integer.MAX_VALUE; + } + if (cur == 0) { + return 0; + } + + int ops = Math.min(dfs(cur - 2), dfs(cur - 3)); + return ops == Integer.MAX_VALUE ? ops : 1 + ops; + } +} +``` + +```cpp +class Solution { +public: + int minOperations(vector& nums) { + unordered_map count; + for (int num : nums) { + count[num]++; + } + + int res = 0; + for (auto& [num, cnt] : count) { + int op = dfs(cnt); + if (op == INT_MAX) { + return -1; + } + res += op; + } + + return res; + } + +private: + int dfs(int cur) { + if (cur < 0) { + return INT_MAX; + } + if (cur == 0) { + return 0; + } + + int ops = min(dfs(cur - 2), dfs(cur - 3)); + return ops == INT_MAX ? ops : 1 + ops; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + minOperations(nums) { + const dfs = (cur) => { + if (cur < 0) { + return Infinity; + } + if (cur === 0) { + return 0; + } + + const ops = Math.min(dfs(cur - 2), dfs(cur - 3)); + return isFinite(ops) ? 1 + ops : ops; + }; + + const count = new Map(); + for (const num of nums) { + count.set(num, (count.get(num) || 0) + 1); + } + + let res = 0; + for (const cnt of count.values()) { + const op = dfs(cnt); + if (op === Infinity) { + return -1; + } + res += op; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * 2 ^ m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ is the size of the array $nums$ and $m$ is the average frequency of the array elements. + +--- + +## 2. Dynamic Programming (Top-Down) + +::tabs-start + +```python +class Solution: + def minOperations(self, nums: List[int]) -> int: + cache = {} + + def dfs(num): + if num < 0: + return float("inf") + if num in [2, 3]: + return 1 + if num in cache: + return cache[num] + + res = min(dfs(num - 2), dfs(num - 3)) + cache[num] = res + 1 + return cache[num] + + count = Counter(nums) + res = 0 + for num, cnt in count.items(): + op = dfs(cnt) + if op == float("inf"): + return -1 + res += op + + return res +``` + +```java +public class Solution { + private Map cache; + + public int minOperations(int[] nums) { + Map count = new HashMap<>(); + for (int num : nums) { + count.put(num, count.getOrDefault(num, 0) + 1); + } + + cache = new HashMap<>(); + int res = 0; + for (int cnt : count.values()) { + int op = dfs(cnt); + if (op == Integer.MAX_VALUE) { + return -1; + } + res += op; + } + + return res; + } + + private int dfs(int cur) { + if (cur < 0) { + return Integer.MAX_VALUE; + } + if (cur == 2 || cur == 3) { + return 1; + } + if (cache.containsKey(cur)) { + return cache.get(cur); + } + + int res = Math.min(dfs(cur - 2), dfs(cur - 3)); + cache.put(cur, res == Integer.MAX_VALUE ? res : res + 1); + return cache.get(cur); + } +} +``` + +```cpp +class Solution { + unordered_map cache; +public: + int minOperations(vector& nums) { + unordered_map count; + for (int num : nums) { + count[num]++; + } + + int res = 0; + for (auto& [num, cnt] : count) { + int op = dfs(cnt); + if (op == INT_MAX) { + return -1; + } + res += op; + } + + return res; + } + +private: + int dfs(int cur) { + if (cur < 0) { + return INT_MAX; + } + if (cur == 2 || cur == 3) { + return 1; + } + if (cache.count(cur)) { + return cache[cur]; + } + + int res = min(dfs(cur - 2), dfs(cur - 3)); + cache[cur] = res == INT_MAX ? res : res + 1; + return cache[cur]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + minOperations(nums) { + const cache = new Map(); + const dfs = (cur) => { + if (cur < 0) { + return Infinity; + } + if (cur === 2 || cur === 3) { + return 1; + } + if (cache.has(cur)) { + return cache.get(cur); + } + + const res = Math.min(dfs(cur - 2), dfs(cur - 3)); + cache.set(cur, isFinite(res) ? 1 + res : res); + return cache.get(cur); + }; + + const count = new Map(); + for (const num of nums) { + count.set(num, (count.get(num) || 0) + 1); + } + + let res = 0; + for (const cnt of count.values()) { + const op = dfs(cnt); + if (!isFinite(op)) { + return -1; + } + res += op; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ is the size of the array $nums$ and $m$ is the average frequency of the array elements. + +--- + +## 3. Dynamic Programming (Bottom-Up) + +::tabs-start + +```python +class Solution: + def minOperations(self, nums: List[int]) -> int: + count = Counter(nums) + maxf = max(count.values()) + minOps = [0] * (maxf + 1) + minOps[1] = float("inf") + + for i in range(2, maxf + 1): + minOps[i] = minOps[i - 2] + if i - 3 >= 0: + minOps[i] = min(minOps[i], minOps[i - 3]) + if minOps[i] != float("inf"): + minOps[i] += 1 + + res = 0 + for num, cnt in count.items(): + op = minOps[cnt] + if op == float("inf"): + return -1 + res += op + + return res +``` + +```java +public class Solution { + public int minOperations(int[] nums) { + Map count = new HashMap<>(); + for (int num : nums) { + count.put(num, count.getOrDefault(num, 0) + 1); + } + + int maxf = count.values().stream().max(Integer::compare).orElse(0); + int[] minOps = new int[maxf + 1]; + minOps[1] = Integer.MAX_VALUE; + + for (int i = 2; i <= maxf; i++) { + minOps[i] = minOps[i - 2]; + if (i - 3 >= 0) { + minOps[i] = Math.min(minOps[i], minOps[i - 3]); + } + if (minOps[i] != Integer.MAX_VALUE) { + minOps[i] += 1; + } + } + + int res = 0; + for (int cnt : count.values()) { + int op = minOps[cnt]; + if (op == Integer.MAX_VALUE) { + return -1; + } + res += op; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int minOperations(vector& nums) { + unordered_map count; + for (int num : nums) { + count[num]++; + } + + int maxf = 0; + for (auto& [num, freq] : count) { + maxf = max(maxf, freq); + } + + vector minOps(maxf + 1, 0); + minOps[1] = INT_MAX; + + for (int i = 2; i <= maxf; i++) { + minOps[i] = minOps[i - 2]; + if (i - 3 >= 0) { + minOps[i] = min(minOps[i], minOps[i - 3]); + } + if (minOps[i] != INT_MAX) { + minOps[i] += 1; + } + } + + int res = 0; + for (auto& [num, cnt] : count) { + int op = minOps[cnt]; + if (op == INT_MAX) { + return -1; + } + res += op; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + minOperations(nums) { + const count = new Map(); + for (const num of nums) { + count.set(num, (count.get(num) || 0) + 1); + } + + const maxf = Math.max(...count.values()); + const minOps = Array(maxf + 1).fill(0); + minOps[1] = Infinity; + + for (let i = 2; i <= maxf; i++) { + minOps[i] = minOps[i - 2]; + if (i - 3 >= 0) { + minOps[i] = Math.min(minOps[i], minOps[i - 3]); + } + if (minOps[i] !== Infinity) { + minOps[i] += 1; + } + } + + let res = 0; + for (const cnt of count.values()) { + const op = minOps[cnt]; + if (op === Infinity) { + return -1; + } + res += op; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ is the size of the array $nums$ and $m$ is the average frequency of the array elements. + +--- + +## 4. Greedy + +::tabs-start + +```python +class Solution: + def minOperations(self, nums: List[int]) -> int: + count = Counter(nums) + res = 0 + + for num, cnt in count.items(): + if cnt == 1: + return -1 + res += math.ceil(cnt / 3) + + return res +``` + +```java +public class Solution { + public int minOperations(int[] nums) { + Map count = new HashMap<>(); + for (int num : nums) { + count.put(num, count.getOrDefault(num, 0) + 1); + } + + int res = 0; + for (int cnt : count.values()) { + if (cnt == 1) { + return -1; + } + res += (cnt + 2) / 3; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int minOperations(vector& nums) { + unordered_map count; + for (int num : nums) { + count[num]++; + } + + int res = 0; + for (auto& [num, cnt] : count) { + if (cnt == 1) { + return -1; + } + res += (cnt + 2) / 3; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + minOperations(nums) { + const count = new Map(); + for (const num of nums) { + count.set(num, (count.get(num) || 0) + 1); + } + + let res = 0; + for (const cnt of count.values()) { + if (cnt === 1) { + return -1; + } + res += Math.ceil(cnt / 3); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/minimum-penalty-for-a-shop.md b/articles/minimum-penalty-for-a-shop.md new file mode 100644 index 000000000..a3e506a88 --- /dev/null +++ b/articles/minimum-penalty-for-a-shop.md @@ -0,0 +1,497 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def bestClosingTime(self, customers: str) -> int: + n = len(customers) + res = n + minPenalty = n + + for i in range(n + 1): + penalty = 0 + for j in range(i): + if customers[j] == 'N': + penalty += 1 + for j in range(i, n): + if customers[j] == 'Y': + penalty += 1 + + if penalty < minPenalty: + minPenalty = penalty + res = i + + return res +``` + +```java +public class Solution { + public int bestClosingTime(String customers) { + int n = customers.length(); + int res = n, minPenalty = n; + + for (int i = 0; i <= n; i++) { + int penalty = 0; + for (int j = 0; j < i; j++) { + if (customers.charAt(j) == 'N') { + penalty++; + } + } + for (int j = i; j < n; j++) { + if (customers.charAt(j) == 'Y') { + penalty++; + } + } + + if (penalty < minPenalty) { + minPenalty = penalty; + res = i; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int bestClosingTime(string customers) { + int n = customers.size(); + int res = n, minPenalty = n; + + for (int i = 0; i <= n; i++) { + int penalty = 0; + for (int j = 0; j < i; j++) { + if (customers[j] == 'N') { + penalty++; + } + } + for (int j = i; j < n; j++) { + if (customers[j] == 'Y') { + penalty++; + } + } + + if (penalty < minPenalty) { + minPenalty = penalty; + res = i; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} customers + * @return {number} + */ + bestClosingTime(customers) { + const n = customers.length; + let res = n, minPenalty = n; + + for (let i = 0; i <= n; i++) { + let penalty = 0; + for (let j = 0; j < i; j++) { + if (customers[j] === 'N') { + penalty++; + } + } + for (let j = i; j < n; j++) { + if (customers[j] === 'Y') { + penalty++; + } + } + + if (penalty < minPenalty) { + minPenalty = penalty; + res = i; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Prefix & Suffix + +::tabs-start + +```python +class Solution: + def bestClosingTime(self, customers: str) -> int: + n = len(customers) + cnt = 0 + + prefixN = [] + for c in customers: + prefixN.append(cnt) + if c == 'N': + cnt += 1 + prefixN.append(cnt) + + suffixY = [0] * (n + 1) + for i in range(n - 1, -1, -1): + suffixY[i] = suffixY[i + 1] + if customers[i] == 'Y': + suffixY[i] += 1 + + res = n + minPenalty = n + for i in range(n + 1): + penalty = prefixN[i] + suffixY[i] + if penalty < minPenalty: + minPenalty = penalty + res = i + + return res +``` + +```java +public class Solution { + public int bestClosingTime(String customers) { + int n = customers.length(); + int cnt = 0; + + int[] prefixN = new int[n + 1]; + for (int i = 0; i < n; i++) { + prefixN[i] = cnt; + if (customers.charAt(i) == 'N') { + cnt++; + } + } + prefixN[n] = cnt; + + int[] suffixY = new int[n + 1]; + for (int i = n - 1; i >= 0; i--) { + suffixY[i] = suffixY[i + 1]; + if (customers.charAt(i) == 'Y') { + suffixY[i]++; + } + } + + int res = n, minPenalty = n; + for (int i = 0; i <= n; i++) { + int penalty = prefixN[i] + suffixY[i]; + if (penalty < minPenalty) { + minPenalty = penalty; + res = i; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int bestClosingTime(string customers) { + int n = customers.size(), cnt = 0; + + vector prefixN(n + 1); + for (int i = 0; i < n; i++) { + prefixN[i] = cnt; + if (customers[i] == 'N') { + cnt++; + } + } + prefixN[n] = cnt; + + vector suffixY(n + 1, 0); + for (int i = n - 1; i >= 0; i--) { + suffixY[i] = suffixY[i + 1]; + if (customers[i] == 'Y') { + suffixY[i]++; + } + } + + int res = n, minPenalty = n; + for (int i = 0; i <= n; i++) { + int penalty = prefixN[i] + suffixY[i]; + if (penalty < minPenalty) { + minPenalty = penalty; + res = i; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} customers + * @return {number} + */ + bestClosingTime(customers) { + const n = customers.length; + let cnt = 0; + + const prefixN = []; + for (const c of customers) { + prefixN.push(cnt); + if (c === 'N') { + cnt++; + } + } + prefixN.push(cnt); + + const suffixY = new Array(n + 1).fill(0); + for (let i = n - 1; i >= 0; i--) { + suffixY[i] = suffixY[i + 1]; + if (customers[i] === 'Y') { + suffixY[i]++; + } + } + + let res = n, minPenalty = n; + for (let i = 0; i <= n; i++) { + const penalty = prefixN[i] + suffixY[i]; + if (penalty < minPenalty) { + minPenalty = penalty; + res = i; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Iteration (Two Pass) + +::tabs-start + +```python +class Solution: + def bestClosingTime(self, customers: str) -> int: + cntY = sum(c == "Y" for c in customers) + + minPenalty = cntY + res = cntN = 0 + for i, c in enumerate(customers): + if c == "Y": + cntY -= 1 + else: + cntN += 1 + + penalty = cntN + cntY + if penalty < minPenalty: + res = i + 1 + minPenalty = penalty + + return res +``` + +```java +public class Solution { + public int bestClosingTime(String customers) { + int cntY = 0; + for (char c : customers.toCharArray()) { + if (c == 'Y') cntY++; + } + + int minPenalty = cntY, res = 0, cntN = 0; + for (int i = 0; i < customers.length(); i++) { + if (customers.charAt(i) == 'Y') { + cntY--; + } else { + cntN++; + } + + int penalty = cntN + cntY; + if (penalty < minPenalty) { + res = i + 1; + minPenalty = penalty; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int bestClosingTime(string customers) { + int cntY = count(customers.begin(), customers.end(), 'Y'); + + int minPenalty = cntY, res = 0, cntN = 0; + for (int i = 0; i < customers.size(); i++) { + if (customers[i] == 'Y') { + cntY--; + } else { + cntN++; + } + + int penalty = cntN + cntY; + if (penalty < minPenalty) { + res = i + 1; + minPenalty = penalty; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} customers + * @return {number} + */ + bestClosingTime(customers) { + let cntY = 0; + for (let c of customers) { + if (c === 'Y') cntY++; + } + + let minPenalty = cntY, res = 0, cntN = 0; + for (let i = 0; i < customers.length; i++) { + if (customers[i] === 'Y') { + cntY--; + } else { + cntN++; + } + + const penalty = cntN + cntY; + if (penalty < minPenalty) { + res = i + 1; + minPenalty = penalty; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 4. Iteration (One Pass) + +::tabs-start + +```python +class Solution: + def bestClosingTime(self, customers: str) -> int: + res = minPenalty = 0 + penalty = 0 + + for i, c in enumerate(customers): + penalty += 1 if c == 'Y' else -1 + + if penalty > minPenalty: + minPenalty = penalty + res = i + 1 + + return res +``` + +```java +public class Solution { + public int bestClosingTime(String customers) { + int res = 0, minPenalty = 0, penalty = 0; + + for (int i = 0; i < customers.length(); i++) { + penalty += customers.charAt(i) == 'Y' ? 1 : -1; + + if (penalty > minPenalty) { + minPenalty = penalty; + res = i + 1; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int bestClosingTime(string customers) { + int res = 0, minPenalty = 0, penalty = 0; + + for (int i = 0; i < customers.size(); i++) { + penalty += customers[i] == 'Y' ? 1 : -1; + + if (penalty > minPenalty) { + minPenalty = penalty; + res = i + 1; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} customers + * @return {number} + */ + bestClosingTime(customers) { + let res = 0, minPenalty = 0, penalty = 0; + + for (let i = 0; i < customers.length; i++) { + penalty += customers[i] === 'Y' ? 1 : -1; + + if (penalty > minPenalty) { + minPenalty = penalty; + res = i + 1; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/non-decreasing-array.md b/articles/non-decreasing-array.md new file mode 100644 index 000000000..aed007f6c --- /dev/null +++ b/articles/non-decreasing-array.md @@ -0,0 +1,105 @@ +## 1. Greedy + +::tabs-start + +```python +class Solution: + def checkPossibility(self, nums: list[int]) -> bool: + changed = False + + for i in range(len(nums) - 1): + if nums[i] <= nums[i + 1]: + continue + if changed: + return False + if i == 0 or nums[i + 1] >= nums[i - 1]: + nums[i] = nums[i + 1] + else: + nums[i + 1] = nums[i] + changed = True + return True +``` + +```java +public class Solution { + public boolean checkPossibility(int[] nums) { + boolean changed = false; + + for (int i = 0; i < nums.length - 1; i++) { + if (nums[i] <= nums[i + 1]) { + continue; + } + if (changed) { + return false; + } + if (i == 0 || nums[i + 1] >= nums[i - 1]) { + nums[i] = nums[i + 1]; + } else { + nums[i + 1] = nums[i]; + } + changed = true; + } + return true; + } +} +``` + +```cpp +class Solution { +public: + bool checkPossibility(vector& nums) { + bool changed = false; + + for (int i = 0; i < nums.size() - 1; i++) { + if (nums[i] <= nums[i + 1]) { + continue; + } + if (changed) { + return false; + } + if (i == 0 || nums[i + 1] >= nums[i - 1]) { + nums[i] = nums[i + 1]; + } else { + nums[i + 1] = nums[i]; + } + changed = true; + } + return true; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + checkPossibility(nums) { + let changed = false; + + for (let i = 0; i < nums.length - 1; i++) { + if (nums[i] <= nums[i + 1]) { + continue; + } + if (changed) { + return false; + } + if (i === 0 || nums[i + 1] >= nums[i - 1]) { + nums[i] = nums[i + 1]; + } else { + nums[i + 1] = nums[i]; + } + changed = true; + } + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/number-of-zero-filled-subarrays.md b/articles/number-of-zero-filled-subarrays.md new file mode 100644 index 000000000..266353c04 --- /dev/null +++ b/articles/number-of-zero-filled-subarrays.md @@ -0,0 +1,338 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def zeroFilledSubarray(self, nums: List[int]) -> int: + res = 0 + for i in range(len(nums)): + for j in range(i, len(nums)): + if nums[j] != 0: + break + res += 1 + return res +``` + +```java +public class Solution { + public long zeroFilledSubarray(int[] nums) { + long res = 0; + for (int i = 0; i < nums.length; i++) { + for (int j = i; j < nums.length; j++) { + if (nums[j] != 0) break; + res++; + } + } + return res; + } +} +``` + +```cpp +class Solution { +public: + long long zeroFilledSubarray(vector& nums) { + long long res = 0; + for (int i = 0; i < nums.size(); i++) { + for (int j = i; j < nums.size(); j++) { + if (nums[j] != 0) break; + res++; + } + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + zeroFilledSubarray(nums) { + let res = 0; + for (let i = 0; i < nums.length; i++) { + for (let j = i; j < nums.length; j++) { + if (nums[j] != 0) break; + res++; + } + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Count Consecutive Zeros - I + +::tabs-start + +```python +class Solution: + def zeroFilledSubarray(self, nums: List[int]) -> int: + res = i = 0 + while i < len(nums): + count = 0 + while i < len(nums) and nums[i] == 0: + count += 1 + i += 1 + res += count + i += 1 + return res +``` + +```java +public class Solution { + public long zeroFilledSubarray(int[] nums) { + long res = 0; + int i = 0; + while (i < nums.length) { + long count = 0; + while (i < nums.length && nums[i] == 0) { + count++; + i++; + res += count; + } + i++; + } + return res; + } +} +``` + +```cpp +class Solution { +public: + long long zeroFilledSubarray(vector& nums) { + long long res = 0; + int i = 0; + while (i < nums.size()) { + long long count = 0; + while (i < nums.size() && nums[i] == 0) { + count++; + i++; + res += count; + } + i++; + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + zeroFilledSubarray(nums) { + let res = 0, i = 0; + while (i < nums.length) { + let count = 0; + while (i < nums.length && nums[i] === 0) { + count++; + i++; + res += count; + } + i++; + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 3. Count Consecutive Zeros - II + +::tabs-start + +```python +class Solution: + def zeroFilledSubarray(self, nums: List[int]) -> int: + res = count = 0 + + for num in nums: + if num == 0: + count += 1 + else: + count = 0 + res += count + + return res +``` + +```java +public class Solution { + public long zeroFilledSubarray(int[] nums) { + long res = 0; + int count = 0; + + for (int num : nums) { + if (num == 0) { + count++; + } else { + count = 0; + } + res += count; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + long long zeroFilledSubarray(vector& nums) { + long long res = 0; + int count = 0; + + for (int& num : nums) { + if (num == 0) { + count++; + } else { + count = 0; + } + res += count; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + zeroFilledSubarray(nums) { + let res = 0, count = 0; + + for (let num of nums) { + if (num === 0) { + count++; + } else { + count = 0; + } + res += count; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 4. Count Consecutive Zeros (Math) + +::tabs-start + +```python +class Solution: + def zeroFilledSubarray(self, nums: List[int]) -> int: + res = count = 0 + for num in nums: + if num == 0: + count += 1 + else: + res += (count * (count + 1)) // 2 + count = 0 + res += (count * (count + 1)) // 2 + return res +``` + +```java +public class Solution { + public long zeroFilledSubarray(int[] nums) { + long res = 0, count = 0; + for (int num : nums) { + if (num == 0) { + count++; + } else { + res += count * (count + 1) / 2; + count = 0; + } + } + res += count * (count + 1) / 2; + return res; + } +} +``` + +```cpp +class Solution { +public: + long long zeroFilledSubarray(vector& nums) { + long long res = 0, count = 0; + for (int num : nums) { + if (num == 0) { + count++; + } else { + res += count * (count + 1) / 2; + count = 0; + } + } + res += count * (count + 1) / 2; + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + zeroFilledSubarray(nums) { + let res = 0, count = 0; + for (let num of nums) { + if (num === 0) { + count++; + } else { + res += (count * (count + 1)) / 2; + count = 0; + } + } + res += (count * (count + 1)) / 2; + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/optimal-partition-of-string.md b/articles/optimal-partition-of-string.md new file mode 100644 index 000000000..c4d89ab77 --- /dev/null +++ b/articles/optimal-partition-of-string.md @@ -0,0 +1,250 @@ +## 1. Greedy (Hash Set) + +::tabs-start + +```python +class Solution: + def partitionString(self, s: str) -> int: + curSet = set() + res = 1 + for c in s: + if c in curSet: + res += 1 + curSet.clear() + curSet.add(c) + return res +``` + +```java +public class Solution { + public int partitionString(String s) { + Set curSet = new HashSet<>(); + int res = 1; + for (char c : s.toCharArray()) { + if (curSet.contains(c)) { + res++; + curSet.clear(); + } + curSet.add(c); + } + return res; + } +} +``` + +```cpp +class Solution { +public: + int partitionString(string s) { + unordered_set curSet; + int res = 1; + for (char c : s) { + if (curSet.count(c)) { + res++; + curSet.clear(); + } + curSet.insert(c); + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number} + */ + partitionString(s) { + let curSet = new Set(); + let res = 1; + for (let c of s) { + if (curSet.has(c)) { + res++; + curSet.clear(); + } + curSet.add(c); + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ since we have at most $26$ different characters. + +--- + +## 2. Greedy (Array) + +::tabs-start + +```python +class Solution: + def partitionString(self, s: str) -> int: + lastIdx = [-1] * 26 + res = 1 + start = 0 + for i, c in enumerate(s): + j = ord(c) - ord('a') + if lastIdx[j] >= start: + start = i + res += 1 + lastIdx[j] = i + return res +``` + +```java +public class Solution { + public int partitionString(String s) { + int[] lastIdx = new int[26]; + Arrays.fill(lastIdx, -1); + int res = 1, start = 0; + for (int i = 0; i < s.length(); i++) { + int j = s.charAt(i) - 'a'; + if (lastIdx[j] >= start) { + start = i; + res++; + } + lastIdx[j] = i; + } + return res; + } +} +``` + +```cpp +class Solution { +public: + int partitionString(string s) { + vector lastIdx(26, -1); + int res = 1, start = 0; + for (int i = 0; i < s.size(); i++) { + int j = s[i] - 'a'; + if (lastIdx[j] >= start) { + start = i; + res++; + } + lastIdx[j] = i; + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number} + */ + partitionString(s) { + const lastIdx = Array(26).fill(-1); + let res = 1, start = 0; + for (let i = 0; i < s.length; i++) { + const j = s.charCodeAt(i) - 97; + if (lastIdx[j] >= start) { + start = i; + res++; + } + lastIdx[j] = i; + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ since we have at most $26$ different characters. + +--- + +## 3. Greedy (Bit Mask) + +::tabs-start + +```python +class Solution: + def partitionString(self, s: str) -> int: + res = 1 + mask = 0 + for c in s: + i = ord(c) - ord('a') + if mask & (1 << i): + mask = 0 + res += 1 + mask |= (1 << i) + return res +``` + +```java +public class Solution { + public int partitionString(String s) { + int res = 1, mask = 0; + for (char c : s.toCharArray()) { + int i = c - 'a'; + if ((mask & (1 << i)) != 0) { + mask = 0; + res++; + } + mask |= (1 << i); + } + return res; + } +} +``` + +```cpp +class Solution { +public: + int partitionString(string s) { + int res = 1, mask = 0; + for (char c : s) { + int i = c - 'a'; + if (mask & (1 << i)) { + mask = 0; + res++; + } + mask |= (1 << i); + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number} + */ + partitionString(s) { + let res = 1, mask = 0; + for (const c of s) { + const i = c.charCodeAt(0) - 97; + if (mask & (1 << i)) { + mask = 0; + res++; + } + mask |= (1 << i); + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/range-sum-query-2d-immutable.md b/articles/range-sum-query-2d-immutable.md new file mode 100644 index 000000000..3d19e47b0 --- /dev/null +++ b/articles/range-sum-query-2d-immutable.md @@ -0,0 +1,369 @@ +## 1. Brute Force + +::tabs-start + +```python +class NumMatrix: + + def __init__(self, matrix: list[list[int]]): + self.matrix = matrix + + def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int: + res = 0 + for r in range(row1, row2 + 1): + for c in range(col1, col2 + 1): + res += self.matrix[r][c] + return res +``` + +```java +public class NumMatrix { + + private int[][] matrix; + + public NumMatrix(int[][] matrix) { + this.matrix = matrix; + } + + public int sumRegion(int row1, int col1, int row2, int col2) { + int res = 0; + for (int r = row1; r <= row2; r++) { + for (int c = col1; c <= col2; c++) { + res += matrix[r][c]; + } + } + return res; + } +} +``` + +```cpp +class NumMatrix { +private: + vector> matrix; + +public: + NumMatrix(vector>& matrix) { + this->matrix = matrix; + } + + int sumRegion(int row1, int col1, int row2, int col2) { + int res = 0; + for (int r = row1; r <= row2; r++) { + for (int c = col1; c <= col2; c++) { + res += matrix[r][c]; + } + } + return res; + } +}; +``` + +```javascript +class NumMatrix { + /** + * @param {number[][]} matrix + */ + constructor(matrix) { + this.matrix = matrix; + } + + /** + * @param {number} row1 + * @param {number} col1 + * @param {number} row2 + * @param {number} col2 + * @return {number} + */ + sumRegion(row1, col1, row2, col2) { + let res = 0; + for (let r = row1; r <= row2; r++) { + for (let c = col1; c <= col2; c++) { + res += this.matrix[r][c]; + } + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(m * n)$ for each query. +* Space complexity: $O(1)$ + +> Where $m$ is the number of rows and $n$ is the number of columns in the matrix. + +--- + +## 2. One Dimensional Prefix Sum + +::tabs-start + +```python +class NumMatrix: + + def __init__(self, matrix: list[list[int]]): + self.prefixSum = [[0] * len(matrix[0]) for _ in range(len(matrix))] + + for row in range(len(matrix)): + self.prefixSum[row][0] = matrix[row][0] + for col in range(1, len(matrix[0])): + self.prefixSum[row][col] = self.prefixSum[row][col - 1] + matrix[row][col] + + def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int: + res = 0 + for row in range(row1, row2 + 1): + if col1 > 0: + res += self.prefixSum[row][col2] - self.prefixSum[row][col1 - 1] + else: + res += self.prefixSum[row][col2] + return res +``` + +```java +public class NumMatrix { + + private int[][] prefixSum; + + public NumMatrix(int[][] matrix) { + int rows = matrix.length, cols = matrix[0].length; + prefixSum = new int[rows][cols]; + + for (int row = 0; row < rows; row++) { + prefixSum[row][0] = matrix[row][0]; + for (int col = 1; col < cols; col++) { + prefixSum[row][col] = prefixSum[row][col - 1] + matrix[row][col]; + } + } + } + + public int sumRegion(int row1, int col1, int row2, int col2) { + int res = 0; + for (int row = row1; row <= row2; row++) { + if (col1 > 0) { + res += prefixSum[row][col2] - prefixSum[row][col1 - 1]; + } else { + res += prefixSum[row][col2]; + } + } + return res; + } +} +``` + +```cpp +class NumMatrix { +private: + vector> prefixSum; + +public: + NumMatrix(vector>& matrix) { + int rows = matrix.size(), cols = matrix[0].size(); + prefixSum = vector>(rows, vector(cols, 0)); + + for (int row = 0; row < rows; row++) { + prefixSum[row][0] = matrix[row][0]; + for (int col = 1; col < cols; col++) { + prefixSum[row][col] = prefixSum[row][col - 1] + matrix[row][col]; + } + } + } + + int sumRegion(int row1, int col1, int row2, int col2) { + int res = 0; + for (int row = row1; row <= row2; row++) { + if (col1 > 0) { + res += prefixSum[row][col2] - prefixSum[row][col1 - 1]; + } else { + res += prefixSum[row][col2]; + } + } + return res; + } +}; +``` + +```javascript +class NumMatrix { + /** + * @param {number[][]} matrix + */ + constructor(matrix) { + this.prefixSum = Array.from({ length: matrix.length }, () => Array(matrix[0].length).fill(0)); + + for (let row = 0; row < matrix.length; row++) { + this.prefixSum[row][0] = matrix[row][0]; + for (let col = 1; col < matrix[0].length; col++) { + this.prefixSum[row][col] = this.prefixSum[row][col - 1] + matrix[row][col]; + } + } + } + + /** + * @param {number} row1 + * @param {number} col1 + * @param {number} row2 + * @param {number} col2 + * @return {number} + */ + sumRegion(row1, col1, row2, col2) { + let res = 0; + for (let row = row1; row <= row2; row++) { + if (col1 > 0) { + res += this.prefixSum[row][col2] - this.prefixSum[row][col1 - 1]; + } else { + res += this.prefixSum[row][col2]; + } + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(m)$ +* Space complexity: $O(m * n)$ + +> Where $m$ is the number of rows and $n$ is the number of columns in the matrix. + +--- + +## 3. Two Dimensional Prefix Sum + +::tabs-start + +```python +class NumMatrix: + + def __init__(self, matrix: list[list[int]]): + ROWS, COLS = len(matrix), len(matrix[0]) + self.sumMat = [[0] * (COLS + 1) for _ in range(ROWS + 1)] + + for r in range(ROWS): + prefix = 0 + for c in range(COLS): + prefix += matrix[r][c] + above = self.sumMat[r][c + 1] + self.sumMat[r + 1][c + 1] = prefix + above + + def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int: + row1, col1, row2, col2 = row1 + 1, col1 + 1, row2 + 1, col2 + 1 + bottomRight = self.sumMat[row2][col2] + above = self.sumMat[row1 - 1][col2] + left = self.sumMat[row2][col1 - 1] + topLeft = self.sumMat[row1 - 1][col1 - 1] + return bottomRight - above - left + topLeft +``` + +```java +public class NumMatrix { + + private int[][] sumMat; + + public NumMatrix(int[][] matrix) { + int ROWS = matrix.length, COLS = matrix[0].length; + sumMat = new int[ROWS + 1][COLS + 1]; + + for (int r = 0; r < ROWS; r++) { + int prefix = 0; + for (int c = 0; c < COLS; c++) { + prefix += matrix[r][c]; + int above = sumMat[r][c + 1]; + sumMat[r + 1][c + 1] = prefix + above; + } + } + } + + public int sumRegion(int row1, int col1, int row2, int col2) { + row1++; col1++; row2++; col2++; + int bottomRight = sumMat[row2][col2]; + int above = sumMat[row1 - 1][col2]; + int left = sumMat[row2][col1 - 1]; + int topLeft = sumMat[row1 - 1][col1 - 1]; + return bottomRight - above - left + topLeft; + } +} +``` + +```cpp +class NumMatrix { +private: + vector> sumMat; + +public: + NumMatrix(vector>& matrix) { + int ROWS = matrix.size(), COLS = matrix[0].size(); + sumMat = vector>(ROWS + 1, vector(COLS + 1, 0)); + + for (int r = 0; r < ROWS; r++) { + int prefix = 0; + for (int c = 0; c < COLS; c++) { + prefix += matrix[r][c]; + int above = sumMat[r][c + 1]; + sumMat[r + 1][c + 1] = prefix + above; + } + } + } + + int sumRegion(int row1, int col1, int row2, int col2) { + row1++; col1++; row2++; col2++; + int bottomRight = sumMat[row2][col2]; + int above = sumMat[row1 - 1][col2]; + int left = sumMat[row2][col1 - 1]; + int topLeft = sumMat[row1 - 1][col1 - 1]; + return bottomRight - above - left + topLeft; + } +}; +``` + +```javascript +class NumMatrix { + /** + * @param {number[][]} matrix + */ + constructor(matrix) { + const ROWS = matrix.length, COLS = matrix[0].length; + this.sumMat = Array.from({ length: ROWS + 1 }, () => Array(COLS + 1).fill(0)); + + for (let r = 0; r < ROWS; r++) { + let prefix = 0; + for (let c = 0; c < COLS; c++) { + prefix += matrix[r][c]; + const above = this.sumMat[r][c + 1]; + this.sumMat[r + 1][c + 1] = prefix + above; + } + } + } + + /** + * @param {number} row1 + * @param {number} col1 + * @param {number} row2 + * @param {number} col2 + * @return {number} + */ + sumRegion(row1, col1, row2, col2) { + row1++; col1++; row2++; col2++; + const bottomRight = this.sumMat[row2][col2]; + const above = this.sumMat[row1 - 1][col2]; + const left = this.sumMat[row2][col1 - 1]; + const topLeft = this.sumMat[row1 - 1][col1 - 1]; + return bottomRight - above - left + topLeft; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(1)$ for each query. +* Space complexity: $O(m * n)$ + +> Where $m$ is the number of rows and $n$ is the number of columns in the matrix. \ No newline at end of file diff --git a/articles/repeated-dna-sequences.md b/articles/repeated-dna-sequences.md new file mode 100644 index 000000000..6976f8850 --- /dev/null +++ b/articles/repeated-dna-sequences.md @@ -0,0 +1,470 @@ +## 1. Hash Set + +::tabs-start + +```python +class Solution: + def findRepeatedDnaSequences(self, s: str) -> List[str]: + seen, res = set(), set() + + for l in range(len(s) - 9): + cur = s[l: l + 10] + if cur in seen: + res.add(cur) + seen.add(cur) + return list(res) +``` + +```java +public class Solution { + public List findRepeatedDnaSequences(String s) { + Set seen = new HashSet<>(); + Set res = new HashSet<>(); + + for (int l = 0; l < s.length() - 9; l++) { + String cur = s.substring(l, l + 10); + if (seen.contains(cur)) { + res.add(cur); + } + seen.add(cur); + } + return new ArrayList<>(res); + } +} +``` + +```cpp +class Solution { +public: + vector findRepeatedDnaSequences(string s) { + if (s.size() < 10) return {}; + unordered_set seen, res; + + for (int l = 0; l < s.size() - 9; l++) { + string cur = s.substr(l, 10); + if (seen.count(cur)) { + res.insert(cur); + } + seen.insert(cur); + } + return vector(res.begin(), res.end()); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string[]} + */ + findRepeatedDnaSequences(s) { + const seen = new Set(); + const res = new Set(); + + for (let l = 0; l < s.length - 9; l++) { + const cur = s.substring(l, l + 10); + if (seen.has(cur)) { + res.add(cur); + } + seen.add(cur); + } + return Array.from(res); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Hash Map + +::tabs-start + +```python +class Solution: + def findRepeatedDnaSequences(self, s: str) -> List[str]: + if len(s) < 10: + return [] + + mp = defaultdict(int) + res = [] + for l in range(len(s) - 9): + cur = s[l: l + 10] + mp[cur] += 1 + if mp[cur] == 2: + res.append(cur) + + return res +``` + +```java +public class Solution { + public List findRepeatedDnaSequences(String s) { + if (s.length() < 10) { + return new ArrayList<>(); + } + + Map mp = new HashMap<>(); + List res = new ArrayList<>(); + + for (int l = 0; l < s.length() - 9; l++) { + String cur = s.substring(l, l + 10); + mp.put(cur, mp.getOrDefault(cur, 0) + 1); + if (mp.get(cur) == 2) { + res.add(cur); + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector findRepeatedDnaSequences(string s) { + if (s.size() < 10) { + return {}; + } + + unordered_map mp; + vector res; + + for (int l = 0; l < s.size() - 9; l++) { + string cur = s.substr(l, 10); + mp[cur]++; + if (mp[cur] == 2) { + res.push_back(cur); + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string[]} + */ + findRepeatedDnaSequences(s) { + if (s.length < 10) { + return []; + } + + const mp = new Map(); + const res = []; + + for (let l = 0; l <= s.length - 10; l++) { + const cur = s.substring(l, l + 10); + mp.set(cur, (mp.get(cur) || 0) + 1); + if (mp.get(cur) === 2) { + res.push(cur); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Rabin-Karp Algorithm (Double Hashing) + +::tabs-start + +```python +class Solution: + def findRepeatedDnaSequences(self, s: str) -> List[str]: + n = len(s) + if n < 10: + return [] + + cnt = defaultdict(int) + res = [] + base1, base2 = 31, 37 + hash1 = hash2 = 0 + power1, power2 = 1, 1 + MOD1, MOD2 = 685683731, 768258391 + + for i in range(9): + power1 *= base1 + power2 *= base2 + power1 %= MOD1 + power2 %= MOD2 + + for i in range(n): + hash1 = (hash1 * base1 + ord(s[i])) % MOD1 + hash2 = (hash2 * base2 + ord(s[i])) % MOD2 + + if i >= 9: + key = (hash1 << 31) | hash2 + cnt[key] += 1 + if cnt[key] == 2: + res.append(s[i - 9 : i + 1]) + + hash1 = (hash1 - power1 * ord(s[i - 9]) % MOD1 + MOD1) % MOD1 + hash2 = (hash2 - power2 * ord(s[i - 9]) % MOD2 + MOD2) + + return res +``` + +```java +public class Solution { + public List findRepeatedDnaSequences(String s) { + int n = s.length(); + if (n < 10) return new ArrayList<>(); + + Map cnt = new HashMap<>(); + List res = new ArrayList<>(); + int base1 = 31, base2 = 37; + long hash1 = 0, hash2 = 0, power1 = 1, power2 = 1; + int MOD1 = 685683731, MOD2 = 768258391; + + for (int i = 0; i < 9; i++) { + power1 = (power1 * base1) % MOD1; + power2 = (power2 * base2) % MOD2; + } + + for (int i = 0; i < n; i++) { + hash1 = (hash1 * base1 + s.charAt(i)) % MOD1; + hash2 = (hash2 * base2 + s.charAt(i)) % MOD2; + + if (i >= 9) { + long key = (hash1 << 31) | hash2; + cnt.put(key, cnt.getOrDefault(key, 0) + 1); + if (cnt.get(key) == 2) { + res.add(s.substring(i - 9, i + 1)); + } + + hash1 = (hash1 - power1 * s.charAt(i - 9) % MOD1 + MOD1) % MOD1; + hash2 = (hash2 - power2 * s.charAt(i - 9) % MOD2 + MOD2) % MOD2; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector findRepeatedDnaSequences(string s) { + int n = s.length(); + if (n < 10) return {}; + + unordered_map cnt; + vector res; + int base1 = 31, base2 = 37; + long long hash1 = 0, hash2 = 0, power1 = 1, power2 = 1; + int MOD1 = 685683731, MOD2 = 768258391; + + for (int i = 0; i < 9; i++) { + power1 = (power1 * base1) % MOD1; + power2 = (power2 * base2) % MOD2; + } + + for (int i = 0; i < n; i++) { + hash1 = (hash1 * base1 + s[i]) % MOD1; + hash2 = (hash2 * base2 + s[i]) % MOD2; + + if (i >= 9) { + long long key = (hash1 << 31) | hash2; + cnt[key]++; + if (cnt[key] == 2) { + res.push_back(s.substr(i - 9, 10)); + } + + hash1 = (hash1 - power1 * s[i - 9] % MOD1 + MOD1) % MOD1; + hash2 = (hash2 - power2 * s[i - 9] % MOD2 + MOD2) % MOD2; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string[]} + */ + findRepeatedDnaSequences(s) { + const n = s.length; + if (n < 10) return []; + + const cnt = new Map(); + const res = []; + const base1 = 31, base2 = 37; + let hash1 = 0, hash2 = 0, power1 = 1, power2 = 1; + const MOD1 = 685683731, MOD2 = 768258391; + + for (let i = 0; i < 9; i++) { + power1 = (power1 * base1) % MOD1; + power2 = (power2 * base2) % MOD2; + } + + for (let i = 0; i < n; i++) { + hash1 = (hash1 * base1 + s.charCodeAt(i)) % MOD1; + hash2 = (hash2 * base2 + s.charCodeAt(i)) % MOD2; + + if (i >= 9) { + const key = `${hash1},${hash2}`; + cnt.set(key, (cnt.get(key) || 0) + 1); + if (cnt.get(key) === 2) { + res.push(s.substring(i - 9, i + 1)); + } + + hash1 = (hash1 - power1 * s.charCodeAt(i - 9) % MOD1 + MOD1) % MOD1; + hash2 = (hash2 - power2 * s.charCodeAt(i - 9) % MOD2 + MOD2) % MOD2; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. Bit Mask + +::tabs-start + +```python +class Solution: + def findRepeatedDnaSequences(self, s: str) -> list[str]: + if len(s) < 10: + return [] + + mp = {'A': 0, 'C': 1, 'G': 2, 'T': 3} + seen, res = set(), set() + mask = 0 + for i in range(len(s)): + mask = ((mask << 2) | mp[s[i]]) & 0xFFFFF + if i >= 9: + if mask in seen: + res.add(s[i - 9: i + 1]) + else: + seen.add(mask) + + return list(res) +``` + +```java +public class Solution { + public List findRepeatedDnaSequences(String s) { + if (s.length() < 10) return new ArrayList<>(); + + Map mp = Map.of('A', 0, 'C', 1, 'G', 2, 'T', 3); + Map cnt = new HashMap<>(); + List res = new ArrayList<>(); + int mask = 0; + + for (int i = 0; i < s.length(); i++) { + mask = ((mask << 2) | mp.get(s.charAt(i))) & 0xFFFFF; + if (i >= 9) { + cnt.put(mask, cnt.getOrDefault(mask, 0) + 1); + if (cnt.get(mask) == 2) { + res.add(s.substring(i - 9, i + 1)); + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector findRepeatedDnaSequences(string s) { + if (s.length() < 10) return {}; + + unordered_map mp = {{'A', 0}, {'C', 1}, + {'G', 2}, {'T', 3}}; + unordered_map cnt; + vector res; + int mask = 0; + + for (int i = 0; i < s.size(); i++) { + mask = ((mask << 2) | mp[s[i]]) & 0xFFFFF; + + if (i >= 9) { + cnt[mask]++; + if (cnt[mask] == 2) { + res.push_back(s.substr(i - 9, 10)); + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string[]} + */ + findRepeatedDnaSequences(s) { + if (s.length < 10) return []; + + const mp = { 'A': 0, 'C': 1, 'G': 2, 'T': 3 }; + const cnt = new Map(); + const res = []; + let mask = 0; + + for (let i = 0; i < s.length; i++) { + mask = ((mask << 2) | mp[s[i]]) & 0xFFFFF; + + if (i >= 9) { + cnt.set(mask, (cnt.get(mask) || 0) + 1); + if (cnt.get(mask) === 2) { + res.push(s.substring(i - 9, i + 1)); + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/sign-of-the-product-of-an-array.md b/articles/sign-of-the-product-of-an-array.md new file mode 100644 index 000000000..76922c8d0 --- /dev/null +++ b/articles/sign-of-the-product-of-an-array.md @@ -0,0 +1,158 @@ +## 1. Count Negative Numbers + +::tabs-start + +```python +class Solution: + def arraySign(self, nums: list[int]) -> int: + neg = 0 + for num in nums: + if num == 0: + return 0 + neg += (1 if num < 0 else 0) + return -1 if neg % 2 else 1 +``` + +```java +public class Solution { + public int arraySign(int[] nums) { + int neg = 0; + for (int num : nums) { + if (num == 0) { + return 0; + } + if (num < 0) { + neg++; + } + } + return neg % 2 == 0 ? 1 : -1; + } +} +``` + +```cpp +class Solution { +public: + int arraySign(vector& nums) { + int neg = 0; + for (int num : nums) { + if (num == 0) { + return 0; + } + if (num < 0) { + neg++; + } + } + return neg % 2 == 0 ? 1 : -1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + arraySign(nums) { + let neg = 0; + for (const num of nums) { + if (num === 0) { + return 0; + } + if (num < 0) { + neg++; + } + } + return neg % 2 === 0 ? 1 : -1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 2. Track the Sign of the Product + +::tabs-start + +```python +class Solution: + def arraySign(self, nums: list[int]) -> int: + sign = 1 + for num in nums: + if num == 0: + return 0 + if num < 0: + sign *= -1 + return sign +``` + +```java +public class Solution { + public int arraySign(int[] nums) { + int sign = 1; + for (int num : nums) { + if (num == 0) { + return 0; + } + if (num < 0) { + sign *= -1; + } + } + return sign; + } +} +``` + +```cpp +class Solution { +public: + int arraySign(vector& nums) { + int sign = 1; + for (int num : nums) { + if (num == 0) { + return 0; + } + if (num < 0) { + sign *= -1; + } + } + return sign; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + arraySign(nums) { + let sign = 1; + for (const num of nums) { + if (num === 0) { + return 0; + } + if (num < 0) { + sign *= -1; + } + } + return sign; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/sort-an-array.md b/articles/sort-an-array.md index 7551c767e..ba9edb507 100644 --- a/articles/sort-an-array.md +++ b/articles/sort-an-array.md @@ -209,7 +209,7 @@ class Solution { ### Time & Space Complexity -* Time complexity: $O(n)$ in average case, O(n ^ 2) in worst case. +* Time complexity: $O(n)$ in average case, $O(n ^ 2)$ in worst case. * Space complexity: $O(\log n)$ for recursive stack. --- diff --git a/articles/sort-characters-by-frequency.md b/articles/sort-characters-by-frequency.md new file mode 100644 index 000000000..779312faf --- /dev/null +++ b/articles/sort-characters-by-frequency.md @@ -0,0 +1,340 @@ +## 1. Sorting + +::tabs-start + +```python +class Solution: + def frequencySort(self, s: str) -> str: + count = Counter(s) + sorted_chars = sorted(s, key=lambda x: (-count[x], x)) + return ''.join(sorted_chars) +``` + +```java +public class Solution { + public String frequencySort(String s) { + int[] count = new int[123]; + for (char c : s.toCharArray()) { + count[c]++; + } + + Character[] chars = new Character[s.length()]; + for (int i = 0; i < s.length(); i++) { + chars[i] = s.charAt(i); + } + + Arrays.sort(chars, (a, b) -> { + if (count[b] == count[a]) { + return a - b; + } + return count[b] - count[a]; + }); + + StringBuilder result = new StringBuilder(); + for (char c : chars) { + result.append(c); + } + + return result.toString(); + } +} +``` + +```cpp +class Solution { +public: + string frequencySort(string s) { + vector count(123); + for (char c : s) { + count[c]++; + } + + vector chars(s.begin(), s.end()); + sort(chars.begin(), chars.end(), [&](char a, char b) { + if (count[b] == count[a]) { + return a < b; + } + return count[b] < count[a]; + }); + + return string(chars.begin(), chars.end()); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string} + */ + frequencySort(s) { + const count = {}; + for (const char of s) { + count[char] = (count[char] || 0) + 1; + } + + const sortedChars = [...s].sort((a, b) => { + if (count[b] === count[a]) { + return a.localeCompare(b); + } + return count[b] - count[a]; + }); + + return sortedChars.join(''); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. + +--- + +## 2. Frequency Sort + +::tabs-start + +```python +class Solution: + def frequencySort(self, s: str) -> str: + count = [0] * 123 + for c in s: + count[ord(c)] += 1 + + freq = [(chr(i), count[i]) for i in range(123) if count[i] > 0] + freq.sort(key=lambda x: (-x[1], x[0])) + + return ''.join(char * freq for char, freq in freq) +``` + +```java +public class Solution { + public String frequencySort(String s) { + int[] count = new int[123]; + for (char c : s.toCharArray()) { + count[c]++; + } + + List freq = new ArrayList<>(); + for (int i = 0; i < 123; i++) { + if (count[i] > 0) { + freq.add(new int[]{i, count[i]}); + } + } + + freq.sort((a, b) -> { + if (b[1] == a[1]) { + return a[0] - b[0]; + } + return b[1] - a[1]; + }); + + StringBuilder res = new StringBuilder(); + for (int[] entry : freq) { + for (int i = 0; i < entry[1]; i++) { + res.append((char) entry[0]); + } + } + + return res.toString(); + } +} +``` + +```cpp +class Solution { +public: + string frequencySort(string s) { + vector count(123, 0); + for (char c : s) { + count[c]++; + } + + vector> freq; + for (int i = 0; i < 123; i++) { + if (count[i] > 0) { + freq.emplace_back((char)i, count[i]); + } + } + + sort(freq.begin(), freq.end(), [](auto& a, auto& b) { + if (a.second == b.second) { + return a.first < b.first; + } + return a.second > b.second; + }); + + string res; + for (const auto& entry : freq) { + res += string(entry.second, entry.first); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string} + */ + frequencySort(s) { + const count = new Array(123).fill(0); + for (const char of s) { + count[char.charCodeAt(0)]++; + } + + const freq = []; + for (let i = 0; i < 123; i++) { + if (count[i] > 0) { + freq.push([String.fromCharCode(i), count[i]]); + } + } + + freq.sort((a, b) => { + if (b[1] === a[1]) { + return a[0].localeCompare(b[0]); + } + return b[1] - a[1]; + }); + + let res = ''; + for (const [char, freqCount] of freq) { + res += char.repeat(freqCount); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ for the output string. + +--- + +## 3. Bucket Sort + +::tabs-start + +```python +class Solution: + def frequencySort(self, s: str) -> str: + count = Counter(s) # char -> freq + buckets = defaultdict(list) # freq -> [char] + + for char, freq in count.items(): + buckets[freq].append(char) + + res = [] + for i in range(len(s), 0, -1): + if i in buckets: + for c in buckets[i]: + res.append(c * i) + + return "".join(res) +``` + +```java +public class Solution { + public String frequencySort(String s) { + Map count = new HashMap<>(); + for (char c : s.toCharArray()) { + count.put(c, count.getOrDefault(c, 0) + 1); + } + + List> buckets = new ArrayList<>(s.length() + 1); + for (int i = 0; i <= s.length(); i++) { + buckets.add(new ArrayList<>()); + } + + for (Map.Entry entry : count.entrySet()) { + buckets.get(entry.getValue()).add(entry.getKey()); + } + + StringBuilder res = new StringBuilder(); + for (int i = s.length(); i > 0; i--) { + for (char c : buckets.get(i)) { + for (int j = 0; j < i; j++) { + res.append(c); + } + } + } + + return res.toString(); + } +} +``` + +```cpp +class Solution { +public: + string frequencySort(string s) { + unordered_map count; + for (char c : s) { + count[c]++; + } + + vector> buckets(s.size() + 1); + for (auto& entry : count) { + buckets[entry.second].push_back(entry.first); + } + + string res; + for (int i = s.size(); i > 0; i--) { + for (char c : buckets[i]) { + res += string(i, c); + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string} + */ + frequencySort(s) { + const count = {}; + for (const char of s) { + count[char] = (count[char] || 0) + 1; + } + + const buckets = Array.from({ length: s.length + 1 }, () => []); + for (const [char, freq] of Object.entries(count)) { + buckets[freq].push(char); + } + + let res = ''; + for (let i = s.length; i > 0; i--) { + for (const char of buckets[i]) { + res += char.repeat(i); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/sum-of-absolute-differences-in-a-sorted-array.md b/articles/sum-of-absolute-differences-in-a-sorted-array.md new file mode 100644 index 000000000..f705f47d7 --- /dev/null +++ b/articles/sum-of-absolute-differences-in-a-sorted-array.md @@ -0,0 +1,430 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def getSumAbsoluteDifferences(self, nums: List[int]) -> List[int]: + res = [] + + for i in nums: + sum = 0 + for j in nums: + sum += abs(i - j) + res.append(sum) + + return res +``` + +```java +public class Solution { + public int[] getSumAbsoluteDifferences(int[] nums) { + int n = nums.length; + int[] res = new int[n]; + + for (int i = 0; i < n; i++) { + int sum = 0; + for (int j = 0; j < n; j++) { + sum += Math.abs(nums[i] - nums[j]); + } + res[i] = sum; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector getSumAbsoluteDifferences(vector& nums) { + int n = nums.size(); + vector res; + + for (int i = 0; i < n; i++) { + int sum = 0; + for (int j = 0; j < n; j++) { + sum += abs(nums[i] - nums[j]); + } + res.push_back(sum); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + getSumAbsoluteDifferences(nums) { + const n = nums.length; + const res = []; + + for (let i = 0; i < n; i++) { + let sum = 0; + for (let j = 0; j < n; j++) { + sum += Math.abs(nums[i] - nums[j]); + } + res.push(sum); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n)$ for the output array. + +--- + +## 2. Prefix & Suffix Sums (Extra Space) + +::tabs-start + +```python +class Solution: + def getSumAbsoluteDifferences(self, nums: List[int]) -> List[int]: + n = len(nums) + prefix_sum = [0] * n + suffix_sum = [0] * n + res = [0] * n + + prefix_sum[0] = nums[0] + for i in range(1, n): + prefix_sum[i] = prefix_sum[i - 1] + nums[i] + + suffix_sum[n - 1] = nums[n - 1] + for i in range(n - 2, -1, -1): + suffix_sum[i] = suffix_sum[i + 1] + nums[i] + + for i in range(n): + left_sum = (i * nums[i]) - (prefix_sum[i - 1] if i > 0 else 0) + right_sum = (suffix_sum[i + 1] if i < n - 1 else 0) - ((n - i - 1) * nums[i]) + res[i] = left_sum + right_sum + + return res +``` + +```java +public class Solution { + public int[] getSumAbsoluteDifferences(int[] nums) { + int n = nums.length; + int[] prefixSum = new int[n]; + int[] suffixSum = new int[n]; + int[] res = new int[n]; + + prefixSum[0] = nums[0]; + for (int i = 1; i < n; i++) { + prefixSum[i] = prefixSum[i - 1] + nums[i]; + } + + suffixSum[n - 1] = nums[n - 1]; + for (int i = n - 2; i >= 0; i--) { + suffixSum[i] = suffixSum[i + 1] + nums[i]; + } + + for (int i = 0; i < n; i++) { + int leftSum = i > 0 ? (i * nums[i] - prefixSum[i - 1]) : 0; + int rightSum = i < n - 1 ? (suffixSum[i + 1] - (n - i - 1) * nums[i]) : 0; + res[i] = leftSum + rightSum; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector getSumAbsoluteDifferences(vector& nums) { + int n = nums.size(); + vector prefixSum(n, 0), suffixSum(n, 0), res(n, 0); + + prefixSum[0] = nums[0]; + for (int i = 1; i < n; i++) { + prefixSum[i] = prefixSum[i - 1] + nums[i]; + } + + suffixSum[n - 1] = nums[n - 1]; + for (int i = n - 2; i >= 0; i--) { + suffixSum[i] = suffixSum[i + 1] + nums[i]; + } + + for (int i = 0; i < n; i++) { + int leftSum = i > 0 ? (i * nums[i] - prefixSum[i - 1]) : 0; + int rightSum = i < n - 1 ? (suffixSum[i + 1] - (n - i - 1) * nums[i]) : 0; + res[i] = leftSum + rightSum; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + getSumAbsoluteDifferences(nums) { + const n = nums.length; + const prefixSum = Array(n).fill(0); + const suffixSum = Array(n).fill(0); + const res = Array(n).fill(0); + + prefixSum[0] = nums[0]; + for (let i = 1; i < n; i++) { + prefixSum[i] = prefixSum[i - 1] + nums[i]; + } + + suffixSum[n - 1] = nums[n - 1]; + for (let i = n - 2; i >= 0; i--) { + suffixSum[i] = suffixSum[i + 1] + nums[i]; + } + + for (let i = 0; i < n; i++) { + const leftSum = i > 0 ? (i * nums[i] - prefixSum[i - 1]) : 0; + const rightSum = i < n - 1 ? (suffixSum[i + 1] - (n - i - 1) * nums[i]) : 0; + res[i] = leftSum + rightSum; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Prefix & Suffix Sums + +::tabs-start + +```python +class Solution: + def getSumAbsoluteDifferences(self, nums: List[int]) -> List[int]: + n = len(nums) + res = [0] * n + + res[n - 1] = nums[n - 1] + for i in range(n - 2, -1, -1): + res[i] = res[i + 1] + nums[i] + + prefix_sum = 0 + for i in range(n): + left_sum = (i * nums[i]) - prefix_sum + right_sum = (res[i + 1] if i < n - 1 else 0) - ((n - i - 1) * nums[i]) + res[i] = left_sum + right_sum + prefix_sum += nums[i] + + return res +``` + +```java +public class Solution { + public int[] getSumAbsoluteDifferences(int[] nums) { + int n = nums.length; + int[] res = new int[n]; + + res[n - 1] = nums[n - 1]; + for (int i = n - 2; i >= 0; i--) { + res[i] = res[i + 1] + nums[i]; + } + + int prefixSum = 0; + for (int i = 0; i < n; i++) { + int leftSum = i * nums[i] - prefixSum; + int rightSum = i < n - 1 ? (res[i + 1] - (n - i - 1) * nums[i]) : 0; + res[i] = leftSum + rightSum; + prefixSum += nums[i]; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector getSumAbsoluteDifferences(vector& nums) { + int n = nums.size(); + vector res(n, 0); + + res[n - 1] = nums[n - 1]; + for (int i = n - 2; i >= 0; i--) { + res[i] = res[i + 1] + nums[i]; + } + + int prefixSum = 0; + for (int i = 0; i < n; i++) { + int leftSum = i * nums[i] - prefixSum; + int rightSum = i < n - 1 ? (res[i + 1] - (n - i - 1) * nums[i]) : 0; + res[i] = leftSum + rightSum; + prefixSum += nums[i]; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + getSumAbsoluteDifferences(nums) { + const n = nums.length; + const res = Array(n).fill(0); + + res[n - 1] = nums[n - 1]; + for (let i = n - 2; i >= 0; i--) { + res[i] = res[i + 1] + nums[i]; + } + + let prefixSum = 0; + for (let i = 0; i < n; i++) { + const leftSum = i * nums[i] - prefixSum; + const rightSum = i < n - 1 ? (res[i + 1] - (n - i - 1) * nums[i]) : 0; + res[i] = leftSum + rightSum; + prefixSum += nums[i]; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ for the output array. + +--- + +## 4. Prefix & Suffix Sums (Optimal) + +::tabs-start + +```python +class Solution: + def getSumAbsoluteDifferences(self, nums: List[int]) -> List[int]: + n = len(nums) + res = [0] * n + + total_sum = sum(nums) + prefix_sum = 0 + + for i, num in enumerate(nums): + total_sum -= nums[i] + left_sum = i * nums[i] - prefix_sum + right_sum = total_sum - (n - i - 1) * nums[i] + res[i] = left_sum + right_sum + prefix_sum += nums[i] + + return res +``` + +```java +public class Solution { + public int[] getSumAbsoluteDifferences(int[] nums) { + int n = nums.length; + int[] res = new int[n]; + + int totalSum = 0, prefixSum = 0; + for (int num : nums) { + totalSum += num; + } + + for (int i = 0; i < n; i++) { + totalSum -= nums[i]; + int leftSum = i * nums[i] - prefixSum; + int rightSum = totalSum - (n - i - 1) * nums[i]; + res[i] = leftSum + rightSum; + prefixSum += nums[i]; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector getSumAbsoluteDifferences(vector& nums) { + int n = nums.size(); + vector res(n, 0); + + int totalSum = 0, prefixSum = 0; + for (int& num : nums) { + totalSum += num; + } + + for (int i = 0; i < n; i++) { + totalSum -= nums[i]; + int leftSum = i * nums[i] - prefixSum; + int rightSum = totalSum - (n - i - 1) * nums[i]; + res[i] = leftSum + rightSum; + prefixSum += nums[i]; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + getSumAbsoluteDifferences(nums) { + const n = nums.length; + const res = Array(n).fill(0); + + let totalSum = nums.reduce((sum, num) => sum + num, 0); + let prefixSum = 0; + + for (let i = 0; i < n; i++) { + totalSum -= nums[i]; + const leftSum = i * nums[i] - prefixSum; + const rightSum = totalSum - (n - i - 1) * nums[i]; + res[i] = leftSum + rightSum; + prefixSum += nums[i]; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ for the output array. \ No newline at end of file diff --git a/articles/wiggle-sort.md b/articles/wiggle-sort.md new file mode 100644 index 000000000..d18f99598 --- /dev/null +++ b/articles/wiggle-sort.md @@ -0,0 +1,293 @@ +## 1. Max-Heap + +::tabs-start + +```python +class Solution: + def wiggleSort(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + + maxHeap = [] + for num in nums: + heappush(maxHeap, -num) + + n = len(nums) + for i in range(1, n, 2): + nums[i] = -heappop(maxHeap) + for i in range(0, n, 2): + nums[i] = -heappop(maxHeap) +``` + +```java +public class Solution { + public void wiggleSort(int[] nums) { + PriorityQueue maxHeap = new PriorityQueue<>(Collections.reverseOrder()); + for (int num : nums) { + maxHeap.add(num); + } + + for (int i = 1; i < nums.length; i += 2) { + nums[i] = maxHeap.poll(); + } + for (int i = 0; i < nums.length; i += 2) { + nums[i] = maxHeap.poll(); + } + } +} +``` + +```cpp +class Solution { +public: + void wiggleSort(vector& nums) { + priority_queue maxHeap; + for (int& num : nums) { + maxHeap.push(num); + } + + for (int i = 1; i < nums.size(); i += 2) { + nums[i] = maxHeap.top(); + maxHeap.pop(); + } + for (int i = 0; i < nums.size(); i += 2) { + nums[i] = maxHeap.top(); + maxHeap.pop(); + } + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ + wiggleSort(nums) { + const maxHeap = new PriorityQueue((a, b) => b - a); + nums.forEach(num => maxHeap.enqueue(num)); + + for (let i = 1; i < nums.length; i += 2) { + nums[i] = maxHeap.dequeue(); + } + for (let i = 0; i < nums.length; i += 2) { + nums[i] = maxHeap.dequeue(); + } + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Sorting + +::tabs-start + +```python +class Solution: + def wiggleSort(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + + nums.sort() + for i in range(1, len(nums) - 1, 2): + nums[i], nums[i + 1] = nums[i + 1], nums[i] +``` + +```java +public class Solution { + public void wiggleSort(int[] nums) { + Arrays.sort(nums); + for (int i = 1; i < nums.length - 1; i += 2) { + int temp = nums[i]; + nums[i] = nums[i + 1]; + nums[i + 1] = temp; + } + } +} +``` + +```cpp +class Solution { +public: + void wiggleSort(vector& nums) { + sort(nums.begin(), nums.end()); + for (int i = 1; i < nums.size() - 1; i += 2) { + swap(nums[i], nums[i + 1]); + } + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ + wiggleSort(nums) { + nums.sort((a, b) => a - b); + for (let i = 1; i < nums.length - 1; i += 2) { + [nums[i], nums[i + 1]] = [nums[i + 1], nums[i]]; + } + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. + +--- + +## 3. Greedy - I + +::tabs-start + +```python +class Solution: + def wiggleSort(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + + for i in range(1, len(nums)): + if ((i % 2 == 1 and nums[i] < nums[i - 1]) or + (i % 2 == 0 and nums[i] > nums[i - 1]) + ): + nums[i], nums[i - 1] = nums[i - 1], nums[i] +``` + +```java +public class Solution { + public void wiggleSort(int[] nums) { + for (int i = 1; i < nums.length; i++) { + if ((i % 2 == 1 && nums[i] < nums[i - 1]) || + (i % 2 == 0 && nums[i] > nums[i - 1])) { + int temp = nums[i]; + nums[i] = nums[i - 1]; + nums[i - 1] = temp; + } + } + } +} +``` + +```cpp +class Solution { +public: + void wiggleSort(vector& nums) { + for (int i = 1; i nums[i - 1])) { + swap(nums[i], nums[i - 1]); + } + } + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ + wiggleSort(nums) { + for (let i = 1; i < nums.length; i++) { + if ((i % 2 == 1 && nums[i] < nums[i - 1]) || + (i % 2 == 0 && nums[i] > nums[i - 1])) { + [nums[i], nums[i - 1]] = [nums[i - 1], nums[i]]; + } + } + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 4. Greedy - II + +::tabs-start + +```python +class Solution: + def wiggleSort(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + + for i in range(1, len(nums)): + if (i % 2) ^ (nums[i] > nums[i - 1]): + nums[i], nums[i - 1] = nums[i - 1], nums[i] +``` + +```java +public class Solution { + public void wiggleSort(int[] nums) { + for (int i = 1; i < nums.length; i++) { + if (((i % 2) ^ (nums[i] > nums[i - 1] ? 1 : 0)) != 0) { + int temp = nums[i]; + nums[i] = nums[i - 1]; + nums[i - 1] = temp; + } + } + } +} +``` + +```cpp +class Solution { +public: + void wiggleSort(vector& nums) { + for (int i = 1; i nums[i - 1])) { + swap(nums[i], nums[i - 1]); + } + } + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ + wiggleSort(nums) { + for(var i = 1; i < nums.length; i++) { + if ((i % 2) ^ (nums[i] > nums[i - 1])) { + [nums[i], nums[i - 1]] = [nums[i - 1], nums[i]]; + } + } + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file