From 6f598d068ef682c95ff48cc557bf050c1047b2c8 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Wed, 2 Apr 2025 23:11:45 +0530 Subject: [PATCH 1/9] Batch-6/Neetcode-ALL/Added-articles --- ...haracters-to-string-to-make-subsequence.md | 210 +++ articles/kth-distinct-string-in-an-array.md | 350 +++++ ...reasing-or-strictly-decreasing-subarray.md | 454 +++++++ articles/maximum-ascending-subarray-sum.md | 173 +++ articles/number-of-senior-citizens.md | 149 +++ .../remove-duplicates-from-sorted-list.md | 2 +- articles/score-of-a-string.md | 60 + articles/string-matching-in-an-array.md | 1157 +++++++++++++++++ 8 files changed, 2554 insertions(+), 1 deletion(-) create mode 100644 articles/append-characters-to-string-to-make-subsequence.md create mode 100644 articles/kth-distinct-string-in-an-array.md create mode 100644 articles/longest-strictly-increasing-or-strictly-decreasing-subarray.md create mode 100644 articles/maximum-ascending-subarray-sum.md create mode 100644 articles/number-of-senior-citizens.md create mode 100644 articles/score-of-a-string.md create mode 100644 articles/string-matching-in-an-array.md diff --git a/articles/append-characters-to-string-to-make-subsequence.md b/articles/append-characters-to-string-to-make-subsequence.md new file mode 100644 index 000000000..de5f09613 --- /dev/null +++ b/articles/append-characters-to-string-to-make-subsequence.md @@ -0,0 +1,210 @@ +## 1. Two Pointers + +::tabs-start + +```python +class Solution: + def appendCharacters(self, s: str, t: str) -> int: + i, j = 0, 0 + + while i < len(s) and j < len(t): + if s[i] == t[j]: + i += 1 + j += 1 + else: + i += 1 + return len(t) - j +``` + +```java +public class Solution { + public int appendCharacters(String s, String t) { + int i = 0, j = 0; + + while (i < s.length() && j < t.length()) { + if (s.charAt(i) == t.charAt(j)) { + i++; + j++; + } else { + i++; + } + } + return t.length() - j; + } +} +``` + +```cpp +class Solution { +public: + int appendCharacters(string s, string t) { + int i = 0, j = 0; + + while (i < s.length() && j < t.length()) { + if (s[i] == t[j]) { + i++; + j++; + } else { + i++; + } + } + return t.length() - j; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @param {string} t + * @return {number} + */ + appendCharacters(s, t) { + let i = 0, j = 0; + + while (i < s.length && j < t.length) { + if (s[i] === t[j]) { + i++; + j++; + } else { + i++; + } + } + return t.length - j; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(1)$ + +> Where $n$ and $m$ are the lengths of the strings $s$ and $t$, respectively. + +--- + +## 2. Index Jumping + +::tabs-start + +```python +class Solution: + def appendCharacters(self, s: str, t: str) -> int: + n, m = len(s), len(t) + store = [[n + 1] * 26 for _ in range(n)] + store[n - 1][ord(s[n - 1]) - ord('a')] = n - 1 + + for i in range(n - 2, -1, -1): + store[i] = store[i + 1][:] + store[i][ord(s[i]) - ord('a')] = i + + i, j = 0, 0 + while i < n and j < m: + if store[i][ord(t[j]) - ord('a')] == n + 1: + break + + i = store[i][ord(t[j]) - ord('a')] + 1 + j += 1 + + return m - j +``` + +```java +public class Solution { + public int appendCharacters(String s, String t) { + int n = s.length(), m = t.length(); + int[][] store = new int[n][26]; + for (int[] row : store) { + Arrays.fill(row, n + 1); + } + store[n - 1][s.charAt(n - 1) - 'a'] = n - 1; + + for (int i = n - 2; i >= 0; i--) { + store[i] = store[i + 1].clone(); + store[i][s.charAt(i) - 'a'] = i; + } + + int i = 0, j = 0; + while (i < n && j < m) { + if (store[i][t.charAt(j) - 'a'] == n + 1) { + break; + } + i = store[i][t.charAt(j) - 'a'] + 1; + j++; + } + + return m - j; + } +} +``` + +```cpp +class Solution { +public: + int appendCharacters(string s, string t) { + int n = s.length(), m = t.length(); + vector> store(n, vector(26, n + 1)); + store[n - 1][s[n - 1] - 'a'] = n - 1; + + for (int i = n - 2; i >= 0; i--) { + store[i] = store[i + 1]; + store[i][s[i] - 'a'] = i; + } + + int i = 0, j = 0; + while (i < n && j < m) { + if (store[i][t[j] - 'a'] == n + 1) { + break; + } + i = store[i][t[j] - 'a'] + 1; + j++; + } + + return m - j; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @param {string} t + * @return {number} + */ + appendCharacters(s, t) { + const n = s.length, m = t.length; + const store = Array.from({ length: n }, () => Array(26).fill(n + 1)); + store[n - 1][s.charCodeAt(n - 1) - 97] = n - 1; + + for (let i = n - 2; i >= 0; i--) { + store[i] = store[i + 1].slice(); + store[i][s.charCodeAt(i) - 97] = i; + } + + let i = 0, j = 0; + while (i < n && j < m) { + if (store[i][t.charCodeAt(j) - 97] === n + 1) { + break; + } + i = store[i][t.charCodeAt(j) - 97] + 1; + j++; + } + + return m - j; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n)$ + +> Where $n$ and $m$ are the lengths of the strings $s$ and $t$, respectively. \ No newline at end of file diff --git a/articles/kth-distinct-string-in-an-array.md b/articles/kth-distinct-string-in-an-array.md new file mode 100644 index 000000000..244281490 --- /dev/null +++ b/articles/kth-distinct-string-in-an-array.md @@ -0,0 +1,350 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def kthDistinct(self, arr: List[str], k: int) -> str: + for i in range(len(arr)): + flag = True + for j in range(len(arr)): + if i == j: + continue + + if arr[i] == arr[j]: + flag = False + break + + if flag: + k -= 1 + if k == 0: + return arr[i] + return "" +``` + +```java +public class Solution { + public String kthDistinct(String[] arr, int k) { + for (int i = 0; i < arr.length; i++) { + boolean flag = true; + for (int j = 0; j < arr.length; j++) { + if (i == j) continue; + + if (arr[i].equals(arr[j])) { + flag = false; + break; + } + } + + if (flag) { + k--; + if (k == 0) { + return arr[i]; + } + } + } + return ""; + } +} +``` + +```cpp +class Solution { +public: + string kthDistinct(vector& arr, int k) { + for (int i = 0; i < arr.size(); i++) { + bool flag = true; + for (int j = 0; j < arr.size(); j++) { + if (i == j) continue; + + if (arr[i] == arr[j]) { + flag = false; + break; + } + } + + if (flag) { + k--; + if (k == 0) { + return arr[i]; + } + } + } + return ""; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} arr + * @param {number} k + * @return {string} + */ + kthDistinct(arr, k) { + for (let i = 0; i < arr.length; i++) { + let flag = true; + for (let j = 0; j < arr.length; j++) { + if (i === j) continue; + + if (arr[i] === arr[j]) { + flag = false; + break; + } + } + + if (flag) { + k--; + if (k === 0) { + return arr[i]; + } + } + } + return ""; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Hash Map + +::tabs-start + +```python +class Solution: + def kthDistinct(self, arr: List[str], k: int) -> str: + count = {} + + for s in arr: + if s not in count: + count[s] = 0 + count[s] += 1 + + for s in arr: + if count[s] == 1: + k -= 1 + if k == 0: + return s + + return "" +``` + +```java +public class Solution { + public String kthDistinct(String[] arr, int k) { + Map count = new HashMap<>(); + + for (String s : arr) { + count.put(s, count.getOrDefault(s, 0) + 1); + } + + for (String s : arr) { + if (count.get(s) == 1) { + k--; + if (k == 0) { + return s; + } + } + } + + return ""; + } +} +``` + +```cpp +class Solution { +public: + string kthDistinct(vector& arr, int k) { + unordered_map count; + + for (const string& s : arr) { + count[s]++; + } + + for (const string& s : arr) { + if (count[s] == 1) { + k--; + if (k == 0) { + return s; + } + } + } + + return ""; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} arr + * @param {number} k + * @return {string} + */ + kthDistinct(arr, k) { + const count = {}; + + for (let s of arr) { + if (!(s in count)) { + count[s] = 0; + } + count[s]++; + } + + for (let s of arr) { + if (count[s] === 1) { + k--; + if (k === 0) { + return s; + } + } + } + + return ""; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Hash Set + +::tabs-start + +```python +class Solution: + def kthDistinct(self, arr: List[str], k: int) -> str: + distinct, seen = set(), set() + + for s in arr: + if s in distinct: + distinct.remove(s) + seen.add(s) + elif s not in seen: + distinct.add(s) + + for s in arr: + if s in distinct: + k -= 1 + if k == 0: + return s + + return "" +``` + +```java +public class Solution { + public String kthDistinct(String[] arr, int k) { + Set distinct = new HashSet<>(); + Set seen = new HashSet<>(); + + for (String s : arr) { + if (distinct.contains(s)) { + distinct.remove(s); + seen.add(s); + } else if (!seen.contains(s)) { + distinct.add(s); + } + } + + for (String s : arr) { + if (distinct.contains(s)) { + k--; + if (k == 0) { + return s; + } + } + } + + return ""; + } +} +``` + +```cpp +class Solution { +public: + string kthDistinct(vector& arr, int k) { + unordered_set distinct, seen; + + for (const string& s : arr) { + if (distinct.count(s)) { + distinct.erase(s); + seen.insert(s); + } else if (!seen.count(s)) { + distinct.insert(s); + } + } + + for (const string& s : arr) { + if (distinct.count(s)) { + k--; + if (k == 0) { + return s; + } + } + } + + return ""; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} arr + * @param {number} k + * @return {string} + */ + kthDistinct(arr, k) { + const distinct = new Set(); + const seen = new Set(); + + for (let s of arr) { + if (distinct.has(s)) { + distinct.delete(s); + seen.add(s); + } else if (!seen.has(s)) { + distinct.add(s); + } + } + + for (let s of arr) { + if (distinct.has(s)) { + k--; + if (k === 0) { + return s; + } + } + } + + return ""; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/longest-strictly-increasing-or-strictly-decreasing-subarray.md b/articles/longest-strictly-increasing-or-strictly-decreasing-subarray.md new file mode 100644 index 000000000..4c55b7a6b --- /dev/null +++ b/articles/longest-strictly-increasing-or-strictly-decreasing-subarray.md @@ -0,0 +1,454 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def longestMonotonicSubarray(self, nums: List[int]) -> int: + n = len(nums) + res = 1 + + for i in range(n - 1): + curLen = 1 + for j in range(i + 1, n): + if nums[j] == nums[j - 1] or ((nums[i] < nums[i + 1]) != (nums[j - 1] < nums[j])): + break + curLen += 1 + + res = max(res, curLen) + + return res +``` + +```java +public class Solution { + public int longestMonotonicSubarray(int[] nums) { + int n = nums.length; + int res = 1; + + for (int i = 0; i < n - 1; i++) { + int curLen = 1; + for (int j = i + 1; j < n; j++) { + if (nums[j] == nums[j - 1] || ((nums[i] < nums[i + 1]) != (nums[j - 1] < nums[j]))) { + break; + } + curLen++; + } + res = Math.max(res, curLen); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int longestMonotonicSubarray(vector& nums) { + int n = nums.size(); + int res = 1; + + for (int i = 0; i < n - 1; i++) { + int curLen = 1; + for (int j = i + 1; j < n; j++) { + if (nums[j] == nums[j - 1] || ((nums[i] < nums[i + 1]) != (nums[j - 1] < nums[j]))) { + break; + } + curLen++; + } + res = max(res, curLen); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + longestMonotonicSubarray(nums) { + let n = nums.length; + let res = 1; + + for (let i = 0; i < n - 1; i++) { + let curLen = 1; + for (let j = i + 1; j < n; j++) { + if (nums[j] === nums[j - 1] || ((nums[i] < nums[i + 1]) !== (nums[j - 1] < nums[j]))) { + break; + } + curLen++; + } + res = Math.max(res, curLen); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Iteration - I + +::tabs-start + +```python +class Solution: + def longestMonotonicSubarray(self, nums: List[int]) -> int: + cur = 1 + res = 1 + increasing = 0 + + for i in range(1, len(nums)): + if nums[i - 1] < nums[i]: + if increasing > 0: + cur += 1 + else: + cur = 2 + increasing = 1 + elif nums[i - 1] > nums[i]: + if increasing < 0: + cur += 1 + else: + cur = 2 + increasing = -1 + else: + cur = 1 + increasing = 0 + res = max(res, cur) + + return res +``` + +```java +public class Solution { + public int longestMonotonicSubarray(int[] nums) { + int cur = 1; + int res = 1; + int increasing = 0; + + for (int i = 1; i < nums.length; i++) { + if (nums[i - 1] < nums[i]) { + if (increasing > 0) { + cur++; + } else { + cur = 2; + increasing = 1; + } + } else if (nums[i - 1] > nums[i]) { + if (increasing < 0) { + cur++; + } else { + cur = 2; + increasing = -1; + } + } else { + cur = 1; + increasing = 0; + } + res = Math.max(res, cur); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int longestMonotonicSubarray(vector& nums) { + int cur = 1; + int res = 1; + int increasing = 0; + + for (int i = 1; i < nums.size(); i++) { + if (nums[i - 1] < nums[i]) { + if (increasing > 0) { + cur++; + } else { + cur = 2; + increasing = 1; + } + } else if (nums[i - 1] > nums[i]) { + if (increasing < 0) { + cur++; + } else { + cur = 2; + increasing = -1; + } + } else { + cur = 1; + increasing = 0; + } + res = max(res, cur); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + longestMonotonicSubarray(nums) { + let cur = 1; + let res = 1; + let increasing = 0; + + for (let i = 1; i < nums.length; i++) { + if (nums[i - 1] < nums[i]) { + if (increasing > 0) { + cur++; + } else { + cur = 2; + increasing = 1; + } + } else if (nums[i - 1] > nums[i]) { + if (increasing < 0) { + cur++; + } else { + cur = 2; + increasing = -1; + } + } else { + cur = 1; + increasing = 0; + } + res = Math.max(res, cur); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 3. Iteration - II + +::tabs-start + +```python +class Solution: + def longestMonotonicSubarray(self, nums: List[int]) -> int: + inc = dec = 1 + res = 1 + + for i in range(1, len(nums)): + if nums[i] == nums[i - 1]: + inc = dec = 1 + elif nums[i] > nums[i - 1]: + inc, dec = inc + 1, 1 + else: + inc, dec = 1, dec + 1 + + res = max(res, inc, dec) + + return res +``` + +```java +public class Solution { + public int longestMonotonicSubarray(int[] nums) { + int inc = 1, dec = 1, res = 1; + + for (int i = 1; i < nums.length; i++) { + if (nums[i] == nums[i - 1]) { + inc = dec = 1; + } else if (nums[i] > nums[i - 1]) { + inc = inc + 1; + dec = 1; + } else { + inc = 1; + dec = dec + 1; + } + res = Math.max(res, Math.max(inc, dec)); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int longestMonotonicSubarray(vector& nums) { + int inc = 1, dec = 1, res = 1; + + for (int i = 1; i < nums.size(); i++) { + if (nums[i] == nums[i - 1]) { + inc = dec = 1; + } else if (nums[i] > nums[i - 1]) { + inc = inc + 1; + dec = 1; + } else { + inc = 1; + dec = dec + 1; + } + res = max(res, max(inc, dec)); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + longestMonotonicSubarray(nums) { + let inc = 1, dec = 1, res = 1; + + for (let i = 1; i < nums.length; i++) { + if (nums[i] === nums[i - 1]) { + inc = dec = 1; + } else if (nums[i] > nums[i - 1]) { + inc = inc + 1; + dec = 1; + } else { + inc = 1; + dec = dec + 1; + } + res = Math.max(res, inc, dec); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 4. Iteration - III + +::tabs-start + +```python +class Solution: + def longestMonotonicSubarray(self, nums: List[int]) -> int: + curLen = res = 1 + + for i in range(1, len(nums)): + if (nums[i] == nums[i - 1] or + ((nums[i - curLen] < nums[i - curLen + 1]) != (nums[i - 1] < nums[i])) + ): + curLen = 1 if (nums[i] == nums[i - 1]) else 2 + continue + + curLen += 1 + res = max(res, curLen) + + return res +``` + +```java +public class Solution { + public int longestMonotonicSubarray(int[] nums) { + int curLen = 1, res = 1; + + for (int i = 1; i < nums.length; i++) { + if (nums[i] == nums[i - 1] || + ((nums[i - curLen] < nums[i - curLen + 1]) != (nums[i - 1] < nums[i]))) { + curLen = (nums[i] == nums[i - 1]) ? 1 : 2; + continue; + } + + curLen++; + res = Math.max(res, curLen); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int longestMonotonicSubarray(vector& nums) { + int curLen = 1, res = 1; + + for (int i = 1; i < nums.size(); i++) { + if (nums[i] == nums[i - 1] || + ((nums[i - curLen] < nums[i - curLen + 1]) != (nums[i - 1] < nums[i]))) { + curLen = (nums[i] == nums[i - 1]) ? 1 : 2; + continue; + } + + curLen++; + res = max(res, curLen); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + longestMonotonicSubarray(nums) { + let curLen = 1, res = 1; + + for (let i = 1; i < nums.length; i++) { + if ( + nums[i] === nums[i - 1] || + ((nums[i - curLen] < nums[i - curLen + 1]) !== (nums[i - 1] < nums[i])) + ) { + curLen = nums[i] === nums[i - 1] ? 1 : 2; + continue; + } + + curLen++; + res = Math.max(res, curLen); + } + + 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/maximum-ascending-subarray-sum.md b/articles/maximum-ascending-subarray-sum.md new file mode 100644 index 000000000..5d4e47a60 --- /dev/null +++ b/articles/maximum-ascending-subarray-sum.md @@ -0,0 +1,173 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def maxAscendingSum(self, nums: List[int]) -> int: + res = 0 + for i in range(len(nums)): + curSum = nums[i] + for j in range(i + 1, len(nums)): + if nums[j] <= nums[j - 1]: + break + curSum += nums[j] + res = max(res, curSum) + return res +``` + +```java +public class Solution { + public int maxAscendingSum(int[] nums) { + int res = 0; + for (int i = 0; i < nums.length; i++) { + int curSum = nums[i]; + for (int j = i + 1; j < nums.length; j++) { + if (nums[j] <= nums[j - 1]) { + break; + } + curSum += nums[j]; + } + res = Math.max(res, curSum); + } + return res; + } +} +``` + +```cpp +class Solution { +public: + int maxAscendingSum(vector& nums) { + int res = 0; + for (int i = 0; i < nums.size(); i++) { + int curSum = nums[i]; + for (int j = i + 1; j < nums.size(); j++) { + if (nums[j] <= nums[j - 1]) { + break; + } + curSum += nums[j]; + } + res = max(res, curSum); + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + maxAscendingSum(nums) { + let res = 0; + for (let i = 0; i < nums.length; i++) { + let curSum = nums[i]; + for (let j = i + 1; j < nums.length; j++) { + if (nums[j] <= nums[j - 1]) { + break; + } + curSum += nums[j]; + } + res = Math.max(res, curSum); + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Iteration + +::tabs-start + +```python +class Solution: + def maxAscendingSum(self, nums: List[int]) -> int: + res = curSum= nums[0] + + for i in range(1, len(nums)): + if nums[i] <= nums[i - 1]: + curSum = 0 + + curSum += nums[i] + res = max(res, curSum) + + return res +``` + +```java +public class Solution { + public int maxAscendingSum(int[] nums) { + int res = nums[0], curSum = nums[0]; + + for (int i = 1; i < nums.length; i++) { + if (nums[i] <= nums[i - 1]) { + curSum = 0; + } + curSum += nums[i]; + res = Math.max(res, curSum); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int maxAscendingSum(vector& nums) { + int res = nums[0], curSum = nums[0]; + + for (int i = 1; i < nums.size(); i++) { + if (nums[i] <= nums[i - 1]) { + curSum = 0; + } + curSum += nums[i]; + res = max(res, curSum); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + maxAscendingSum(nums) { + let res = nums[0], curSum = nums[0]; + + for (let i = 1; i < nums.length; i++) { + if (nums[i] <= nums[i - 1]) { + curSum = 0; + } + curSum += nums[i]; + res = Math.max(res, curSum); + } + + 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/number-of-senior-citizens.md b/articles/number-of-senior-citizens.md new file mode 100644 index 000000000..11a6b0d29 --- /dev/null +++ b/articles/number-of-senior-citizens.md @@ -0,0 +1,149 @@ +## 1. String Parsing + +::tabs-start + +```python +class Solution: + def countSeniors(self, details: List[str]) -> int: + res = 0 + for d in details: + if int(d[11:13]) > 60: + res += 1 + return res +``` + +```java +public class Solution { + public int countSeniors(String[] details) { + int res = 0; + for (String d : details) { + if (Integer.parseInt(d.substring(11, 13)) > 60) { + res++; + } + } + return res; + } +} +``` + +```cpp +class Solution { +public: + int countSeniors(vector& details) { + int res = 0; + for (const string& d : details) { + if (stoi(d.substr(11, 2)) > 60) { + res++; + } + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} details + * @return {number} + */ + countSeniors(details) { + let res = 0; + for (let d of details) { + if (parseInt(d.slice(11, 13)) > 60) { + res++; + } + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 2. Character-Based Extraction + +::tabs-start + +```python +class Solution: + def countSeniors(self, details: List[str]) -> int: + res = 0 + for d in details: + ten = ord(d[11]) - ord("0") + one = ord(d[12]) - ord("0") + age = one + 10 * ten + if age > 60: + res += 1 + return res +``` + +```java +public class Solution { + public int countSeniors(String[] details) { + int res = 0; + for (String d : details) { + int ten = d.charAt(11) - '0'; + int one = d.charAt(12) - '0'; + int age = one + 10 * ten; + if (age > 60) { + res++; + } + } + return res; + } +} +``` + +```cpp +class Solution { +public: + int countSeniors(vector& details) { + int res = 0; + for (const string& d : details) { + int ten = d[11] - '0'; + int one = d[12] - '0'; + int age = one + 10 * ten; + if (age > 60) { + res++; + } + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} details + * @return {number} + */ + countSeniors(details) { + let res = 0; + for (let d of details) { + let ten = d.charCodeAt(11) - 48; + let one = d.charCodeAt(12) - 48; + let age = one + 10 * ten; + if (age > 60) { + res++; + } + } + 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/remove-duplicates-from-sorted-list.md b/articles/remove-duplicates-from-sorted-list.md index b50bbbdcb..9184c3e9c 100644 --- a/articles/remove-duplicates-from-sorted-list.md +++ b/articles/remove-duplicates-from-sorted-list.md @@ -88,7 +88,7 @@ class Solution { ### Time & Space Complexity -* Time complexity: $O(2 ^ n)$ +* Time complexity: $O(n)$ * Space complexity: $O(n)$ for recursion stack. --- diff --git a/articles/score-of-a-string.md b/articles/score-of-a-string.md new file mode 100644 index 000000000..9a5bf9bdf --- /dev/null +++ b/articles/score-of-a-string.md @@ -0,0 +1,60 @@ +## 1. Iteration + +::tabs-start + +```python +class Solution: + def scoreOfString(self, s: str) -> int: + res = 0 + for i in range(len(s) - 1): + res += abs(ord(s[i]) - ord(s[i + 1])) + return res +``` + +```java +public class Solution { + public int scoreOfString(String s) { + int res = 0; + for (int i = 0; i < s.length() - 1; i++) { + res += Math.abs(s.charAt(i) - s.charAt(i + 1)); + } + return res; + } +} +``` + +```cpp +class Solution { +public: + int scoreOfString(string s) { + int res = 0; + for (int i = 0; i < s.length() - 1; i++) { + res += abs(s[i] - s[i + 1]); + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number} + */ + scoreOfString(s) { + let res = 0; + for (let i = 0; i < s.length - 1; i++) { + res += Math.abs(s.charCodeAt(i) - s.charCodeAt(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/string-matching-in-an-array.md b/articles/string-matching-in-an-array.md new file mode 100644 index 000000000..f369be41c --- /dev/null +++ b/articles/string-matching-in-an-array.md @@ -0,0 +1,1157 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def stringMatching(self, words: List[str]) -> List[str]: + res = [] + + for i in range(len(words)): + for j in range(len(words)): + if i == j: + continue + + if words[i] in words[j]: + res.append(words[i]) + break + + return res +``` + +```java +public class Solution { + public List stringMatching(String[] words) { + List res = new ArrayList<>(); + + for (int i = 0; i < words.length; i++) { + for (int j = 0; j < words.length; j++) { + if (i == j) { + continue; + } + + if (words[j].contains(words[i])) { + res.add(words[i]); + break; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector stringMatching(vector& words) { + vector res; + + for (int i = 0; i < words.size(); i++) { + for (int j = 0; j < words.size(); j++) { + if (i == j) { + continue; + } + + if (words[j].find(words[i]) != string::npos) { + res.push_back(words[i]); + break; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @return {string[]} + */ + stringMatching(words) { + let res = []; + + for (let i = 0; i < words.length; i++) { + for (let j = 0; j < words.length; j++) { + if (i === j) { + continue; + } + + if (words[j].includes(words[i])) { + res.push(words[i]); + break; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2 * m ^ 2)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n * m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the length of the longest word. + +--- + +## 2. Sorting + +::tabs-start + +```python +class Solution: + def stringMatching(self, words: List[str]) -> List[str]: + res = [] + words.sort(key=len) + + for i in range(len(words)): + for j in range(i + 1, len(words)): + if words[i] in words[j]: + res.append(words[i]) + break + + return res +``` + +```java +public class Solution { + public List stringMatching(String[] words) { + List res = new ArrayList<>(); + Arrays.sort(words, Comparator.comparingInt(String::length)); + + for (int i = 0; i < words.length; i++) { + for (int j = i + 1; j < words.length; j++) { + if (words[j].contains(words[i])) { + res.add(words[i]); + break; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector stringMatching(vector& words) { + vector res; + sort(words.begin(), words.end(), [](const string& a, const string& b) { + return a.length() < b.length(); + }); + + for (int i = 0; i < words.size(); i++) { + for (int j = i + 1; j < words.size(); j++) { + if (words[j].find(words[i]) != string::npos) { + res.push_back(words[i]); + break; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @return {string[]} + */ + stringMatching(words) { + let res = []; + words.sort((a, b) => a.length - b.length); + + for (let i = 0; i < words.length; i++) { + for (let j = i + 1; j < words.length; j++) { + if (words[j].includes(words[i])) { + res.push(words[i]); + break; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2 * m ^ 2)$ +* Space complexity: + * $O(1)$ or $O(n)$ depending on the sorting algorithm. + * $O(n * m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the length of the longest word. + +--- + +## 3. Knuth-Morris-Pratt (KMP) Algorithm + +::tabs-start + +```python +class Solution: + def stringMatching(self, words: List[str]) -> List[str]: + def kmp(word1: str, word2: str) -> int: + lps = [0] * len(word2) + prevLPS, i = 0, 1 + + while i < len(word2): + if word2[i] == word2[prevLPS]: + lps[i] = prevLPS + 1 + prevLPS += 1 + i += 1 + elif prevLPS == 0: + lps[i] = 0 + i += 1 + else: + prevLPS = lps[prevLPS - 1] + + i = j = 0 + while i < len(word1): + if word1[i] == word2[j]: + i += 1 + j += 1 + else: + if j == 0: + i += 1 + else: + j = lps[j - 1] + + if j == len(word2): + return i - len(word2) + + return -1 + + res = [] + words.sort(key=len) + + for i in range(len(words)): + for j in range(i + 1, len(words)): + if kmp(words[j], words[i]) != -1: + res.append(words[i]) + break + + return res +``` + +```java +public class Solution { + public List stringMatching(String[] words) { + List res = new ArrayList<>(); + Arrays.sort(words, Comparator.comparingInt(String::length)); + + for (int i = 0; i < words.length; i++) { + for (int j = i + 1; j < words.length; j++) { + if (kmp(words[j], words[i]) != -1) { + res.add(words[i]); + break; + } + } + } + + return res; + } + + private int kmp(String word1, String word2) { + int[] lps = new int[word2.length()]; + int prevLPS = 0, i = 1; + + while (i < word2.length()) { + if (word2.charAt(i) == word2.charAt(prevLPS)) { + lps[i] = prevLPS + 1; + prevLPS++; + i++; + } else if (prevLPS == 0) { + lps[i] = 0; + i++; + } else { + prevLPS = lps[prevLPS - 1]; + } + } + + i = 0; + int j = 0; + while (i < word1.length()) { + if (word1.charAt(i) == word2.charAt(j)) { + i++; + j++; + } else { + if (j == 0) { + i++; + } else { + j = lps[j - 1]; + } + } + + if (j == word2.length()) { + return i - word2.length(); + } + } + + return -1; + } +} +``` + +```cpp +class Solution { +public: + vector stringMatching(vector& words) { + vector res; + sort(words.begin(), words.end(), [](const string& a, const string& b) { + return a.length() < b.length(); + }); + + for (int i = 0; i < words.size(); i++) { + for (int j = i + 1; j < words.size(); j++) { + if (kmp(words[j], words[i]) != -1) { + res.push_back(words[i]); + break; + } + } + } + + return res; + } + +private: + int kmp(const string& word1, const string& word2) { + vector lps(word2.size(), 0); + int prevLPS = 0, i = 1; + + while (i < word2.size()) { + if (word2[i] == word2[prevLPS]) { + lps[i++] = ++prevLPS; + } else if (prevLPS == 0) { + lps[i++] = 0; + } else { + prevLPS = lps[prevLPS - 1]; + } + } + + i = 0; + int j = 0; + while (i < word1.size()) { + if (word1[i] == word2[j]) { + i++; + j++; + } else { + if (j == 0) { + i++; + } else { + j = lps[j - 1]; + } + } + + if (j == word2.size()) { + return i - word2.size(); + } + } + + return -1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @return {string[]} + */ + stringMatching(words) { + const kmp = (word1, word2) => { + const lps = Array(word2.length).fill(0); + let prevLPS = 0, i = 1; + + while (i < word2.length) { + if (word2[i] === word2[prevLPS]) { + lps[i++] = ++prevLPS; + } else if (prevLPS === 0) { + lps[i++] = 0; + } else { + prevLPS = lps[prevLPS - 1]; + } + } + + i = 0; + let j = 0; + while (i < word1.length) { + if (word1[i] === word2[j]) { + i++; + j++; + } else { + if (j === 0) { + i++; + } else { + j = lps[j - 1]; + } + } + + if (j === word2.length) { + return i - word2.length; + } + } + + return -1; + }; + + let res = []; + words.sort((a, b) => a.length - b.length); + + for (let i = 0; i < words.length; i++) { + for (let j = i + 1; j < words.length; j++) { + if (kmp(words[j], words[i]) !== -1) { + res.push(words[i]); + break; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2 * m)$ +* Space complexity: + * $O(m)$ extra space. + * $O(1)$ or $O(n)$ space depending on the sorting algorithm. + * $O(n * m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the length of the longest word. + +--- + +## 4. Rabin-Karp Algorithm (Rolling Hash) + +::tabs-start + +```python +class Solution: + def stringMatching(self, words: List[str]) -> List[str]: + def rabinKarp(word1: str, word2: str) -> int: + base1, mod1 = 31, 768258391 + base2, mod2 = 37, 685683731 + n, m = len(word1), len(word2) + + power1, power2 = 1, 1 + for _ in range(m): + power1 = (power1 * base1) % mod1 + power2 = (power2 * base2) % mod2 + + word1_hash1 = word1_hash2 = 0 + word2_hash1 = word2_hash2 = 0 + + for i in range(m): + word1_hash1 = (word1_hash1 * base1 + ord(word2[i])) % mod1 + word1_hash2 = (word1_hash2 * base2 + ord(word2[i])) % mod2 + word2_hash1 = (word2_hash1 * base1 + ord(word1[i])) % mod1 + word2_hash2 = (word2_hash2 * base2 + ord(word1[i])) % mod2 + + for i in range(n - m + 1): + if word2_hash1 == word1_hash1 and word2_hash2 == word1_hash2: + return i + + if i + m < n: + word2_hash1 = (word2_hash1 * base1 - ord(word1[i]) * power1 + ord(word1[i + m])) % mod1 + word2_hash2 = (word2_hash2 * base2 - ord(word1[i]) * power2 + ord(word1[i + m])) % mod2 + + word2_hash1 = (word2_hash1 + mod1) % mod1 + word2_hash2 = (word2_hash2 + mod2) % mod2 + + return -1 + + res = [] + words.sort(key=len) + + for i in range(len(words)): + for j in range(i + 1, len(words)): + if rabinKarp(words[j], words[i]) != -1: + res.append(words[i]) + break + + return res +``` + +```java +public class Solution { + public List stringMatching(String[] words) { + List res = new ArrayList<>(); + Arrays.sort(words, Comparator.comparingInt(String::length)); + + for (int i = 0; i < words.length; i++) { + for (int j = i + 1; j < words.length; j++) { + if (rabinKarp(words[j], words[i]) != -1) { + res.add(words[i]); + break; + } + } + } + + return res; + } + + private int rabinKarp(String word1, String word2) { + int base1 = 31, mod1 = 768258391; + int base2 = 37, mod2 = 685683731; + int n = word1.length(), m = word2.length(); + + long power1 = 1, power2 = 1; + for (int k = 0; k < m; k++) { + power1 = (power1 * base1) % mod1; + power2 = (power2 * base2) % mod2; + } + + long word1Hash1 = 0, word1Hash2 = 0; + long word2Hash1 = 0, word2Hash2 = 0; + + for (int i = 0; i < m; i++) { + word1Hash1 = (word1Hash1 * base1 + word2.charAt(i)) % mod1; + word1Hash2 = (word1Hash2 * base2 + word2.charAt(i)) % mod2; + word2Hash1 = (word2Hash1 * base1 + word1.charAt(i)) % mod1; + word2Hash2 = (word2Hash2 * base2 + word1.charAt(i)) % mod2; + } + + for (int i = 0; i <= n - m; i++) { + if (word2Hash1 == word1Hash1 && word2Hash2 == word1Hash2) { + return i; + } + + if (i + m < n) { + word2Hash1 = (word2Hash1 * base1 - word1.charAt(i) * power1 + word1.charAt(i + m)) % mod1; + word2Hash2 = (word2Hash2 * base2 - word1.charAt(i) * power2 + word1.charAt(i + m)) % mod2; + + if (word2Hash1 < 0) word2Hash1 += mod1; + if (word2Hash2 < 0) word2Hash2 += mod2; + } + } + + return -1; + } +} +``` + +```cpp +class Solution { +public: + vector stringMatching(vector& words) { + vector res; + sort(words.begin(), words.end(), [](const string& a, const string& b) { + return a.length() < b.length(); + }); + + for (int i = 0; i < words.size(); i++) { + for (int j = i + 1; j < words.size(); j++) { + if (rabinKarp(words[j], words[i]) != -1) { + res.push_back(words[i]); + break; + } + } + } + + return res; + } + +private: + int rabinKarp(const string& word1, const string& word2) { + int base1 = 31, mod1 = 768258391; + int base2 = 37, mod2 = 685683731; + int n = word1.size(), m = word2.size(); + + long long power1 = 1, power2 = 1; + for (int i = 0; i < m; i++) { + power1 = (power1 * base1) % mod1; + power2 = (power2 * base2) % mod2; + } + + long long word1Hash1 = 0, word1Hash2 = 0; + long long word2Hash1 = 0, word2Hash2 = 0; + + for (int i = 0; i < m; i++) { + word1Hash1 = (word1Hash1 * base1 + word2[i]) % mod1; + word1Hash2 = (word1Hash2 * base2 + word2[i]) % mod2; + word2Hash1 = (word2Hash1 * base1 + word1[i]) % mod1; + word2Hash2 = (word2Hash2 * base2 + word1[i]) % mod2; + } + + for (int i = 0; i <= n - m; i++) { + if (word2Hash1 == word1Hash1 && word2Hash2 == word1Hash2) { + return i; + } + + if (i + m < n) { + word2Hash1 = (word2Hash1 * base1 - word1[i] * power1 + word1[i + m]) % mod1; + word2Hash2 = (word2Hash2 * base2 - word1[i] * power2 + word1[i + m]) % mod2; + + if (word2Hash1 < 0) word2Hash1 += mod1; + if (word2Hash2 < 0) word2Hash2 += mod2; + } + } + + return -1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @return {string[]} + */ + stringMatching(words) { + const rabinKarp = (word1, word2) => { + const base1 = 31, mod1 = 768258391; + const base2 = 37, mod2 = 685683731; + const n = word1.length, m = word2.length; + + let power1 = 1, power2 = 1; + for (let k = 0; k < m; k++) { + power1 = (power1 * base1) % mod1; + power2 = (power2 * base2) % mod2; + } + + let hash1 = 0, hash2 = 0; + let cur1 = 0, cur2 = 0; + + for (let i = 0; i < m; i++) { + hash1 = (hash1 * base1 + word2.charCodeAt(i)) % mod1; + hash2 = (hash2 * base2 + word2.charCodeAt(i)) % mod2; + cur1 = (cur1 * base1 + word1.charCodeAt(i)) % mod1; + cur2 = (cur2 * base2 + word1.charCodeAt(i)) % mod2; + } + + for (let i = 0; i <= n - m; i++) { + if (cur1 === hash1 && cur2 === hash2) { + return i; + } + + if (i + m < n) { + cur1 = (cur1 * base1 - word1.charCodeAt(i) * power1 + word1.charCodeAt(i + m)) % mod1; + cur2 = (cur2 * base2 - word1.charCodeAt(i) * power2 + word1.charCodeAt(i + m)) % mod2; + + cur1 = (cur1 + mod1) % mod1; + cur2 = (cur2 + mod2) % mod2; + } + } + + return -1; + }; + + words.sort((a, b) => a.length - b.length); + let res = []; + + for (let i = 0; i < words.length; i++) { + for (let j = i + 1; j < words.length; j++) { + if (rabinKarp(words[j], words[i]) !== -1) { + res.push(words[i]); + break; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2 * m)$ +* Space complexity: + * $O(1)$ or $O(n)$ space depending on the sorting algorithm. + * $O(n * m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the length of the longest word. + +--- + +## 5. Z-Algorithm + +::tabs-start + +```python +class Solution: + def stringMatching(self, words: List[str]) -> List[str]: + def zAlgorithm(word1: str, word2: str) -> int: + s = word2 + "$" + word1 + n = len(s) + z = [0] * n + l, r = 0, 0 + + for i in range(1, n): + if i <= r: + z[i] = min(r - i + 1, z[i - l]) + while i + z[i] < n and s[z[i]] == s[i + z[i]]: + z[i] += 1 + if i + z[i] - 1 > r: + l, r = i, i + z[i] - 1 + + for i in range(len(word2) + 1, n): + if z[i] == len(word2): + return i - len(word2) - 1 + + return -1 + + res = [] + words.sort(key=len) + + for i in range(len(words)): + for j in range(i + 1, len(words)): + if zAlgorithm(words[j], words[i]) != -1: + res.append(words[i]) + break + + return res +``` + +```java +public class Solution { + public List stringMatching(String[] words) { + List res = new ArrayList<>(); + Arrays.sort(words, Comparator.comparingInt(String::length)); + + for (int i = 0; i < words.length; i++) { + for (int j = i + 1; j < words.length; j++) { + if (zAlgorithm(words[j], words[i]) != -1) { + res.add(words[i]); + break; + } + } + } + + return res; + } + + private int zAlgorithm(String word1, String word2) { + String s = word2 + "$" + word1; + int n = s.length(); + int[] z = new int[n]; + int l = 0, r = 0; + + for (int i = 1; i < n; i++) { + if (i <= r) { + z[i] = Math.min(r - i + 1, z[i - l]); + } + while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i])) { + z[i]++; + } + if (i + z[i] - 1 > r) { + l = i; + r = i + z[i] - 1; + } + } + + for (int i = word2.length() + 1; i < n; i++) { + if (z[i] == word2.length()) { + return i - word2.length() - 1; + } + } + + return -1; + } +} +``` + +```cpp +class Solution { +public: + vector stringMatching(vector& words) { + vector res; + sort(words.begin(), words.end(), [](const string& a, const string& b) { + return a.length() < b.length(); + }); + + for (int i = 0; i < words.size(); i++) { + for (int j = i + 1; j < words.size(); j++) { + if (zAlgorithm(words[j], words[i]) != -1) { + res.push_back(words[i]); + break; + } + } + } + + return res; + } + +private: + int zAlgorithm(const string& word1, const string& word2) { + string s = word2 + "$" + word1; + int n = s.size(); + vector z(n, 0); + int l = 0, r = 0; + + for (int i = 1; i < n; i++) { + if (i <= r) { + z[i] = min(r - i + 1, z[i - l]); + } + while (i + z[i] < n && s[z[i]] == s[i + z[i]]) { + z[i]++; + } + if (i + z[i] - 1 > r) { + l = i; + r = i + z[i] - 1; + } + } + + for (int i = word2.size() + 1; i < n; i++) { + if (z[i] == word2.size()) { + return i - word2.size() - 1; + } + } + + return -1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @return {string[]} + */ + stringMatching(words) { + const zAlgorithm = (word1, word2) => { + const s = word2 + "$" + word1; + const n = s.length; + const z = Array(n).fill(0); + let l = 0, r = 0; + + for (let i = 1; i < n; i++) { + if (i <= r) { + z[i] = Math.min(r - i + 1, z[i - l]); + } + while (i + z[i] < n && s[z[i]] === s[i + z[i]]) { + z[i]++; + } + if (i + z[i] - 1 > r) { + l = i; + r = i + z[i] - 1; + } + } + + for (let i = word2.length + 1; i < n; i++) { + if (z[i] === word2.length) { + return i - word2.length - 1; + } + } + + return -1; + }; + + words.sort((a, b) => a.length - b.length); + let res = []; + + for (let i = 0; i < words.length; i++) { + for (let j = i + 1; j < words.length; j++) { + if (zAlgorithm(words[j], words[i]) !== -1) { + res.push(words[i]); + break; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2 * m)$ +* Space complexity: + * $O(m)$ extra space. + * $O(1)$ or $O(n)$ space depending on the sorting algorithm. + * $O(n * m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the length of the longest word. + +--- + +## 6. Trie + +::tabs-start + +```python +class TrieNode: + def __init__(self): + self.children = [None] * 26 + self.cnt = 0 + +class Trie: + def __init__(self): + self.root = TrieNode() + + def insert_suffixes(self, word: str) -> None: + for i in range(len(word)): + node = self.root + for j in range(i, len(word)): + idx = ord(word[j]) - ord('a') + if not node.children[idx]: + node.children[idx] = TrieNode() + + node = node.children[idx] + node.cnt += 1 + + def search(self, word: str) -> bool: + node = self.root + for c in word: + idx = ord(c) - ord('a') + node = node.children[idx] + return node.cnt > 1 + +class Solution: + def stringMatching(self, words: List[str]) -> List[str]: + res = [] + trie = Trie() + + for word in words: + trie.insert_suffixes(word) + + for word in words: + if trie.search(word): + res.append(word) + + return res +``` + +```java +class TrieNode { + TrieNode[] children; + int cnt; + + TrieNode() { + children = new TrieNode[26]; + cnt = 0; + } +} + +class Trie { + TrieNode root; + + Trie() { + root = new TrieNode(); + } + + void insertSuffixes(String word) { + for (int i = 0; i < word.length(); i++) { + TrieNode node = root; + for (int j = i; j < word.length(); j++) { + int idx = word.charAt(j) - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new TrieNode(); + } + + node = node.children[idx]; + node.cnt++; + } + } + } + + boolean search(String word) { + TrieNode node = root; + for (int i = 0; i < word.length(); i++) { + int idx = word.charAt(i) - 'a'; + node = node.children[idx]; + } + return node.cnt > 1; + } +} + +class Solution { + public List stringMatching(String[] words) { + List res = new ArrayList<>(); + Trie trie = new Trie(); + + for (String word : words) { + trie.insertSuffixes(word); + } + + for (String word : words) { + if (trie.search(word)) { + res.add(word); + } + } + + return res; + } +} +``` + +```cpp +class TrieNode { +public: + TrieNode* children[26]; + int cnt; + + TrieNode() { + for (int i = 0; i < 26; i++) children[i] = nullptr; + cnt = 0; + } +}; + +class Trie { +public: + TrieNode* root; + + Trie() { + root = new TrieNode(); + } + + void insertSuffixes(const string& word) { + for (int i = 0; i < word.size(); i++) { + TrieNode* node = root; + for (int j = i; j < word.size(); j++) { + int idx = word[j] - 'a'; + if (!node->children[idx]) { + node->children[idx] = new TrieNode(); + } + + node = node->children[idx]; + node->cnt++; + } + } + } + + bool search(const string& word) { + TrieNode* node = root; + for (char c : word) { + int idx = c - 'a'; + node = node->children[idx]; + } + return node->cnt > 1; + } +}; + +class Solution { +public: + vector stringMatching(vector& words) { + vector res; + Trie trie; + + for (const string& word : words) { + trie.insertSuffixes(word); + } + + for (const string& word : words) { + if (trie.search(word)) { + res.push_back(word); + } + } + + return res; + } +}; +``` + +```javascript +class TrieNode { + constructor() { + this.children = new Array(26).fill(null); + this.cnt = 0; + } +} + +class Trie { + constructor() { + this.root = new TrieNode(); + } + + /** + * @param {string} word + * @return {void} + */ + insertSuffixes(word) { + for (let i = 0; i < word.length; i++) { + let node = this.root; + for (let j = i; j < word.length; j++) { + let idx = word.charCodeAt(j) - 97; + if (!node.children[idx]) { + node.children[idx] = new TrieNode(); + } + + node = node.children[idx]; + node.cnt++; + } + } + } + + /** + * @param {string} word + * @return {boolean} + */ + search(word) { + let node = this.root; + for (let i = 0; i < word.length; i++) { + let idx = word.charCodeAt(i) - 97; + node = node.children[idx]; + } + return node.cnt > 1; + } +} + +class Solution { + /** + * @param {string[]} words + * @return {string[]} + */ + stringMatching(words) { + const res = []; + const trie = new Trie(); + + for (let word of words) { + trie.insertSuffixes(word); + } + + for (let word of words) { + if (trie.search(word)) { + res.push(word); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m ^ 2)$ +* Space complexity: + * $O(n * m ^ 2)$ extra space. + * $O(n * m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the length of the longest word. \ No newline at end of file From bb693d92e99ee229678fe6070fd69285dd75d6f7 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Thu, 3 Apr 2025 21:22:40 +0530 Subject: [PATCH 2/9] Batch-6/Neetcode-ALL/Added-articles --- .../check-if-array-is-sorted-and-rotated.md | 306 +++++++++++ articles/circular-sentence.md | 154 ++++++ .../count-the-number-of-consistent-strings.md | 415 +++++++++++++++ articles/divide-array-into-equal-pairs.md | 290 +++++++++++ articles/find-missing-and-repeated-values.md | 492 ++++++++++++++++++ articles/height-checker.md | 206 ++++++++ articles/special-array-i.md | 129 +++++ 7 files changed, 1992 insertions(+) create mode 100644 articles/check-if-array-is-sorted-and-rotated.md create mode 100644 articles/circular-sentence.md create mode 100644 articles/count-the-number-of-consistent-strings.md create mode 100644 articles/divide-array-into-equal-pairs.md create mode 100644 articles/find-missing-and-repeated-values.md create mode 100644 articles/height-checker.md create mode 100644 articles/special-array-i.md diff --git a/articles/check-if-array-is-sorted-and-rotated.md b/articles/check-if-array-is-sorted-and-rotated.md new file mode 100644 index 000000000..061da0d48 --- /dev/null +++ b/articles/check-if-array-is-sorted-and-rotated.md @@ -0,0 +1,306 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def check(self, nums: List[int]) -> bool: + sortedNums = sorted(nums) + arr = [] + + for i in range(len(nums)): + arr.insert(0, sortedNums.pop()) + if nums == arr + sortedNums: + return True + + return False +``` + +```java +public class Solution { + public boolean check(int[] nums) { + int n = nums.length; + int[] sortedNums = nums.clone(); + Arrays.sort(sortedNums); + + for (int i = 0; i < n; i++) { + boolean match = true; + int idx = 0; + for (int j = n - i; j < n && match; j++) { + if (nums[idx] != sortedNums[j]) { + match = false; + } + idx += 1; + } + + for (int j = 0; j < n - i && match; j++) { + if (nums[idx] != sortedNums[j]) { + match = false; + } + idx += 1; + } + + if (match) return true; + } + + return false; + } +} +``` + +```cpp +class Solution { +public: + bool check(vector& nums) { + int n = nums.size(); + vector sortedNums = nums; + sort(sortedNums.begin(), sortedNums.end()); + + for (int i = 0; i < n; i++) { + bool match = true; + int idx = 0; + for (int j = n - i; j < n && match; j++) { + if (nums[idx] != sortedNums[j]) { + match = false; + } + idx++; + } + + for (int j = 0; j < n - i && match; j++) { + if (nums[idx] != sortedNums[j]) { + match = false; + } + idx++; + } + + if (match) return true; + } + + return false; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + check(nums) { + const n = nums.length; + const sortedNums = [...nums].sort((a, b) => a - b); + + for (let i = 0; i < n; i++) { + let match = true; + let idx = 0; + + for (let j = n - i; j < n && match; j++) { + if (nums[idx] !== sortedNums[j]) { + match = false; + } + idx++; + } + + for (let j = 0; j < n - i && match; j++) { + if (nums[idx] !== sortedNums[j]) { + match = false; + } + idx++; + } + + if (match) return true; + } + + return false; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n)$ + +--- + +## 2. Sliding Window + +::tabs-start + +```python +class Solution: + def check(self, nums: List[int]) -> bool: + N = len(nums) + count = 1 + + for i in range(1, 2 * N): + if nums[(i - 1) % N] <= nums[i % N]: + count += 1 + else: + count = 1 + if count == N: + return True + + return N == 1 +``` + +```java +public class Solution { + public boolean check(int[] nums) { + int N = nums.length; + int count = 1; + + for (int i = 1; i < 2 * N; i++) { + if (nums[(i - 1) % N] <= nums[i % N]) { + count++; + } else { + count = 1; + } + if (count == N) { + return true; + } + } + + return N == 1; + } +} +``` + +```cpp +class Solution { +public: + bool check(vector& nums) { + int N = nums.size(); + int count = 1; + + for (int i = 1; i < 2 * N; i++) { + if (nums[(i - 1) % N] <= nums[i % N]) { + count++; + } else { + count = 1; + } + if (count == N) { + return true; + } + } + + return N == 1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + check(nums) { + const N = nums.length; + let count = 1; + + for (let i = 1; i < 2 * N; i++) { + if (nums[(i - 1) % N] <= nums[i % N]) { + count++; + } else { + count = 1; + } + if (count === N) { + return true; + } + } + + return N === 1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 3. Iteration + +::tabs-start + +```python +class Solution: + def check(self, nums: List[int]) -> bool: + count, N = 0, len(nums) + + for i in range(N): + if nums[i] > nums[(i + 1) % N]: + count += 1 + if count > 1: + return False + + return True +``` + +```java +public class Solution { + public boolean check(int[] nums) { + int count = 0, N = nums.length; + + for (int i = 0; i < N; i++) { + if (nums[i] > nums[(i + 1) % N] && ++count > 1) { + return false; + } + } + + return true; + } +} +``` + +```cpp +class Solution { +public: + bool check(vector& nums) { + int count = 0, N = nums.size(); + + for (int i = 0; i < N; i++) { + if (nums[i] > nums[(i + 1) % N] && ++count > 1) { + return false; + } + } + + return true; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + check(nums) { + let count = 0, N = nums.length; + + for (let i = 0; i < N; i++) { + if (nums[i] > nums[(i + 1) % N] && ++count > 1) { + return false; + } + } + + 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/circular-sentence.md b/articles/circular-sentence.md new file mode 100644 index 000000000..c4e969dc1 --- /dev/null +++ b/articles/circular-sentence.md @@ -0,0 +1,154 @@ +## 1. Splitting the String + +::tabs-start + +```python +class Solution: + def isCircularSentence(self, sentence: str) -> bool: + w = sentence.split(" ") + + for i in range(len(w)): + if w[i][0] != w[i - 1][-1]: + return False + + return True +``` + +```java +public class Solution { + public boolean isCircularSentence(String sentence) { + String[] w = sentence.split(" "); + int n = w.length; + + for (int i = 0; i < n; i++) { + char start = w[i].charAt(0); + char end = w[(i - 1 + n) % n].charAt(w[(i - 1 + n) % n].length() - 1); + if (start != end) { + return false; + } + } + + return true; + } +} +``` + +```cpp +class Solution { +public: + bool isCircularSentence(string sentence) { + vector w; + stringstream ss(sentence); + string word; + + while (ss >> word) { + w.push_back(word); + } + + for (int i = 0; i < w.size(); i++) { + char start = w[i][0]; + char end = w[(i - 1 + w.size()) % w.size()].back(); + if (start != end) { + return false; + } + } + + return true; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} sentence + * @return {boolean} + */ + isCircularSentence(sentence) { + const w = sentence.split(" "); + + for (let i = 0; i < w.length; i++) { + const start = w[i][0]; + const prevEnd = w[(i - 1 + w.length) % w.length].slice(-1); + if (start !== prevEnd) { + return false; + } + } + + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Iteration (Space Optimized) + +::tabs-start + +```python +class Solution: + def isCircularSentence(self, sentence: str) -> bool: + for i in range(len(sentence)): + if sentence[i] == " " and sentence[i - 1] != sentence[i + 1]: + return False + return sentence[0] == sentence[-1] +``` + +```java +public class Solution { + public boolean isCircularSentence(String sentence) { + for (int i = 0; i < sentence.length(); i++) { + if (sentence.charAt(i) == ' ' && sentence.charAt(i - 1) != sentence.charAt(i + 1)) { + return false; + } + } + return sentence.charAt(0) == sentence.charAt(sentence.length() - 1); + } +} +``` + +```cpp +class Solution { +public: + bool isCircularSentence(string sentence) { + for (int i = 0; i < sentence.size(); i++) { + if (sentence[i] == ' ' && sentence[i - 1] != sentence[i + 1]) { + return false; + } + } + return sentence.front() == sentence.back(); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} sentence + * @return {boolean} + */ + isCircularSentence(sentence) { + for (let i = 0; i < sentence.length; i++) { + if (sentence[i] === ' ' && sentence[i - 1] !== sentence[i + 1]) { + return false; + } + } + return sentence[0] === sentence[sentence.length - 1]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/count-the-number-of-consistent-strings.md b/articles/count-the-number-of-consistent-strings.md new file mode 100644 index 000000000..600698357 --- /dev/null +++ b/articles/count-the-number-of-consistent-strings.md @@ -0,0 +1,415 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def countConsistentStrings(self, allowed: str, words: List[str]) -> int: + res = 0 + + for w in words: + flag = 1 + for c in w: + if c not in allowed: + flag = 0 + break + res += flag + + return res +``` + +```java +public class Solution { + public int countConsistentStrings(String allowed, String[] words) { + int res = 0; + + for (String w : words) { + boolean flag = true; + for (char c : w.toCharArray()) { + if (allowed.indexOf(c) == -1) { + flag = false; + break; + } + } + if (flag) res++; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int countConsistentStrings(string allowed, vector& words) { + int res = 0; + + for (string& w : words) { + bool flag = true; + for (char c : w) { + if (allowed.find(c) == string::npos) { + flag = false; + break; + } + } + res += flag; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} allowed + * @param {string[]} words + * @return {number} + */ + countConsistentStrings(allowed, words) { + let res = 0; + + for (let w of words) { + let flag = 1; + for (let c of w) { + if (!allowed.includes(c)) { + flag = 0; + break; + } + } + res += flag; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m * l)$ +* Space complexity: $O(1)$ + +> Where $n$ is the number of words, $m$ is the length of the string $allowed$, and $l$ is the length of the longest word. + +--- + +## 2. Hash Set + +::tabs-start + +```python +class Solution: + def countConsistentStrings(self, allowed: str, words: List[str]) -> int: + allowed = set(allowed) + + res = len(words) + for w in words: + for c in w: + if c not in allowed: + res -= 1 + break + + return res +``` + +```java +public class Solution { + public int countConsistentStrings(String allowed, String[] words) { + Set allowedSet = new HashSet<>(); + for (char c : allowed.toCharArray()) { + allowedSet.add(c); + } + + int res = words.length; + for (String w : words) { + for (char c : w.toCharArray()) { + if (!allowedSet.contains(c)) { + res--; + break; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int countConsistentStrings(string allowed, vector& words) { + unordered_set allowedSet(allowed.begin(), allowed.end()); + + int res = words.size(); + for (string& w : words) { + for (char c : w) { + if (allowedSet.find(c) == allowedSet.end()) { + res--; + break; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} allowed + * @param {string[]} words + * @return {number} + */ + countConsistentStrings(allowed, words) { + const allowedSet = new Set(allowed); + let res = words.length; + + for (let w of words) { + for (let c of w) { + if (!allowedSet.has(c)) { + res--; + break; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * l + m)$ +* Space complexity: $O(m)$ + +> Where $n$ is the number of words, $m$ is the length of the string $allowed$, and $l$ is the length of the longest word. + +--- + +## 3. Boolean Array + +::tabs-start + +```python +class Solution: + def countConsistentStrings(self, allowed: str, words: List[str]) -> int: + allowedArr = [False] * 26 + for c in allowed: + allowedArr[ord(c) - ord('a')] = True + + res = len(words) + for w in words: + for c in w: + if not allowedArr[ord(c) - ord('a')]: + res -= 1 + break + + return res +``` + +```java +public class Solution { + public int countConsistentStrings(String allowed, String[] words) { + Set allowedSet = new HashSet<>(); + for (char c : allowed.toCharArray()) { + allowedSet.add(c); + } + + int res = words.length; + for (String w : words) { + for (char c : w.toCharArray()) { + if (!allowedSet.contains(c)) { + res--; + break; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int countConsistentStrings(string allowed, vector& words) { + bool allowedArr[26] = {}; + for (char c : allowed) { + allowedArr[c - 'a'] = true; + } + + int res = words.size(); + for (const string& w : words) { + for (char c : w) { + if (!allowedArr[c - 'a']) { + res--; + break; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} allowed + * @param {string[]} words + * @return {number} + */ + countConsistentStrings(allowed, words) { + const allowedArr = new Array(26).fill(false); + for (let c of allowed) { + allowedArr[c.charCodeAt(0) - 97] = true; + } + + let res = words.length; + for (let w of words) { + for (let c of w) { + if (!allowedArr[c.charCodeAt(0) - 97]) { + res--; + break; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * l + m)$ +* Space complexity: $O(m)$ + +> Where $n$ is the number of words, $m$ is the length of the string $allowed$, and $l$ is the length of the longest word. + +--- + +## 4. Bitmask + +::tabs-start + +```python +class Solution: + def countConsistentStrings(self, allowed: str, words: List[str]) -> int: + bit_mask = 0 + for c in allowed: + bit = 1 << (ord(c) - ord('a')) + bit_mask = bit_mask | bit + + res = len(words) + for w in words: + for c in w: + bit = 1 << (ord(c) - ord('a')) + if bit & bit_mask == 0: + res -= 1 + break + + return res +``` + +```java +public class Solution { + public int countConsistentStrings(String allowed, String[] words) { + int bitMask = 0; + for (char c : allowed.toCharArray()) { + bitMask |= 1 << (c - 'a'); + } + + int res = words.length; + for (String w : words) { + for (char c : w.toCharArray()) { + int bit = 1 << (c - 'a'); + if ((bit & bitMask) == 0) { + res--; + break; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int countConsistentStrings(string allowed, vector& words) { + int bitMask = 0; + for (char c : allowed) { + bitMask |= (1 << (c - 'a')); + } + + int res = words.size(); + for (const string& w : words) { + for (char c : w) { + int bit = 1 << (c - 'a'); + if ((bit & bitMask) == 0) { + res--; + break; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} allowed + * @param {string[]} words + * @return {number} + */ + countConsistentStrings(allowed, words) { + let bitMask = 0; + for (let c of allowed) { + bitMask |= 1 << (c.charCodeAt(0) - 97); + } + + let res = words.length; + for (let w of words) { + for (let c of w) { + const bit = 1 << (c.charCodeAt(0) - 97); + if ((bit & bitMask) === 0) { + res--; + break; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * l + m)$ +* Space complexity: $O(1)$ + +> Where $n$ is the number of words, $m$ is the length of the string $allowed$, and $l$ is the length of the longest word. \ No newline at end of file diff --git a/articles/divide-array-into-equal-pairs.md b/articles/divide-array-into-equal-pairs.md new file mode 100644 index 000000000..bc8a01fb1 --- /dev/null +++ b/articles/divide-array-into-equal-pairs.md @@ -0,0 +1,290 @@ +## 1. Sorting + +::tabs-start + +```python +class Solution: + def divideArray(self, nums: List[int]) -> bool: + N = len(nums) + nums.sort() + + i = 0 + while i < N: + j = i + while j < N and nums[i] == nums[j]: + j += 1 + + if (j - i) % 2 != 0: + return False + + i = j + + return True +``` + +```java +public class Solution { + public boolean divideArray(int[] nums) { + int N = nums.length; + Arrays.sort(nums); + + int i = 0; + while (i < N) { + int j = i; + while (j < N && nums[i] == nums[j]) { + j++; + } + + if ((j - i) % 2 != 0) { + return false; + } + + i = j; + } + + return true; + } +} +``` + +```cpp +class Solution { +public: + bool divideArray(vector& nums) { + int N = nums.size(); + sort(nums.begin(), nums.end()); + + int i = 0; + while (i < N) { + int j = i; + while (j < N && nums[i] == nums[j]) { + j++; + } + + if ((j - i) % 2 != 0) { + return false; + } + + i = j; + } + + return true; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + divideArray(nums) { + const N = nums.length; + nums.sort((a, b) => a - b); + + let i = 0; + while (i < N) { + let j = i; + while (j < N && nums[i] === nums[j]) { + j++; + } + + if ((j - i) % 2 !== 0) { + return false; + } + + i = j; + } + + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. + +--- + +## 2. Hash Map + +::tabs-start + +```python +class Solution: + def divideArray(self, nums: List[int]) -> bool: + count = {} + for num in nums: + if num not in count: + count[num] = 0 + count[num] += 1 + + for cnt in count.values(): + if cnt % 2 == 1: + return False + + return True +``` + +```java +public class Solution { + public boolean divideArray(int[] nums) { + Map count = new HashMap<>(); + for (int num : nums) { + count.put(num, count.getOrDefault(num, 0) + 1); + } + + for (int cnt : count.values()) { + if (cnt % 2 == 1) { + return false; + } + } + + return true; + } +} +``` + +```cpp +class Solution { +public: + bool divideArray(vector& nums) { + unordered_map count; + for (int num : nums) { + count[num]++; + } + + for (auto& [key, cnt] : count) { + if (cnt % 2 == 1) { + return false; + } + } + + return true; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + divideArray(nums) { + const count = {}; + for (let num of nums) { + if (!(num in count)) { + count[num] = 0; + } + count[num]++; + } + + for (let key in count) { + if (count[key] % 2 === 1) { + return false; + } + } + + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Hash Set + +::tabs-start + +```python +class Solution: + def divideArray(self, nums: List[int]) -> bool: + odd_set = set() + + for num in nums: + if num not in odd_set: + odd_set.add(num) + else: + odd_set.remove(num) + + return not len(odd_set) +``` + +```java +public class Solution { + public boolean divideArray(int[] nums) { + Set oddSet = new HashSet<>(); + + for (int num : nums) { + if (!oddSet.contains(num)) { + oddSet.add(num); + } else { + oddSet.remove(num); + } + } + + return oddSet.isEmpty(); + } +} +``` + +```cpp +class Solution { +public: + bool divideArray(vector& nums) { + unordered_set oddSet; + + for (int num : nums) { + if (oddSet.count(num)) { + oddSet.erase(num); + } else { + oddSet.insert(num); + } + } + + return oddSet.empty(); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + divideArray(nums) { + const oddSet = new Set(); + + for (let num of nums) { + if (oddSet.has(num)) { + oddSet.delete(num); + } else { + oddSet.add(num); + } + } + + return oddSet.size === 0; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/find-missing-and-repeated-values.md b/articles/find-missing-and-repeated-values.md new file mode 100644 index 000000000..58753bb0f --- /dev/null +++ b/articles/find-missing-and-repeated-values.md @@ -0,0 +1,492 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def findMissingAndRepeatedValues(self, grid: List[List[int]]) -> List[int]: + n = len(grid) + double = missing = 0 + + for num in range(1, n * n + 1): + cnt = 0 + for i in range(n): + for j in range(n): + if num == grid[i][j]: + cnt += 1 + + if cnt == 2: + double = num + elif cnt == 0: + missing = num + + return [double, missing] +``` + +```java +public class Solution { + public int[] findMissingAndRepeatedValues(int[][] grid) { + int n = grid.length; + int doubleVal = 0, missing = 0; + + for (int num = 1; num <= n * n; num++) { + int cnt = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == num) { + cnt++; + } + } + } + + if (cnt == 2) { + doubleVal = num; + } else if (cnt == 0) { + missing = num; + } + } + + return new int[]{doubleVal, missing}; + } +} +``` + +```cpp +class Solution { +public: + vector findMissingAndRepeatedValues(vector>& grid) { + int n = grid.size(); + int doubleVal = 0, missing = 0; + + for (int num = 1; num <= n * n; num++) { + int cnt = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == num) { + cnt++; + } + } + } + + if (cnt == 2) { + doubleVal = num; + } else if (cnt == 0) { + missing = num; + } + } + + return {doubleVal, missing}; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[][]} grid + * @return {number[]} + */ + findMissingAndRepeatedValues(grid) { + const n = grid.length; + let doubleVal = 0, missing = 0; + + for (let num = 1; num <= n * n; num++) { + let cnt = 0; + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === num) { + cnt++; + } + } + } + + if (cnt === 2) { + doubleVal = num; + } else if (cnt === 0) { + missing = num; + } + } + + return [doubleVal, missing]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 4)$ +* Space complexity: $O(1)$ + +--- + +## 2. Hash Map + +::tabs-start + +```python +class Solution: + def findMissingAndRepeatedValues(self, grid: List[List[int]]) -> List[int]: + N = len(grid) + count = defaultdict(int) + + for i in range(N): + for j in range(N): + count[grid[i][j]] += 1 + + double = missing = 0 + + for num in range(1, N * N + 1): + if count[num] == 0: + missing = num + if count[num] == 2: + double = num + + return [double, missing] +``` + +```java +public class Solution { + public int[] findMissingAndRepeatedValues(int[][] grid) { + int N = grid.length; + Map count = new HashMap<>(); + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + count.put(grid[i][j], count.getOrDefault(grid[i][j], 0) + 1); + } + } + + int doubleVal = 0, missing = 0; + + for (int num = 1; num <= N * N; num++) { + int freq = count.getOrDefault(num, 0); + if (freq == 0) missing = num; + if (freq == 2) doubleVal = num; + } + + return new int[]{doubleVal, missing}; + } +} +``` + +```cpp +class Solution { +public: + vector findMissingAndRepeatedValues(vector>& grid) { + int N = grid.size(); + unordered_map count; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + count[grid[i][j]]++; + } + } + + int doubleVal = 0, missing = 0; + + for (int num = 1; num <= N * N; num++) { + int freq = count[num]; + if (freq == 0) missing = num; + if (freq == 2) doubleVal = num; + } + + return {doubleVal, missing}; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[][]} grid + * @return {number[]} + */ + findMissingAndRepeatedValues(grid) { + const N = grid.length; + const count = {}; + + for (let i = 0; i < N; i++) { + for (let j = 0; j < N; j++) { + let val = grid[i][j]; + count[val] = (count[val] || 0) + 1; + } + } + + let doubleVal = 0, missing = 0; + + for (let num = 1; num <= N * N; num++) { + let freq = count[num] || 0; + if (freq === 0) missing = num; + if (freq === 2) doubleVal = num; + } + + return [doubleVal, missing]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n ^ 2)$ + +--- + +## 3. Hash Set + +::tabs-start + +```python +class Solution: + def findMissingAndRepeatedValues(self, grid: List[List[int]]) -> List[int]: + N = len(grid) + seen = set() + double = missing = 0 + + for i in range(N): + for j in range(N): + if grid[i][j] in seen: + double = grid[i][j] + seen.add(grid[i][j]) + + for num in range(1, N * N + 1): + if num not in seen: + missing = num + break + + return [double, missing] +``` + +```java +public class Solution { + public int[] findMissingAndRepeatedValues(int[][] grid) { + int N = grid.length; + Set seen = new HashSet<>(); + int doubleVal = 0, missing = 0; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + if (seen.contains(grid[i][j])) { + doubleVal = grid[i][j]; + } + seen.add(grid[i][j]); + } + } + + for (int num = 1; num <= N * N; num++) { + if (!seen.contains(num)) { + missing = num; + break; + } + } + + return new int[]{doubleVal, missing}; + } +} +``` + +```cpp +class Solution { +public: + vector findMissingAndRepeatedValues(vector>& grid) { + int N = grid.size(); + unordered_set seen; + int doubleVal = 0, missing = 0; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + if (seen.count(grid[i][j])) { + doubleVal = grid[i][j]; + } + seen.insert(grid[i][j]); + } + } + + for (int num = 1; num <= N * N; num++) { + if (!seen.count(num)) { + missing = num; + break; + } + } + + return {doubleVal, missing}; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[][]} grid + * @return {number[]} + */ + findMissingAndRepeatedValues(grid) { + const N = grid.length; + const seen = new Set(); + let doubleVal = 0, missing = 0; + + for (let i = 0; i < N; i++) { + for (let j = 0; j < N; j++) { + const val = grid[i][j]; + if (seen.has(val)) { + doubleVal = val; + } + seen.add(val); + } + } + + for (let num = 1; num <= N * N; num++) { + if (!seen.has(num)) { + missing = num; + break; + } + } + + return [doubleVal, missing]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n ^ 2)$ + +--- + +## 4. Math + +::tabs-start + +```python +class Solution: + def findMissingAndRepeatedValues(self, grid: List[List[int]]) -> List[int]: + N = len(grid) + gridSum = 0 + gridSqSum = 0 + + for i in range(N): + for j in range(N): + gridSum += grid[i][j] + gridSqSum += grid[i][j] * grid[i][j] + + totSum = (N * N * (N * N + 1)) // 2 + diff = gridSum - totSum # a - b + + totSqSum = (N * N * (N * N + 1) * (2 * N * N + 1)) // 6 + sqDiff = gridSqSum - totSqSum # (a^2) - (b^2) + + sum = sqDiff // diff # a + b + + a = (sum + diff) // 2 + b = sum - a + return [a, b] +``` + +```java +public class Solution { + public int[] findMissingAndRepeatedValues(int[][] grid) { + int N = grid.length; + long gridSum = 0; + long gridSqSum = 0; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + gridSum += grid[i][j]; + gridSqSum += 1L * grid[i][j] * grid[i][j]; + } + } + + long totSum = (long) N * N * (N * N + 1) / 2; + long diff = gridSum - totSum; // a - b + + long totSqSum = (long) N * N * (N * N + 1) * (2L * N * N + 1) / 6; + long sqDiff = gridSqSum - totSqSum; // (a^2) - (b^2) + + long sum = sqDiff / diff; // a + b + + long a = (sum + diff) / 2; + long b = sum - a; + + return new int[]{(int) a, (int) b}; + } +} +``` + +```cpp +class Solution { +public: + vector findMissingAndRepeatedValues(vector>& grid) { + int N = grid.size(); + long long gridSum = 0; + long long gridSqSum = 0; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + gridSum += grid[i][j]; + gridSqSum += 1LL * grid[i][j] * grid[i][j]; + } + } + + long long totSum = 1LL * N * N * (N * N + 1) / 2; + long long diff = gridSum - totSum; // a - b + + long long totSqSum = 1LL * N * N * (N * N + 1) * (2 * N * N + 1) / 6; + long long sqDiff = gridSqSum - totSqSum; // (a^2) - (b^2) + + long long sum = sqDiff / diff; // a + b + + int a = (sum + diff) / 2; + int b = sum - a; + + return {a, b}; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[][]} grid + * @return {number[]} + */ + findMissingAndRepeatedValues(grid) { + const N = grid.length; + let gridSum = 0; + let gridSqSum = 0; + + for (let i = 0; i < N; i++) { + for (let j = 0; j < N; j++) { + gridSum += grid[i][j]; + gridSqSum += grid[i][j] * grid[i][j]; + } + } + + let totSum = N * N * (N * N + 1) / 2; + let diff = gridSum - totSum; // a - b + + let totSqSum = N * N * (N * N + 1) * (2 * N * N + 1) / 6; + let sqDiff = gridSqSum - totSqSum; // (a^2) - (b^2) + + let sum = sqDiff / diff; // a + b + + let a = (sum + diff) / 2; + let b = sum - a; + + return [a, b]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/height-checker.md b/articles/height-checker.md new file mode 100644 index 000000000..1e0919676 --- /dev/null +++ b/articles/height-checker.md @@ -0,0 +1,206 @@ +## 1. Sorting + +::tabs-start + +```python +class Solution: + def heightChecker(self, heights: List[int]) -> int: + expected = sorted(heights) + + res = 0 + for i in range(len(heights)): + if heights[i] != expected[i]: + res += 1 + + return res +``` + +```java +public class Solution { + public int heightChecker(int[] heights) { + int[] expected = Arrays.copyOf(heights, heights.length); + Arrays.sort(expected); + + int res = 0; + for (int i = 0; i < heights.length; i++) { + if (heights[i] != expected[i]) { + res++; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int heightChecker(vector& heights) { + vector expected = heights; + sort(expected.begin(), expected.end()); + + int res = 0; + for (int i = 0; i < heights.size(); i++) { + if (heights[i] != expected[i]) { + res++; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} heights + * @return {number} + */ + heightChecker(heights) { + const expected = [...heights].sort((a, b) => a - b); + + let res = 0; + for (let i = 0; i < heights.length; i++) { + if (heights[i] !== expected[i]) { + res++; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Counting Sort + +::tabs-start + +```python +class Solution: + def heightChecker(self, heights: List[int]) -> int: + count = [0] * 101 + for h in heights: + count[h] += 1 + + expected = [] + for h in range(1, 101): + c = count[h] + for _ in range(c): + expected.append(h) + + res = 0 + for i in range(len(heights)): + if heights[i] != expected[i]: + res += 1 + + return res +``` + +```java +public class Solution { + public int heightChecker(int[] heights) { + int[] count = new int[101]; + for (int h : heights) { + count[h]++; + } + + List expected = new ArrayList<>(); + for (int h = 1; h <= 100; h++) { + int c = count[h]; + for (int i = 0; i < c; i++) { + expected.add(h); + } + } + + int res = 0; + for (int i = 0; i < heights.length; i++) { + if (heights[i] != expected.get(i)) { + res++; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int heightChecker(vector& heights) { + int count[101] = {}; + for (int h : heights) { + count[h]++; + } + + vector expected; + for (int h = 1; h <= 100; h++) { + int c = count[h]; + for (int i = 0; i < c; i++) { + expected.push_back(h); + } + } + + int res = 0; + for (int i = 0; i < heights.size(); i++) { + if (heights[i] != expected[i]) { + res++; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} heights + * @return {number} + */ + heightChecker(heights) { + const count = new Array(101).fill(0); + for (let h of heights) { + count[h]++; + } + + const expected = []; + for (let h = 1; h <= 100; h++) { + let c = count[h]; + for (let i = 0; i < c; i++) { + expected.push(h); + } + } + + let res = 0; + for (let i = 0; i < heights.length; i++) { + if (heights[i] !== expected[i]) { + res++; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + k)$ +* Space complexity: $O(n + k)$ + +> Where $n$ is the size of the input array, and $k$ is the range of numbers. \ No newline at end of file diff --git a/articles/special-array-i.md b/articles/special-array-i.md new file mode 100644 index 000000000..40ccd36c6 --- /dev/null +++ b/articles/special-array-i.md @@ -0,0 +1,129 @@ +## 1. Modulo Comparision + +::tabs-start + +```python +class Solution: + def isArraySpecial(self, nums: List[int]) -> bool: + for i in range(1, len(nums)): + if nums[i - 1] % 2 == nums[i] % 2: + return False + return True +``` + +```java +public class Solution { + public boolean isArraySpecial(int[] nums) { + for (int i = 1; i < nums.length; i++) { + if (nums[i - 1] % 2 == nums[i] % 2) { + return false; + } + } + return true; + } +} +``` + +```cpp +class Solution { +public: + bool isArraySpecial(vector& nums) { + for (int i = 1; i < nums.size(); i++) { + if (nums[i - 1] % 2 == nums[i] % 2) { + return false; + } + } + return true; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + isArraySpecial(nums) { + for (let i = 1; i < nums.length; i++) { + if (nums[i - 1] % 2 === nums[i] % 2) { + return false; + } + } + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 2. Bitwise Comparision + +::tabs-start + +```python +class Solution: + def isArraySpecial(self, nums: List[int]) -> bool: + for i in range(1, len(nums)): + if nums[i - 1] & 1 == nums[i] & 1: + return False + return True +``` + +```java +public class Solution { + public boolean isArraySpecial(int[] nums) { + for (int i = 1; i < nums.length; i++) { + if ((nums[i - 1] & 1) == (nums[i] & 1)) { + return false; + } + } + return true; + } +} +``` + +```cpp +class Solution { +public: + bool isArraySpecial(vector& nums) { + for (int i = 1; i < nums.size(); i++) { + if ((nums[i - 1] & 1) == (nums[i] & 1)) { + return false; + } + } + return true; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {boolean} + */ + isArraySpecial(nums) { + for (let i = 1; i < nums.length; i++) { + if ((nums[i - 1] & 1) === (nums[i] & 1)) { + return false; + } + } + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file From f748c6eafed09a9e57d604d97419bf648c5fbfe6 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Fri, 4 Apr 2025 08:10:57 +0530 Subject: [PATCH 3/9] Batch-6/Neetcode-ALL/Added-articles --- articles/longest-palindrome.md | 419 +++++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 articles/longest-palindrome.md diff --git a/articles/longest-palindrome.md b/articles/longest-palindrome.md new file mode 100644 index 000000000..635b7a163 --- /dev/null +++ b/articles/longest-palindrome.md @@ -0,0 +1,419 @@ +## 1. Hash Map + +::tabs-start + +```python +class Solution: + def longestPalindrome(self, s: str) -> int: + count = defaultdict(int) + res = 0 + + for c in s: + count[c] += 1 + if count[c] % 2 == 0: + res += 2 + + for cnt in count.values(): + if cnt % 2: + res += 1 + break + + return res +``` + +```java +public class Solution { + public int longestPalindrome(String s) { + Map count = new HashMap<>(); + int res = 0; + + for (char c : s.toCharArray()) { + count.put(c, count.getOrDefault(c, 0) + 1); + if (count.get(c) % 2 == 0) { + res += 2; + } + } + + for (int cnt : count.values()) { + if (cnt % 2 == 1) { + res += 1; + break; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int longestPalindrome(string s) { + unordered_map count; + int res = 0; + + for (char c : s) { + count[c]++; + if (count[c] % 2 == 0) { + res += 2; + } + } + + for (auto& [ch, cnt] : count) { + if (cnt % 2 == 1) { + res += 1; + break; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number} + */ + longestPalindrome(s) { + const count = {}; + let res = 0; + + for (let c of s) { + count[c] = (count[c] || 0) + 1; + if (count[c] % 2 === 0) { + res += 2; + } + } + + for (let key in count) { + if (count[key] % 2 === 1) { + res += 1; + break; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(m)$ + +> Where $n$ is the length of the given string, and $m$ is the number of distinct characters in the string. + +--- + +## 2. Hash Map (Optimal) + +::tabs-start + +```python +class Solution: + def longestPalindrome(self, s: str) -> int: + count = defaultdict(int) + res = 0 + + for c in s: + count[c] += 1 + if count[c] % 2 == 0: + res += 2 + + return res + (res < len(s)) +``` + +```java +public class Solution { + public int longestPalindrome(String s) { + Map count = new HashMap<>(); + int res = 0; + + for (char c : s.toCharArray()) { + count.put(c, count.getOrDefault(c, 0) + 1); + if (count.get(c) % 2 == 0) { + res += 2; + } + } + + return res + (res < s.length() ? 1 : 0); + } +} +``` + +```cpp +class Solution { +public: + int longestPalindrome(string s) { + unordered_map count; + int res = 0; + + for (char c : s) { + count[c]++; + if (count[c] % 2 == 0) { + res += 2; + } + } + + return res + (res < s.size()); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number} + */ + longestPalindrome(s) { + const count = {}; + let res = 0; + + for (let c of s) { + count[c] = (count[c] || 0) + 1; + if (count[c] % 2 === 0) { + res += 2; + } + } + + return res + (res < s.length ? 1 : 0); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(m)$ + +> Where $n$ is the length of the given string, and $m$ is the number of distinct characters in the string. + +--- + +## 3. Hash Set + +::tabs-start + +```python +class Solution: + def longestPalindrome(self, s: str) -> int: + seen = set() + res = 0 + + for c in s: + if c in seen: + seen.remove(c) + res += 2 + else: + seen.add(c) + + return res + 1 if seen else res +``` + +```java +public class Solution { + public int longestPalindrome(String s) { + Set seen = new HashSet<>(); + int res = 0; + + for (char c : s.toCharArray()) { + if (seen.contains(c)) { + seen.remove(c); + res += 2; + } else { + seen.add(c); + } + } + + return seen.isEmpty() ? res : res + 1; + } +} +``` + +```cpp +class Solution { +public: + int longestPalindrome(string s) { + unordered_set seen; + int res = 0; + + for (char c : s) { + if (seen.count(c)) { + seen.erase(c); + res += 2; + } else { + seen.insert(c); + } + } + + return seen.empty() ? res : res + 1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number} + */ + longestPalindrome(s) { + const seen = new Set(); + let res = 0; + + for (let c of s) { + if (seen.has(c)) { + seen.delete(c); + res += 2; + } else { + seen.add(c); + } + } + + return seen.size === 0 ? res : res + 1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(m)$ + +> Where $n$ is the length of the given string, and $m$ is the number of distinct characters in the string. + +--- + +## 4. Bitmask + +::tabs-start + +```python +class Solution: + def longestPalindrome(self, s: str) -> int: + mask1 = 0 # [a - z] + mask2 = 0 # [A - Z] + res = 0 + + for c in s: + if 'a' <= c <= 'z': + bit = 1 << (ord(c) - ord('a')) + if mask1 & bit: + res += 2 + mask1 ^= bit + else: + bit = 1 << (ord(c) - ord('A')) + if mask2 & bit: + res += 2 + mask2 ^= bit + + return res + 1 if mask1 or mask2 else res +``` + +```java +public class Solution { + public int longestPalindrome(String s) { + int mask1 = 0; // [a - z] + int mask2 = 0; // [A - Z] + int res = 0; + + for (char c : s.toCharArray()) { + if (c >= 'a' && c <= 'z') { + int bit = 1 << (c - 'a'); + if ((mask1 & bit) != 0) { + res += 2; + } + mask1 ^= bit; + } else { + int bit = 1 << (c - 'A'); + if ((mask2 & bit) != 0) { + res += 2; + } + mask2 ^= bit; + } + } + + return (mask1 != 0 || mask2 != 0) ? res + 1 : res; + } +} +``` + +```cpp +class Solution { +public: + int longestPalindrome(string s) { + int mask1 = 0; // [a - z] + int mask2 = 0; // [A - Z] + int res = 0; + + for (char c : s) { + if ('a' <= c && c <= 'z') { + int bit = 1 << (c - 'a'); + if (mask1 & bit) { + res += 2; + } + mask1 ^= bit; + } else { + int bit = 1 << (c - 'A'); + if (mask2 & bit) { + res += 2; + } + mask2 ^= bit; + } + } + + return (mask1 || mask2) ? res + 1 : res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number} + */ + longestPalindrome(s) { + let mask1 = 0; // [a - z] + let mask2 = 0; // [A - Z] + let res = 0; + + for (let c of s) { + if (c >= 'a' && c <= 'z') { + let bit = 1 << (c.charCodeAt(0) - 97); + if (mask1 & bit) { + res += 2; + } + mask1 ^= bit; + } else { + let bit = 1 << (c.charCodeAt(0) - 65); + if (mask2 & bit) { + res += 2; + } + mask2 ^= bit; + } + } + + return (mask1 || mask2) ? res + 1 : res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file From 7d5ed7321e5ffbb23a1b304a74cbfb2d69930277 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Sat, 5 Apr 2025 21:38:07 +0530 Subject: [PATCH 4/9] Batch-6/Neetcode-ALL/Added-articles --- articles/average-waiting-time.md | 169 +++++++ articles/count-vowel-strings-in-ranges.md | 336 +++++++++++++ articles/find-common-characters.md | 122 +++++ articles/relative-sort-array.md | 551 ++++++++++++++++++++++ 4 files changed, 1178 insertions(+) create mode 100644 articles/average-waiting-time.md create mode 100644 articles/count-vowel-strings-in-ranges.md create mode 100644 articles/find-common-characters.md create mode 100644 articles/relative-sort-array.md diff --git a/articles/average-waiting-time.md b/articles/average-waiting-time.md new file mode 100644 index 000000000..0d6c7c818 --- /dev/null +++ b/articles/average-waiting-time.md @@ -0,0 +1,169 @@ +## 1. Simulation - I + +::tabs-start + +```python +class Solution: + def averageWaitingTime(self, customers: List[List[int]]) -> float: + t = 0 + total = 0 + + for arrival, order in customers: + if t > arrival: + total += t - arrival + else: + t = arrival + total += order + t += order + + return total / len(customers) +``` + +```java +public class Solution { + public double averageWaitingTime(int[][] customers) { + long t = 0, total = 0; + + for (int[] c : customers) { + int arrival = c[0], order = c[1]; + if (t > arrival) { + total += t - arrival; + } else { + t = arrival; + } + total += order; + t += order; + } + + return (double) total / customers.length; + } +} +``` + +```cpp +class Solution { +public: + double averageWaitingTime(vector>& customers) { + long long t = 0, total = 0; + + for (auto& c : customers) { + int arrival = c[0], order = c[1]; + if (t > arrival) { + total += t - arrival; + } else { + t = arrival; + } + total += order; + t += order; + } + + return (double) total / customers.size(); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[][]} customers + * @return {number} + */ + averageWaitingTime(customers) { + let t = 0, total = 0; + + for (let [arrival, order] of customers) { + if (t > arrival) { + total += t - arrival; + } else { + t = arrival; + } + total += order; + t += order; + } + + return total / customers.length; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 2. Simulation - II + +::tabs-start + +```python +class Solution: + def averageWaitingTime(self, customers: List[List[int]]) -> float: + t = total = 0 + for arrival, order in customers: + t = max(t, arrival) + order + total += t - arrival + return total / len(customers) +``` + +```java +public class Solution { + public double averageWaitingTime(int[][] customers) { + long t = 0, total = 0; + + for (int[] c : customers) { + int arrival = c[0], order = c[1]; + t = Math.max(t, arrival) + order; + total += t - arrival; + } + + return (double) total / customers.length; + } +} +``` + +```cpp +class Solution { +public: + double averageWaitingTime(vector>& customers) { + long long t = 0, total = 0; + + for (auto& c : customers) { + int arrival = c[0], order = c[1]; + t = max(t, (long long)arrival) + order; + total += t - arrival; + } + + return (double) total / customers.size(); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[][]} customers + * @return {number} + */ + averageWaitingTime(customers) { + let t = 0, total = 0; + + for (let [arrival, order] of customers) { + t = Math.max(t, arrival) + order; + total += t - arrival; + } + + return total / customers.length; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/count-vowel-strings-in-ranges.md b/articles/count-vowel-strings-in-ranges.md new file mode 100644 index 000000000..22c92a839 --- /dev/null +++ b/articles/count-vowel-strings-in-ranges.md @@ -0,0 +1,336 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def vowelStrings(self, words: List[str], queries: List[List[int]]) -> List[int]: + vowels = set("aeiou") + res = [] + + for start, end in queries: + cnt = 0 + for i in range(start, end + 1): + if words[i][0] in vowels and words[i][-1] in vowels: + cnt += 1 + res.append(cnt) + + return res +``` + +```java +public class Solution { + public int[] vowelStrings(String[] words, int[][] queries) { + Set vowels = Set.of('a', 'e', 'i', 'o', 'u'); + int[] res = new int[queries.length]; + + for (int k = 0; k < queries.length; k++) { + int start = queries[k][0], end = queries[k][1], count = 0; + + for (int i = start; i <= end; i++) { + String word = words[i]; + if (vowels.contains(word.charAt(0)) && vowels.contains(word.charAt(word.length() - 1))) { + count++; + } + } + + res[k] = count; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector vowelStrings(vector& words, vector>& queries) { + unordered_set vowels = {'a', 'e', 'i', 'o', 'u'}; + vector res; + + for (auto& q : queries) { + int start = q[0], end = q[1], count = 0; + + for (int i = start; i <= end; i++) { + if (vowels.count(words[i][0]) && vowels.count(words[i].back())) { + count++; + } + } + + res.push_back(count); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @param {number[][]} queries + * @return {number[]} + */ + vowelStrings(words, queries) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u']); + const res = []; + + for (let [start, end] of queries) { + let count = 0; + for (let i = start; i <= end; i++) { + const word = words[i]; + if (vowels.has(word[0]) && vowels.has(word[word.length - 1])) { + count++; + } + } + res.push(count); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: + * $O(1)$ extra space. + * $O(m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the number of queries. + +--- + +## 2. Prefix Sum + Hash Set + +::tabs-start + +```python +class Solution: + def vowelStrings(self, words: List[str], queries: List[List[int]]) -> List[int]: + vowel_set = set("aeiou") + prefix_cnt = [0] * (len(words) + 1) + prev = 0 + + for i, w in enumerate(words): + if w[0] in vowel_set and w[-1] in vowel_set: + prev += 1 + prefix_cnt[i + 1] = prev + + res = [0] * len(queries) + for i, q in enumerate(queries): + l, r = q + res[i] = prefix_cnt[r + 1] - prefix_cnt[l] + + return res +``` + +```java +public class Solution { + public int[] vowelStrings(String[] words, int[][] queries) { + Set vowels = Set.of('a', 'e', 'i', 'o', 'u'); + int n = words.length; + int[] prefixCnt = new int[n + 1]; + + for (int i = 0; i < n; i++) { + String w = words[i]; + prefixCnt[i + 1] = prefixCnt[i]; + if (vowels.contains(w.charAt(0)) && vowels.contains(w.charAt(w.length() - 1))) { + prefixCnt[i + 1]++; + } + } + + int[] res = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + int l = queries[i][0], r = queries[i][1]; + res[i] = prefixCnt[r + 1] - prefixCnt[l]; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector vowelStrings(vector& words, vector>& queries) { + unordered_set vowels = {'a', 'e', 'i', 'o', 'u'}; + int n = words.size(); + vector prefixCnt(n + 1, 0); + + for (int i = 0; i < n; i++) { + prefixCnt[i + 1] = prefixCnt[i]; + if (vowels.count(words[i][0]) && vowels.count(words[i].back())) { + prefixCnt[i + 1]++; + } + } + + vector res; + for (auto& q : queries) { + int l = q[0], r = q[1]; + res.push_back(prefixCnt[r + 1] - prefixCnt[l]); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @param {number[][]} queries + * @return {number[]} + */ + vowelStrings(words, queries) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u']); + const n = words.length; + const prefixCnt = new Array(n + 1).fill(0); + + for (let i = 0; i < n; i++) { + prefixCnt[i + 1] = prefixCnt[i]; + const w = words[i]; + if (vowels.has(w[0]) && vowels.has(w[w.length - 1])) { + prefixCnt[i + 1]++; + } + } + + const res = new Array(queries.length); + for (let i = 0; i < queries.length; i++) { + const [l, r] = queries[i]; + res[i] = prefixCnt[r + 1] - prefixCnt[l]; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: + * $O(n)$ extra space. + * $O(m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the number of queries. + +--- + +## 3. Prefix Sum + Bitmask + +::tabs-start + +```python +class Solution: + def vowelStrings(self, words: List[str], queries: List[List[int]]) -> List[int]: + vowels = sum(1 << (ord(c) - ord('a')) for c in "aeiou") + prefix = [0] + for w in words: + prefix.append(prefix[-1]) + if (1 << (ord(w[0]) - ord('a'))) & vowels and (1 << (ord(w[-1]) - ord('a'))) & vowels: + prefix[-1] += 1 + return [prefix[r + 1] - prefix[l] for l, r in queries] +``` + +```java +public class Solution { + public int[] vowelStrings(String[] words, int[][] queries) { + int vowels = 0; + for (char c : "aeiou".toCharArray()) { + vowels |= 1 << (c - 'a'); + } + + int[] prefix = new int[words.length + 1]; + for (int i = 0; i < words.length; i++) { + int f = words[i].charAt(0) - 'a'; + int l = words[i].charAt(words[i].length() - 1) - 'a'; + int isVowel = ((1 << f) & vowels) != 0 && ((1 << l) & vowels) != 0 ? 1 : 0; + prefix[i + 1] = prefix[i] + isVowel; + } + + int[] res = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + int l = queries[i][0], r = queries[i][1]; + res[i] = prefix[r + 1] - prefix[l]; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector vowelStrings(vector& words, vector>& queries) { + int vowels = 0; + for (char c : string("aeiou")) { + vowels |= (1 << (c - 'a')); + } + + int n = words.size(); + vector prefix(n + 1); + for (int i = 0; i < n; i++) { + int f = words[i][0] - 'a'; + int l = words[i].back() - 'a'; + int isVowel = ((1 << f) & vowels) && ((1 << l) & vowels); + prefix[i + 1] = prefix[i] + isVowel; + } + + vector res; + for (auto& q : queries) { + int l = q[0], r = q[1]; + res.push_back(prefix[r + 1] - prefix[l]); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @param {number[][]} queries + * @return {number[]} + */ + vowelStrings(words, queries) { + let vowels = 0; + for (let c of "aeiou") { + vowels |= 1 << (c.charCodeAt(0) - 97); + } + + const prefix = [0]; + for (let w of words) { + const f = w.charCodeAt(0) - 97; + const l = w.charCodeAt(w.length - 1) - 97; + const isVowel = ((1 << f) & vowels) && ((1 << l) & vowels) ? 1 : 0; + prefix.push(prefix[prefix.length - 1] + isVowel); + } + + return queries.map(([l, r]) => prefix[r + 1] - prefix[l]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: + * $O(n)$ extra space. + * $O(m)$ space for the output list. + +> Where $n$ is the number of words, and $m$ is the number of queries. \ No newline at end of file diff --git a/articles/find-common-characters.md b/articles/find-common-characters.md new file mode 100644 index 000000000..4a6cfe1e8 --- /dev/null +++ b/articles/find-common-characters.md @@ -0,0 +1,122 @@ +## 1. Frequency Count + +::tabs-start + +```python +class Solution: + def commonChars(self, words: List[str]) -> List[str]: + cnt = Counter(words[0]) + + for w in words: + cur_cnt = Counter(w) + for c in cnt: + cnt[c] = min(cnt[c], cur_cnt[c]) + + res = [] + for c in cnt: + for i in range(cnt[c]): + res.append(c) + + return res +``` + +```java +public class Solution { + public List commonChars(String[] words) { + int[] cnt = new int[26]; + Arrays.fill(cnt, Integer.MAX_VALUE); + + for (String word : words) { + int[] curCnt = new int[26]; + for (char c : word.toCharArray()) { + curCnt[c - 'a']++; + } + + for (int i = 0; i < 26; i++) { + cnt[i] = Math.min(cnt[i], curCnt[i]); + } + } + + List res = new ArrayList<>(); + for (int i = 0; i < 26; i++) { + for (int j = 0; j < cnt[i]; j++) { + res.add(String.valueOf((char) (i + 'a'))); + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector commonChars(vector& words) { + vector cnt(26, INT_MAX); + + for (string& word : words) { + vector curCnt(26, 0); + for (char c : word) { + curCnt[c - 'a']++; + } + + for (int i = 0; i < 26; i++) { + cnt[i] = min(cnt[i], curCnt[i]); + } + } + + vector res; + for (int i = 0; i < 26; i++) { + for (int j = 0; j < cnt[i]; j++) { + res.push_back(string(1, i + 'a')); + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words + * @return {string[]} + */ + commonChars(words) { + const cnt = new Array(26).fill(Infinity); + + for (let word of words) { + const curCnt = new Array(26).fill(0); + for (let c of word) { + curCnt[c.charCodeAt(0) - 97]++; + } + + for (let i = 0; i < 26; i++) { + cnt[i] = Math.min(cnt[i], curCnt[i]); + } + } + + const res = []; + for (let i = 0; i < 26; i++) { + for (let j = 0; j < cnt[i]; j++) { + res.push(String.fromCharCode(i + 97)); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: + * $O(1)$ extra space, since we have at most $26$ different characters. + * $O(n * m)$ space for the output list. + +> Where $n$ is the number of words and $m$ is the length of the longest word. \ No newline at end of file diff --git a/articles/relative-sort-array.md b/articles/relative-sort-array.md new file mode 100644 index 000000000..8681e3fba --- /dev/null +++ b/articles/relative-sort-array.md @@ -0,0 +1,551 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: + res = [] + + for num2 in arr2: + for i, num1 in enumerate(arr1): + if num1 == num2: + res.append(num1) + arr1[i] = -1 + + arr1.sort() + for i in range(len(res), len(arr1)): + res.append(arr1[i]) + + return res +``` + +```java +public class Solution { + public int[] relativeSortArray(int[] arr1, int[] arr2) { + List res = new ArrayList<>(); + + for (int num2 : arr2) { + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] == num2) { + res.add(arr1[i]); + arr1[i] = -1; + } + } + } + + Arrays.sort(arr1); + for (int i = res.size(); i < arr1.length; i++) { + res.add(arr1[i]); + } + + return res.stream().mapToInt(i -> i).toArray(); + } +} +``` + +```cpp +class Solution { +public: + vector relativeSortArray(vector& arr1, vector& arr2) { + vector res; + + for (int num2 : arr2) { + for (int i = 0; i < arr1.size(); i++) { + if (arr1[i] == num2) { + res.push_back(arr1[i]); + arr1[i] = -1; + } + } + } + + sort(arr1.begin(), arr1.end()); + for (int i = res.size(); i < arr1.size(); i++) { + res.push_back(arr1[i]); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @return {number[]} + */ + relativeSortArray(arr1, arr2) { + const res = []; + + for (let num2 of arr2) { + for (let i = 0; i < arr1.length; i++) { + if (arr1[i] === num2) { + res.push(arr1[i]); + arr1[i] = -1; + } + } + } + + arr1.sort((a, b) => a - b); + for (let i = res.length; i < arr1.length; i++) { + res.push(arr1[i]); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(m * n + n \log n)$ +* Space complexity: + * $O(1)$ or $O(n)$ depending on the sorting algorithm. + * $O(n)$ space for the output list. + +> Where $n$ is the size of the array $arr1$, and $m$ is the size of the array $arr2$. + +--- + +## 2. Hash Map + +::tabs-start + +```python +class Solution: + def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: + arr2_set = set(arr2) + arr1_count = defaultdict(int) + end = [] + + for num in arr1: + if num not in arr2_set: + end.append(num) + arr1_count[num] += 1 + end.sort() + + res = [] + for num in arr2: + for _ in range(arr1_count[num]): + res.append(num) + return res + end +``` + +```java +public class Solution { + public int[] relativeSortArray(int[] arr1, int[] arr2) { + Set arr2Set = new HashSet<>(); + for (int num : arr2) arr2Set.add(num); + + Map count = new HashMap<>(); + List end = new ArrayList<>(); + for (int num : arr1) { + if (!arr2Set.contains(num)) end.add(num); + count.put(num, count.getOrDefault(num, 0) + 1); + } + Collections.sort(end); + + List res = new ArrayList<>(); + for (int num : arr2) { + int freq = count.get(num); + for (int i = 0; i < freq; i++) res.add(num); + } + res.addAll(end); + + return res.stream().mapToInt(i -> i).toArray(); + } +} +``` + +```cpp +class Solution { +public: + vector relativeSortArray(vector& arr1, vector& arr2) { + unordered_set arr2Set(arr2.begin(), arr2.end()); + unordered_map count; + vector end; + + for (int num : arr1) { + if (!arr2Set.count(num)) end.push_back(num); + count[num]++; + } + + sort(end.begin(), end.end()); + vector res; + + for (int num : arr2) { + for (int i = 0; i < count[num]; i++) { + res.push_back(num); + } + } + + res.insert(res.end(), end.begin(), end.end()); + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @return {number[]} + */ + relativeSortArray(arr1, arr2) { + const arr2Set = new Set(arr2); + const count = {}; + const end = []; + + for (let num of arr1) { + if (!arr2Set.has(num)) end.push(num); + count[num] = (count[num] || 0) + 1; + } + + end.sort((a, b) => a - b); + const res = []; + + for (let num of arr2) { + for (let i = 0; i < count[num]; i++) { + res.push(num); + } + } + + return res.concat(end); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m + n \log n)$ +* Space complexity: $O(n)$ + +> Where $n$ is the size of the array $arr1$, and $m$ is the size of the array $arr2$. + +--- + +## 3. Hash Map (Optimal) + +::tabs-start + +```python +class Solution: + def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: + count = {} + for num in arr1: + count[num] = count.get(num, 0) + 1 + + res = [] + for num in arr2: + res += [num] * count.pop(num) + + for num in sorted(count): + res += [num] * count[num] + + return res +``` + +```java +public class Solution { + public int[] relativeSortArray(int[] arr1, int[] arr2) { + Map count = new HashMap<>(); + for (int num : arr1) { + count.put(num, count.getOrDefault(num, 0) + 1); + } + + List res = new ArrayList<>(); + for (int num : arr2) { + int freq = count.remove(num); + for (int i = 0; i < freq; i++) { + res.add(num); + } + } + + List remaining = new ArrayList<>(count.keySet()); + Collections.sort(remaining); + for (int num : remaining) { + int freq = count.get(num); + for (int i = 0; i < freq; i++) { + res.add(num); + } + } + + return res.stream().mapToInt(i -> i).toArray(); + } +} +``` + +```cpp +class Solution { +public: + vector relativeSortArray(vector& arr1, vector& arr2) { + unordered_map count; + for (int num : arr1) { + count[num]++; + } + + vector res; + for (int num : arr2) { + for (int i = 0; i < count[num]; i++) { + res.push_back(num); + } + count.erase(num); + } + + vector remaining; + for (auto& [num, freq] : count) { + for (int i = 0; i < freq; i++) { + remaining.push_back(num); + } + } + + sort(remaining.begin(), remaining.end()); + res.insert(res.end(), remaining.begin(), remaining.end()); + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @return {number[]} + */ + relativeSortArray(arr1, arr2) { + const count = {}; + for (let num of arr1) { + count[num] = (count[num] || 0) + 1; + } + + const res = []; + for (let num of arr2) { + for (let i = 0; i < count[num]; i++) { + res.push(num); + } + delete count[num]; + } + + const remaining = Object.keys(count).map(Number).sort((a, b) => a - b); + for (let num of remaining) { + for (let i = 0; i < count[num]; i++) { + res.push(num); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m + n \log n)$ +* Space complexity: $O(n)$ + +> Where $n$ is the size of the array $arr1$, and $m$ is the size of the array $arr2$. + +--- + +## 4. Counting Sort + +::tabs-start + +```python +class Solution: + def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: + max_val = max(arr1) + count = [0] * (max_val + 1) + + for num in arr1: + count[num] += 1 + + res = [] + for num in arr2: + res += [num] * count[num] + count[num] = 0 + + for num in range(len(count)): + res += [num] * count[num] + + return res +``` + +```java +public class Solution { + public int[] relativeSortArray(int[] arr1, int[] arr2) { + int max = 0; + for (int num : arr1) max = Math.max(max, num); + + int[] count = new int[max + 1]; + for (int num : arr1) count[num]++; + + List res = new ArrayList<>(); + for (int num : arr2) { + while (count[num]-- > 0) res.add(num); + } + + for (int num = 0; num < count.length; num++) { + while (count[num]-- > 0) res.add(num); + } + + return res.stream().mapToInt(i -> i).toArray(); + } +} +``` + +```cpp +class Solution { +public: + vector relativeSortArray(vector& arr1, vector& arr2) { + int max_val = *max_element(arr1.begin(), arr1.end()); + vector count(max_val + 1, 0); + + for (int num : arr1) count[num]++; + + vector res; + for (int num : arr2) { + while (count[num]-- > 0) res.push_back(num); + } + + for (int num = 0; num <= max_val; num++) { + while (count[num]-- > 0) res.push_back(num); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @return {number[]} + */ + relativeSortArray(arr1, arr2) { + let max = Math.max(...arr1); + let count = new Array(max + 1).fill(0); + + for (let num of arr1) count[num]++; + + let res = []; + for (let num of arr2) { + while (count[num]-- > 0) res.push(num); + } + + for (let num = 0; num < count.length; num++) { + while (count[num]-- > 0) res.push(num); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m + M)$ +* Space complexity: + * $O(M)$ extra space. + * $O(n)$ space for the output list. + +> Where $n$ is the size of the array $arr1$, $m$ is the size of the array $arr2$, and $M$ is the maximum value in the array $arr1$. + +--- + +## 5. Custom Sort + +::tabs-start + +```python +class Solution: + def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: + index = {num: i for i, num in enumerate(arr2)} + return sorted(arr1, key=lambda x: (index.get(x, 1000 + x))) +``` + +```java +public class Solution { + public int[] relativeSortArray(int[] arr1, int[] arr2) { + Map index = new HashMap<>(); + for (int i = 0; i < arr2.length; i++) { + index.put(arr2[i], i); + } + + Integer[] boxed = Arrays.stream(arr1).boxed().toArray(Integer[]::new); + Arrays.sort(boxed, (a, b) -> { + int ia = index.getOrDefault(a, 1000 + a); + int ib = index.getOrDefault(b, 1000 + b); + return Integer.compare(ia, ib); + }); + + return Arrays.stream(boxed).mapToInt(i -> i).toArray(); + } +} +``` + +```cpp +class Solution { +public: + vector relativeSortArray(vector& arr1, vector& arr2) { + unordered_map index; + for (int i = 0; i < arr2.size(); i++) { + index[arr2[i]] = i; + } + + sort(arr1.begin(), arr1.end(), [&](int a, int b) { + int ia = index.count(a) ? index[a] : 1000 + a; + int ib = index.count(b) ? index[b] : 1000 + b; + return ia < ib; + }); + + return arr1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @return {number[]} + */ + relativeSortArray(arr1, arr2) { + const index = new Map(); + arr2.forEach((num, i) => index.set(num, i)); + + return arr1.sort((a, b) => { + const ia = index.has(a) ? index.get(a) : 1000 + a; + const ib = index.has(b) ? index.get(b) : 1000 + b; + return ia - ib; + }); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m + n \log n)$ +* Space complexity: + * $O(m)$ extra space. + * $O(n)$ space for the output list. + +> Where $n$ is the size of the array $arr1$, and $m$ is the size of the array $arr2$. \ No newline at end of file From 0367f57f9f7816299dc7136fe6062656fdd9546f Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Sun, 6 Apr 2025 08:11:47 +0530 Subject: [PATCH 5/9] Batch-6/Neetcode-ALL/Added-articles --- ...perations-to-move-all-balls-to-each-box.md | 325 ++++++++++++++++++ .../sort-array-by-increasing-frequency.md | 79 +++++ articles/sort-the-people.md | 256 ++++++++++++++ 3 files changed, 660 insertions(+) create mode 100644 articles/minimum-number-of-operations-to-move-all-balls-to-each-box.md create mode 100644 articles/sort-array-by-increasing-frequency.md create mode 100644 articles/sort-the-people.md diff --git a/articles/minimum-number-of-operations-to-move-all-balls-to-each-box.md b/articles/minimum-number-of-operations-to-move-all-balls-to-each-box.md new file mode 100644 index 000000000..c00bbfdb0 --- /dev/null +++ b/articles/minimum-number-of-operations-to-move-all-balls-to-each-box.md @@ -0,0 +1,325 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def minOperations(self, boxes: str) -> List[int]: + n = len(boxes) + res = [0] * n + + for pos in range(n): + for i in range(n): + if boxes[i] == '1': + res[pos] += abs(pos - i) + + return res +``` + +```java +public class Solution { + public int[] minOperations(String boxes) { + int n = boxes.length(); + int[] res = new int[n]; + + for (int pos = 0; pos < n; pos++) { + for (int i = 0; i < n; i++) { + if (boxes.charAt(i) == '1') { + res[pos] += Math.abs(pos - i); + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector minOperations(string boxes) { + int n = boxes.size(); + vector res(n, 0); + + for (int pos = 0; pos < n; pos++) { + for (int i = 0; i < n; i++) { + if (boxes[i] == '1') { + res[pos] += abs(pos - i); + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} boxes + * @return {number[]} + */ + minOperations(boxes) { + const n = boxes.length; + const res = new Array(n).fill(0); + + for (let pos = 0; pos < n; pos++) { + for (let i = 0; i < n; i++) { + if (boxes[i] === '1') { + res[pos] += Math.abs(pos - i); + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output list. + +--- + +## 2. Prefix Sum + +::tabs-start + +```python +class Solution: + def minOperations(self, boxes: str) -> List[int]: + n = len(boxes) + res = [0] * n + + prefix_count = [0] * (n + 1) + index_sum = [0] * (n + 1) + for i in range(n): + prefix_count[i + 1] = prefix_count[i] + (boxes[i] == '1') + index_sum[i + 1] = index_sum[i] + (i if boxes[i] == '1' else 0) + + for i in range(n): + left = prefix_count[i] + left_sum = index_sum[i] + + right = prefix_count[n] - prefix_count[i + 1] + right_sum = index_sum[n] - index_sum[i + 1] + + res[i] = (i * left - left_sum) + (right_sum - i * right) + + return res +``` + +```java +public class Solution { + public int[] minOperations(String boxes) { + int n = boxes.length(); + int[] res = new int[n]; + int[] prefixCount = new int[n + 1]; + int[] indexSum = new int[n + 1]; + + for (int i = 0; i < n; i++) { + prefixCount[i + 1] = prefixCount[i] + (boxes.charAt(i) == '1' ? 1 : 0); + indexSum[i + 1] = indexSum[i] + (boxes.charAt(i) == '1' ? i : 0); + } + + for (int i = 0; i < n; i++) { + int left = prefixCount[i]; + int leftSum = indexSum[i]; + + int right = prefixCount[n] - prefixCount[i + 1]; + int rightSum = indexSum[n] - indexSum[i + 1]; + + res[i] = i * left - leftSum + (rightSum - i * right); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector minOperations(string boxes) { + int n = boxes.size(); + vector res(n), prefixCount(n + 1, 0), indexSum(n + 1, 0); + + for (int i = 0; i < n; i++) { + prefixCount[i + 1] = prefixCount[i] + (boxes[i] == '1' ? 1 : 0); + indexSum[i + 1] = indexSum[i] + (boxes[i] == '1' ? i : 0); + } + + for (int i = 0; i < n; i++) { + int left = prefixCount[i]; + int leftSum = indexSum[i]; + int right = prefixCount[n] - prefixCount[i + 1]; + int rightSum = indexSum[n] - indexSum[i + 1]; + res[i] = i * left - leftSum + (rightSum - i * right); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} boxes + * @return {number[]} + */ + minOperations(boxes) { + const n = boxes.length; + const res = new Array(n).fill(0); + const prefixCount = new Array(n + 1).fill(0); + const indexSum = new Array(n + 1).fill(0); + + for (let i = 0; i < n; i++) { + prefixCount[i + 1] = prefixCount[i] + (boxes[i] === '1' ? 1 : 0); + indexSum[i + 1] = indexSum[i] + (boxes[i] === '1' ? i : 0); + } + + for (let i = 0; i < n; i++) { + const left = prefixCount[i]; + const leftSum = indexSum[i]; + const right = prefixCount[n] - prefixCount[i + 1]; + const rightSum = indexSum[n] - indexSum[i + 1]; + + res[i] = i * left - leftSum + (rightSum - i * right); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Prefix Sum (Optimal) + +::tabs-start + +```python +class Solution: + def minOperations(self, boxes: str) -> List[int]: + n = len(boxes) + res = [0] * n + + balls = moves = 0 + for i in range(n): + res[i] = balls + moves + moves += balls + balls += int(boxes[i]) + + balls = moves = 0 + for i in range(n - 1, -1, -1): + res[i] += balls + moves + moves += balls + balls += int(boxes[i]) + + return res +``` + +```java +public class Solution { + public int[] minOperations(String boxes) { + int n = boxes.length(); + int[] res = new int[n]; + + int balls = 0, moves = 0; + for (int i = 0; i < n; i++) { + res[i] = balls + moves; + moves += balls; + balls += boxes.charAt(i) - '0'; + } + + balls = moves = 0; + for (int i = n - 1; i >= 0; i--) { + res[i] += balls + moves; + moves += balls; + balls += boxes.charAt(i) - '0'; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector minOperations(string boxes) { + int n = boxes.size(); + vector res(n, 0); + + int balls = 0, moves = 0; + for (int i = 0; i < n; i++) { + res[i] = balls + moves; + moves += balls; + balls += boxes[i] - '0'; + } + + balls = moves = 0; + for (int i = n - 1; i >= 0; i--) { + res[i] += balls + moves; + moves += balls; + balls += boxes[i] - '0'; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} boxes + * @return {number[]} + */ + minOperations(boxes) { + const n = boxes.length; + const res = new Array(n).fill(0); + + let balls = 0, moves = 0; + for (let i = 0; i < n; i++) { + res[i] = balls + moves; + moves += balls; + balls += Number(boxes[i]); + } + + balls = moves = 0; + for (let i = n - 1; i >= 0; i--) { + res[i] += balls + moves; + moves += balls; + balls += Number(boxes[i]); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output list. \ No newline at end of file diff --git a/articles/sort-array-by-increasing-frequency.md b/articles/sort-array-by-increasing-frequency.md new file mode 100644 index 000000000..04a4e1c80 --- /dev/null +++ b/articles/sort-array-by-increasing-frequency.md @@ -0,0 +1,79 @@ +## 1. Custom Sort + +::tabs-start + +```python +class Solution: + def frequencySort(self, nums: List[int]) -> List[int]: + count = Counter(nums) + nums.sort(key=lambda n: (count[n], -n)) + return nums +``` + +```java +public class Solution { + public int[] frequencySort(int[] nums) { + Map count = new HashMap<>(); + for (int num : nums) { + count.put(num, count.getOrDefault(num, 0) + 1); + } + + Integer[] arr = Arrays.stream(nums).boxed().toArray(Integer[]::new); + Arrays.sort(arr, (a, b) -> { + int freqA = count.get(a), freqB = count.get(b); + if (freqA != freqB) return Integer.compare(freqA, freqB); + return Integer.compare(b, a); + }); + + return Arrays.stream(arr).mapToInt(i -> i).toArray(); + } +} +``` + +```cpp +class Solution { +public: + vector frequencySort(vector& nums) { + unordered_map count; + for (int num : nums) { + count[num]++; + } + + sort(nums.begin(), nums.end(), [&](int a, int b) { + if (count[a] != count[b]) return count[a] < count[b]; + return a > b; + }); + + return nums; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number[]} + */ + frequencySort(nums) { + const count = {}; + for (let num of nums) { + count[num] = (count[num] || 0) + 1; + } + + nums.sort((a, b) => { + if (count[a] !== count[b]) return count[a] - count[b]; + return b - a; + }); + + return nums; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/sort-the-people.md b/articles/sort-the-people.md new file mode 100644 index 000000000..c5d8ca911 --- /dev/null +++ b/articles/sort-the-people.md @@ -0,0 +1,256 @@ +## 1. Hash Map + +::tabs-start + +```python +class Solution: + def sortPeople(self, names: List[str], heights: List[int]) -> List[str]: + height_to_name = {} + for h, n in zip(heights, names): + height_to_name[h] = n + + res = [] + for h in reversed(sorted(heights)): + res.append(height_to_name[h]) + + return res +``` + +```java +public class Solution { + public String[] sortPeople(String[] names, int[] heights) { + Map map = new HashMap<>(); + for (int i = 0; i < heights.length; i++) { + map.put(heights[i], names[i]); + } + + Arrays.sort(heights); + String[] res = new String[heights.length]; + for (int i = 0; i < heights.length; i++) { + res[i] = map.get(heights[heights.length - 1 - i]); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector sortPeople(vector& names, vector& heights) { + unordered_map map; + for (int i = 0; i < heights.size(); i++) { + map[heights[i]] = names[i]; + } + + sort(heights.begin(), heights.end()); + vector res; + for (int i = heights.size() - 1; i >= 0; i--) { + res.push_back(map[heights[i]]); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} names + * @param {number[]} heights + * @return {string[]} + */ + sortPeople(names, heights) { + const map = {}; + for (let i = 0; i < heights.length; i++) { + map[heights[i]] = names[i]; + } + + heights.sort((a, b) => a - b); + const res = []; + for (let i = heights.length - 1; i >= 0; i--) { + res.push(map[heights[i]]); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Sorting the Pairs + +::tabs-start + +```python +class Solution: + def sortPeople(self, names: List[str], heights: List[int]) -> List[str]: + arr = list(zip(heights, names)) + arr.sort(reverse=True) + return [name for _, name in arr] +``` + +```java +public class Solution { + public String[] sortPeople(String[] names, int[] heights) { + int n = names.length; + Pair[] arr = new Pair[n]; + + for (int i = 0; i < n; i++) { + arr[i] = new Pair(heights[i], names[i]); + } + + Arrays.sort(arr, (a, b) -> Integer.compare(b.height, a.height)); + + String[] res = new String[n]; + for (int i = 0; i < n; i++) { + res[i] = arr[i].name; + } + + return res; + } + + static class Pair { + int height; + String name; + + Pair(int height, String name) { + this.height = height; + this.name = name; + } + } +} +``` + +```cpp +class Solution { +public: + vector sortPeople(vector& names, vector& heights) { + vector> arr; + for (int i = 0; i < names.size(); i++) { + arr.emplace_back(heights[i], names[i]); + } + + sort(arr.begin(), arr.end(), [](auto& a, auto& b) { + return a.first > b.first; + }); + + vector res; + for (auto& [_, name] : arr) { + res.push_back(name); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} names + * @param {number[]} heights + * @return {string[]} + */ + sortPeople(names, heights) { + const arr = names.map((name, i) => [heights[i], name]); + arr.sort((a, b) => b[0] - a[0]); + return arr.map(pair => pair[1]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Sorting the Indices + +::tabs-start + +```python +class Solution: + def sortPeople(self, names: List[str], heights: List[int]) -> List[str]: + indices = list(range(len(names))) + indices.sort(key=lambda i: -heights[i]) + return [names[i] for i in indices] +``` + +```java +public class Solution { + public String[] sortPeople(String[] names, int[] heights) { + Integer[] indices = new Integer[names.length]; + for (int i = 0; i < names.length; i++) { + indices[i] = i; + } + + Arrays.sort(indices, (i, j) -> Integer.compare(heights[j], heights[i])); + + String[] res = new String[names.length]; + for (int i = 0; i < names.length; i++) { + res[i] = names[indices[i]]; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector sortPeople(vector& names, vector& heights) { + int n = names.size(); + vector indices(n); + iota(indices.begin(), indices.end(), 0); + + sort(indices.begin(), indices.end(), [&](int a, int b) { + return heights[a] > heights[b]; + }); + + vector res; + for (int i : indices) { + res.push_back(names[i]); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} names + * @param {number[]} heights + * @return {string[]} + */ + sortPeople(names, heights) { + const indices = names.map((_, i) => i); + indices.sort((a, b) => heights[b] - heights[a]); + return indices.map(i => names[i]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ \ No newline at end of file From b4c8712804bde5fff02db82f2b1960874ded53d5 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Sun, 6 Apr 2025 19:16:41 +0530 Subject: [PATCH 6/9] Batch-6/Neetcode-ALL/Added-articles --- articles/make-sum-divisible-by-p.md | 235 ++++++++ articles/minimum-index-of-a-valid-split.md | 385 +++++++++++++ articles/number-of-sub-arrays-with-odd-sum.md | 521 ++++++++++++++++++ articles/number-of-ways-to-split-array.md | 320 +++++++++++ articles/subarray-sums-divisible-by-k.md | 280 ++++++++++ 5 files changed, 1741 insertions(+) create mode 100644 articles/make-sum-divisible-by-p.md create mode 100644 articles/minimum-index-of-a-valid-split.md create mode 100644 articles/number-of-sub-arrays-with-odd-sum.md create mode 100644 articles/number-of-ways-to-split-array.md create mode 100644 articles/subarray-sums-divisible-by-k.md diff --git a/articles/make-sum-divisible-by-p.md b/articles/make-sum-divisible-by-p.md new file mode 100644 index 000000000..493f5732c --- /dev/null +++ b/articles/make-sum-divisible-by-p.md @@ -0,0 +1,235 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def minSubarray(self, nums: List[int], p: int) -> int: + n = len(nums) + totSum = sum(nums) + + if totSum % p == 0: + return 0 + + for l in range(1, n): + curSum = 0 + for i in range(n): + curSum += nums[i] + if i >= l: + curSum -= nums[i - l] + + remainSum = totSum - curSum + if remainSum % p == 0: + return l + + return -1 +``` + +```java +public class Solution { + public int minSubarray(int[] nums, int p) { + int n = nums.length; + long totSum = 0; + for (int num : nums) totSum += num; + + if (totSum % p == 0) return 0; + + for (int l = 1; l < n; l++) { + long curSum = 0; + for (int i = 0; i < n; i++) { + curSum += nums[i]; + if (i >= l) curSum -= nums[i - l]; + + long remainSum = totSum - curSum; + if (remainSum % p == 0) return l; + } + } + + return -1; + } +} +``` + +```cpp +class Solution { +public: + int minSubarray(vector& nums, int p) { + int n = nums.size(); + long long totSum = 0; + for (int num : nums) totSum += num; + + if (totSum % p == 0) return 0; + + for (int l = 1; l < n; l++) { + long long curSum = 0; + for (int i = 0; i < n; i++) { + curSum += nums[i]; + if (i >= l) curSum -= nums[i - l]; + + long long remainSum = totSum - curSum; + if (remainSum % p == 0) return l; + } + } + + return -1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @param {number} p + * @return {number} + */ + minSubarray(nums, p) { + const n = nums.length; + let totSum = nums.reduce((a, b) => a + b, 0); + + if (totSum % p === 0) return 0; + + for (let l = 1; l < n; l++) { + let curSum = 0; + for (let i = 0; i < n; i++) { + curSum += nums[i]; + if (i >= l) curSum -= nums[i - l]; + + const remainSum = totSum - curSum; + if (remainSum % p === 0) return l; + } + } + + return -1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Prefix Sum + +::tabs-start + +```python +class Solution: + def minSubarray(self, nums: List[int], p: int) -> int: + total = sum(nums) + remain = total % p + if remain == 0: + return 0 + + res = len(nums) + cur_sum = 0 + remain_to_idx = {0: -1} + + for i, n in enumerate(nums): + cur_sum = (cur_sum + n) % p + prefix = (cur_sum - remain + p) % p + if prefix in remain_to_idx: + length = i - remain_to_idx[prefix] + res = min(res, length) + remain_to_idx[cur_sum] = i + + return -1 if res == len(nums) else res +``` + +```java +public class Solution { + public int minSubarray(int[] nums, int p) { + long total = 0; + for (int num : nums) total += num; + int remain = (int)(total % p); + if (remain == 0) return 0; + + int res = nums.length; + long curSum = 0; + Map map = new HashMap<>(); + map.put(0, -1); + + for (int i = 0; i < nums.length; i++) { + curSum = (curSum + nums[i]) % p; + int prefix = (int)((curSum - remain + p) % p); + if (map.containsKey(prefix)) { + res = Math.min(res, i - map.get(prefix)); + } + map.put((int)curSum, i); + } + + return res == nums.length ? -1 : res; + } +} +``` + +```cpp +class Solution { +public: + int minSubarray(vector& nums, int p) { + long total = 0; + for (int num : nums) total += num; + int remain = total % p; + if (remain == 0) return 0; + + int res = nums.size(); + long curSum = 0; + unordered_map map; + map[0] = -1; + + for (int i = 0; i < nums.size(); i++) { + curSum = (curSum + nums[i]) % p; + int prefix = (curSum - remain + p) % p; + if (map.count(prefix)) { + res = min(res, i - map[prefix]); + } + map[curSum] = i; + } + + return res == nums.size() ? -1 : res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @param {number} p + * @return {number} + */ + minSubarray(nums, p) { + let total = nums.reduce((a, b) => a + b, 0); + let remain = total % p; + if (remain === 0) return 0; + + let res = nums.length; + let curSum = 0; + const map = new Map(); + map.set(0, -1); + + for (let i = 0; i < nums.length; i++) { + curSum = (curSum + nums[i]) % p; + let prefix = (curSum - remain + p) % p; + if (map.has(prefix)) { + res = Math.min(res, i - map.get(prefix)); + } + map.set(curSum, i); + } + + return res === nums.length ? -1 : 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-index-of-a-valid-split.md b/articles/minimum-index-of-a-valid-split.md new file mode 100644 index 000000000..17548cd54 --- /dev/null +++ b/articles/minimum-index-of-a-valid-split.md @@ -0,0 +1,385 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def minimumIndex(self, nums: List[int]) -> int: + n = len(nums) + + for i in range(n - 1): + left_cnt = defaultdict(int) + for l in range(i + 1): + left_cnt[nums[l]] += 1 + + right_cnt = defaultdict(int) + for r in range(i + 1, n): + right_cnt[nums[r]] += 1 + + for num in left_cnt: + if left_cnt[num] > (i + 1) // 2 and right_cnt[num] > (n - i - 1) // 2: + return i + + return -1 +``` + +```java +public class Solution { + public int minimumIndex(List nums) { + int n = nums.size(); + + for (int i = 0; i < n - 1; i++) { + Map leftCnt = new HashMap<>(); + for (int l = 0; l <= i; l++) { + int val = nums.get(l); + leftCnt.put(val, leftCnt.getOrDefault(val, 0) + 1); + } + + Map rightCnt = new HashMap<>(); + for (int r = i + 1; r < n; r++) { + int val = nums.get(r); + rightCnt.put(val, rightCnt.getOrDefault(val, 0) + 1); + } + + for (int num : leftCnt.keySet()) { + if (leftCnt.get(num) > (i + 1) / 2 && rightCnt.getOrDefault(num, 0) > (n - i - 1) / 2) { + return i; + } + } + } + + return -1; + } +} +``` + +```cpp +class Solution { +public: + int minimumIndex(vector& nums) { + int n = nums.size(); + + for (int i = 0; i < n - 1; i++) { + unordered_map leftCnt, rightCnt; + for (int l = 0; l <= i; l++) { + leftCnt[nums[l]]++; + } + for (int r = i + 1; r < n; r++) { + rightCnt[nums[r]]++; + } + + for (auto& [num, cnt] : leftCnt) { + if (cnt > (i + 1) / 2 && rightCnt[num] > (n - i - 1) / 2) { + return i; + } + } + } + + return -1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + minimumIndex(nums) { + const n = nums.length; + + for (let i = 0; i < n - 1; i++) { + const leftCnt = {}; + for (let l = 0; l <= i; l++) { + leftCnt[nums[l]] = (leftCnt[nums[l]] || 0) + 1; + } + + const rightCnt = {}; + for (let r = i + 1; r < n; r++) { + rightCnt[nums[r]] = (rightCnt[nums[r]] || 0) + 1; + } + + for (const num in leftCnt) { + if (leftCnt[num] > Math.floor((i + 1) / 2) && + (rightCnt[num] || 0) > Math.floor((n - i - 1) / 2)) { + return i; + } + } + } + + return -1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n)$ + +--- + +## 2. Hash Map + +::tabs-start + +```python +class Solution: + def minimumIndex(self, nums: List[int]) -> int: + left = defaultdict(int) + right = Counter(nums) + + for i in range(len(nums)): + left[nums[i]] += 1 + right[nums[i]] -= 1 + + left_len = i + 1 + right_len = len(nums) - i - 1 + + if 2 * left[nums[i]] > left_len and 2 * right[nums[i]] > right_len: + return i + + return -1 +``` + +```java +public class Solution { + public int minimumIndex(List nums) { + Map left = new HashMap<>(); + Map right = new HashMap<>(); + int n = nums.size(); + + for (int num : nums) { + right.put(num, right.getOrDefault(num, 0) + 1); + } + + for (int i = 0; i < n; i++) { + int num = nums.get(i); + left.put(num, left.getOrDefault(num, 0) + 1); + right.put(num, right.get(num) - 1); + + int leftLen = i + 1; + int rightLen = n - i - 1; + + if (2 * left.get(num) > leftLen && 2 * right.get(num) > rightLen) { + return i; + } + } + + return -1; + } +} +``` + +```cpp +class Solution { +public: + int minimumIndex(vector& nums) { + unordered_map left, right; + int n = nums.size(); + + for (int num : nums) { + right[num]++; + } + + for (int i = 0; i < n; i++) { + int num = nums[i]; + left[num]++; + right[num]--; + + int leftLen = i + 1; + int rightLen = n - i - 1; + + if (2 * left[num] > leftLen && 2 * right[num] > rightLen) { + return i; + } + } + + return -1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + minimumIndex(nums) { + const left = {}; + const right = {}; + const n = nums.length; + + for (const num of nums) { + right[num] = (right[num] || 0) + 1; + } + + for (let i = 0; i < n; i++) { + const num = nums[i]; + left[num] = (left[num] || 0) + 1; + right[num] -= 1; + + const leftLen = i + 1; + const rightLen = n - i - 1; + + if (2 * left[num] > leftLen && 2 * right[num] > rightLen) { + return i; + } + } + + return -1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Boyer-Moore Voting Algorithm + +::tabs-start + +```python +class Solution: + def minimumIndex(self, nums: List[int]) -> int: + majority = count = 0 + for num in nums: + if count == 0: + majority = num + count += (1 if majority == num else -1) + + left_cnt, right_cnt = 0, nums.count(majority) + + for i in range(len(nums)): + if nums[i] == majority: + left_cnt += 1 + right_cnt -= 1 + + left_len = i + 1 + right_len = len(nums) - i - 1 + + if 2 * left_cnt > left_len and 2 * right_cnt > right_len: + return i + + return -1 +``` + +```java +public class Solution { + public int minimumIndex(List nums) { + int majority = 0, count = 0; + for (int num : nums) { + if (count == 0) majority = num; + count += (majority == num) ? 1 : -1; + } + + int leftCnt = 0, rightCnt = 0; + for (int num : nums) { + if (num == majority) rightCnt++; + } + + int n = nums.size(); + for (int i = 0; i < n; i++) { + if (nums.get(i) == majority) { + leftCnt++; + rightCnt--; + } + + int leftLen = i + 1; + int rightLen = n - i - 1; + + if (2 * leftCnt > leftLen && 2 * rightCnt > rightLen) { + return i; + } + } + + return -1; + } +} +``` + +```cpp +class Solution { +public: + int minimumIndex(vector& nums) { + int majority = 0, count = 0; + for (int num : nums) { + if (count == 0) majority = num; + count += (num == majority ? 1 : -1); + } + + int leftCnt = 0, rightCnt = count_if(nums.begin(), nums.end(), + [&](int x) { return x == majority; }); + + int n = nums.size(); + for (int i = 0; i < n; i++) { + if (nums[i] == majority) { + leftCnt++; + rightCnt--; + } + + int leftLen = i + 1; + int rightLen = n - i - 1; + + if (2 * leftCnt > leftLen && 2 * rightCnt > rightLen) { + return i; + } + } + + return -1; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + minimumIndex(nums) { + let majority = 0, count = 0; + for (let num of nums) { + if (count === 0) majority = num; + count += (num === majority ? 1 : -1); + } + + let leftCnt = 0; + let rightCnt = nums.filter(x => x === majority).length; + const n = nums.length; + + for (let i = 0; i < n; i++) { + if (nums[i] === majority) { + leftCnt++; + rightCnt--; + } + + let leftLen = i + 1; + let rightLen = n - i - 1; + + if (2 * leftCnt > leftLen && 2 * rightCnt > rightLen) { + return i; + } + } + + return -1; + } +} +``` + +::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-sub-arrays-with-odd-sum.md b/articles/number-of-sub-arrays-with-odd-sum.md new file mode 100644 index 000000000..e13063014 --- /dev/null +++ b/articles/number-of-sub-arrays-with-odd-sum.md @@ -0,0 +1,521 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def numOfSubarrays(self, arr: List[int]) -> int: + n, res = len(arr), 0 + mod = int(1e9 + 7) + + for i in range(n): + curSum = 0 + for j in range(i, n): + curSum += arr[j] + if curSum % 2: + res = (res + 1) % mod + + return res +``` + +```java +public class Solution { + public int numOfSubarrays(int[] arr) { + int n = arr.length, res = 0; + int mod = (int)1e9 + 7; + + for (int i = 0; i < n; i++) { + int curSum = 0; + for (int j = i; j < n; j++) { + curSum += arr[j]; + if (curSum % 2 != 0) { + res = (res + 1) % mod; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int numOfSubarrays(vector& arr) { + int n = arr.size(), res = 0; + int mod = 1e9 + 7; + + for (int i = 0; i < n; i++) { + int curSum = 0; + for (int j = i; j < n; j++) { + curSum += arr[j]; + if (curSum % 2 != 0) { + res = (res + 1) % mod; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr + * @return {number} + */ + numOfSubarrays(arr) { + const n = arr.length; + let res = 0; + const mod = 1e9 + 7; + + for (let i = 0; i < n; i++) { + let curSum = 0; + for (let j = i; j < n; j++) { + curSum += arr[j]; + if (curSum % 2 !== 0) { + res = (res + 1) % mod; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Dynamic Programming (Top-Down) + +::tabs-start + +```python +class Solution: + def numOfSubarrays(self, arr: List[int]) -> int: + mod = 10**9 + 7 + n = len(arr) + memo = {} + + def dp(i: int, parity: int) -> int: + if i == n: + return 0 + + if (i, parity) in memo: + return memo[(i, parity)] + + new_parity = (parity + arr[i]) % 2 + res = new_parity + dp(i + 1, new_parity) + memo[(i, parity)] = res % mod + return memo[(i, parity)] + + ans = 0 + for i in range(n): + ans = (ans + dp(i, 0)) % mod + + return ans +``` + +```java +public class Solution { + int[][] memo; + int[] arr; + int mod = (int)1e9 + 7; + + public int numOfSubarrays(int[] arr) { + int n = arr.length; + this.arr = arr; + memo = new int[n][2]; + for (int i = 0; i < n; i++) { + memo[i][0] = -1; + memo[i][1] = -1; + } + + int res = 0; + for (int i = 0; i < n; i++) { + res = (res + dp(i, 0)) % mod; + } + return res; + } + + private int dp(int i, int parity) { + if (i == arr.length) return 0; + if (memo[i][parity] != -1) return memo[i][parity]; + + int newParity = (parity + arr[i]) % 2; + int res = newParity + dp(i + 1, newParity); + return memo[i][parity] = res % mod; + } +} +``` + +```cpp +class Solution { +public: + int mod = 1e9 + 7; + vector> memo; + vector arr; + + int numOfSubarrays(vector& arr) { + this->arr = arr; + int n = arr.size(); + memo.assign(n, vector(2, -1)); + + int res = 0; + for (int i = 0; i < n; i++) { + res = (res + dp(i, 0)) % mod; + } + return res; + } + + int dp(int i, int parity) { + if (i == arr.size()) return 0; + if (memo[i][parity] != -1) return memo[i][parity]; + + int newParity = (parity + arr[i]) % 2; + int res = newParity + dp(i + 1, newParity); + return memo[i][parity] = res % mod; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr + * @return {number} + */ + numOfSubarrays(arr) { + const mod = 1e9 + 7; + const n = arr.length; + const memo = Array.from({ length: n }, () => Array(2).fill(-1)); + + const dp = (i, parity) => { + if (i === n) return 0; + if (memo[i][parity] !== -1) return memo[i][parity]; + + const newParity = (parity + arr[i]) % 2; + const res = newParity + dp(i + 1, newParity); + return memo[i][parity] = res % mod; + }; + + let res = 0; + for (let i = 0; i < n; i++) { + res = (res + dp(i, 0)) % mod; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Dynamic Programming (Bottom-Up) + +::tabs-start + +```python +class Solution: + def numOfSubarrays(self, arr: List[int]) -> int: + n = len(arr) + mod = 10**9 + 7 + dp = [[0] * 2 for _ in range(n + 1)] + + for i in range(n - 1, -1, -1): + for parity in range(2): + new_parity = (parity + arr[i]) % 2 + dp[i][parity] = (new_parity + dp[i + 1][new_parity]) % mod + + res = 0 + for i in range(n): + res = (res + dp[i][0]) % mod + return res +``` + +```java +public class Solution { + public int numOfSubarrays(int[] arr) { + int n = arr.length; + int mod = (int)1e9 + 7; + int[][] dp = new int[n + 1][2]; + + for (int i = n - 1; i >= 0; i--) { + for (int parity = 0; parity <= 1; parity++) { + int newParity = (parity + arr[i]) % 2; + dp[i][parity] = (newParity + dp[i + 1][newParity]) % mod; + } + } + + int res = 0; + for (int i = 0; i < n; i++) { + res = (res + dp[i][0]) % mod; + } + return res; + } +} +``` + +```cpp +class Solution { +public: + int numOfSubarrays(vector& arr) { + int n = arr.size(), mod = 1e9 + 7; + vector> dp(n + 1, vector(2, 0)); + + for (int i = n - 1; i >= 0; i--) { + for (int parity = 0; parity <= 1; parity++) { + int newParity = (parity + arr[i]) % 2; + dp[i][parity] = (newParity + dp[i + 1][newParity]) % mod; + } + } + + int res = 0; + for (int i = 0; i < n; i++) { + res = (res + dp[i][0]) % mod; + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr + * @return {number} + */ + numOfSubarrays(arr) { + const n = arr.length; + const mod = 1e9 + 7; + const dp = Array.from({ length: n + 1 }, () => [0, 0]); + + for (let i = n - 1; i >= 0; i--) { + for (let parity = 0; parity <= 1; parity++) { + const newParity = (parity + arr[i]) % 2; + dp[i][parity] = (newParity + dp[i + 1][newParity]) % mod; + } + } + + let res = 0; + for (let i = 0; i < n; i++) { + res = (res + dp[i][0]) % mod; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. Prefix Sum - I + +::tabs-start + +```python +class Solution: + def numOfSubarrays(self, arr: List[int]) -> int: + cur_sum = odd_cnt = even_cnt = res = 0 + MOD = 10**9 + 7 + + for n in arr: + cur_sum += n + if cur_sum % 2: + res = (res + 1 + even_cnt) % MOD + odd_cnt += 1 + else: + res = (res + odd_cnt) % MOD + even_cnt += 1 + + return res +``` + +```java +public class Solution { + public int numOfSubarrays(int[] arr) { + int curSum = 0, oddCnt = 0, evenCnt = 0, res = 0; + int MOD = (int)1e9 + 7; + + for (int n : arr) { + curSum += n; + if (curSum % 2 != 0) { + res = (res + 1 + evenCnt) % MOD; + oddCnt++; + } else { + res = (res + oddCnt) % MOD; + evenCnt++; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int numOfSubarrays(vector& arr) { + long long curSum = 0, oddCnt = 0, evenCnt = 0, res = 0; + const int MOD = 1e9 + 7; + + for (int n : arr) { + curSum += n; + if (curSum % 2 != 0) { + res = (res + 1 + evenCnt) % MOD; + oddCnt++; + } else { + res = (res + oddCnt) % MOD; + evenCnt++; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr + * @return {number} + */ + numOfSubarrays(arr) { + let curSum = 0, oddCnt = 0, evenCnt = 0, res = 0; + const MOD = 1e9 + 7; + + for (let n of arr) { + curSum += n; + if (curSum % 2 !== 0) { + res = (res + 1 + evenCnt) % MOD; + oddCnt++; + } else { + res = (res + oddCnt) % MOD; + evenCnt++; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 5. Prefix Sum - II + +::tabs-start + +```python +class Solution: + def numOfSubarrays(self, arr: List[int]) -> int: + count = [1, 0] + prefix = res = 0 + MOD = 10**9 + 7 + + for num in arr: + prefix = (prefix + num) % 2 + res = (res + count[1 - prefix]) % MOD + count[prefix] += 1 + + return res +``` + +```java +public class Solution { + public int numOfSubarrays(int[] arr) { + int[] count = {1, 0}; + int prefix = 0, res = 0; + int MOD = (int)1e9 + 7; + + for (int num : arr) { + prefix = (prefix + num) % 2; + res = (res + count[1 - prefix]) % MOD; + count[prefix]++; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int numOfSubarrays(vector& arr) { + int count[2] = {1, 0}; + int prefix = 0, res = 0; + const int MOD = 1e9 + 7; + + for (int num : arr) { + prefix = (prefix + num) % 2; + res = (res + count[1 - prefix]) % MOD; + count[prefix]++; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} arr + * @return {number} + */ + numOfSubarrays(arr) { + const count = [1, 0]; + let prefix = 0, res = 0; + const MOD = 1e9 + 7; + + for (const num of arr) { + prefix = (prefix + num) % 2; + res = (res + count[1 - prefix]) % MOD; + count[prefix]++; + } + + 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/number-of-ways-to-split-array.md b/articles/number-of-ways-to-split-array.md new file mode 100644 index 000000000..ca66c41c0 --- /dev/null +++ b/articles/number-of-ways-to-split-array.md @@ -0,0 +1,320 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def waysToSplitArray(self, nums: List[int]) -> int: + n = len(nums) + res = 0 + + for i in range(n - 1): + leftSum = 0 + for j in range(i + 1): + leftSum += nums[j] + + rightSum = 0 + for j in range(i + 1, n): + rightSum += nums[j] + + res += (1 if leftSum >= rightSum else 0) + + return res +``` + +```java +public class Solution { + public int waysToSplitArray(int[] nums) { + int n = nums.length; + int res = 0; + + for (int i = 0; i < n - 1; i++) { + long leftSum = 0; + for (int j = 0; j <= i; j++) { + leftSum += nums[j]; + } + + long rightSum = 0; + for (int j = i + 1; j < n; j++) { + rightSum += nums[j]; + } + + if (leftSum >= rightSum) { + res++; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int waysToSplitArray(vector& nums) { + int n = nums.size(); + int res = 0; + + for (int i = 0; i < n - 1; i++) { + long long leftSum = 0; + for (int j = 0; j <= i; j++) { + leftSum += nums[j]; + } + + long long rightSum = 0; + for (int j = i + 1; j < n; j++) { + rightSum += nums[j]; + } + + if (leftSum >= rightSum) { + res++; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + waysToSplitArray(nums) { + let n = nums.length; + let res = 0; + + for (let i = 0; i < n - 1; i++) { + let leftSum = 0; + for (let j = 0; j <= i; j++) { + leftSum += nums[j]; + } + + let rightSum = 0; + for (let j = i + 1; j < n; j++) { + rightSum += nums[j]; + } + + if (leftSum >= rightSum) { + res++; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Prefix Sum + +::tabs-start + +```python +class Solution: + def waysToSplitArray(self, nums: List[int]) -> int: + n = len(nums) + prefix = [0] * (n + 1) + + for i in range(n): + prefix[i + 1] = prefix[i] + nums[i] + + res = 0 + for i in range(1, n): + left = prefix[i] + right = prefix[n] - prefix[i] + if left >= right: + res += 1 + + return res +``` + +```java +public class Solution { + public int waysToSplitArray(int[] nums) { + int n = nums.length; + long[] prefix = new long[n + 1]; + + for (int i = 0; i < n; i++) { + prefix[i + 1] = prefix[i] + nums[i]; + } + + int res = 0; + for (int i = 1; i < n; i++) { + long left = prefix[i]; + long right = prefix[n] - prefix[i]; + if (left >= right) { + res++; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int waysToSplitArray(vector& nums) { + int n = nums.size(); + vector prefix(n + 1, 0); + + for (int i = 0; i < n; i++) { + prefix[i + 1] = prefix[i] + nums[i]; + } + + int res = 0; + for (int i = 1; i < n; i++) { + long long left = prefix[i]; + long long right = prefix[n] - prefix[i]; + if (left >= right) { + res++; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + waysToSplitArray(nums) { + const n = nums.length; + const prefix = Array(n + 1).fill(0); + + for (let i = 0; i < n; i++) { + prefix[i + 1] = prefix[i] + nums[i]; + } + + let res = 0; + for (let i = 1; i < n; i++) { + const left = prefix[i]; + const right = prefix[n] - prefix[i]; + if (left >= right) { + res++; + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Prefix Sum (Optimal) + +::tabs-start + +```python +class Solution: + def waysToSplitArray(self, nums: List[int]) -> int: + right = sum(nums) + left = res = 0 + + for i in range(len(nums) - 1): + left += nums[i] + right -= nums[i] + res += 1 if left >= right else 0 + + return res +``` + +```java +public class Solution { + public int waysToSplitArray(int[] nums) { + long right = 0, left = 0; + for (int num : nums) { + right += num; + } + + int res = 0; + for (int i = 0; i < nums.length - 1; i++) { + left += nums[i]; + right -= nums[i]; + if (left >= right) { + res++; + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int waysToSplitArray(vector& nums) { + long long right = 0, left = 0; + for (int num : nums) { + right += num; + } + + int res = 0; + for (int i = 0; i < nums.size() - 1; i++) { + left += nums[i]; + right -= nums[i]; + if (left >= right) { + res++; + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + waysToSplitArray(nums) { + let right = nums.reduce((a, b) => a + b, 0); + let left = 0, res = 0; + + for (let i = 0; i < nums.length - 1; i++) { + left += nums[i]; + right -= nums[i]; + if (left >= right) { + res++; + } + } + + 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/subarray-sums-divisible-by-k.md b/articles/subarray-sums-divisible-by-k.md new file mode 100644 index 000000000..f1faeaf61 --- /dev/null +++ b/articles/subarray-sums-divisible-by-k.md @@ -0,0 +1,280 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def subarraysDivByK(self, nums: List[int], k: int) -> int: + n, res = len(nums), 0 + + for i in range(n): + curSum = 0 + for j in range(i, n): + curSum += nums[j] + if curSum % k == 0: + res += 1 + + return res +``` + +```java +public class Solution { + public int subarraysDivByK(int[] nums, int k) { + int n = nums.length, res = 0; + + for (int i = 0; i < n; i++) { + int curSum = 0; + for (int j = i; j < n; j++) { + curSum += nums[j]; + if (curSum % k == 0) { + res++; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int subarraysDivByK(vector& nums, int k) { + int n = nums.size(), res = 0; + + for (int i = 0; i < n; i++) { + int curSum = 0; + for (int j = i; j < n; j++) { + curSum += nums[j]; + if (curSum % k == 0) { + res++; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ + subarraysDivByK(nums, k) { + const n = nums.length; + let res = 0; + + for (let i = 0; i < n; i++) { + let curSum = 0; + for (let j = i; j < n; j++) { + curSum += nums[j]; + if (curSum % k === 0) { + res++; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Prefix Sum + Hash Map + +::tabs-start + +```python +class Solution: + def subarraysDivByK(self, nums: List[int], k: int) -> int: + prefix_sum = 0 + res = 0 + prefix_cnt = defaultdict(int) + prefix_cnt[0] = 1 + + for n in nums: + prefix_sum += n + remain = prefix_sum % k + + res += prefix_cnt[remain] + prefix_cnt[remain] += 1 + + return res +``` + +```java +public class Solution { + public int subarraysDivByK(int[] nums, int k) { + int prefixSum = 0, res = 0; + Map prefixCnt = new HashMap<>(); + prefixCnt.put(0, 1); + + for (int n : nums) { + prefixSum += n; + int remain = prefixSum % k; + if (remain < 0) remain += k; + + res += prefixCnt.getOrDefault(remain, 0); + prefixCnt.put(remain, prefixCnt.getOrDefault(remain, 0) + 1); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int subarraysDivByK(vector& nums, int k) { + int prefixSum = 0, res = 0; + unordered_map prefixCnt; + prefixCnt[0] = 1; + + for (int n : nums) { + prefixSum += n; + int remain = prefixSum % k; + if (remain < 0) remain += k; + + res += prefixCnt[remain]; + prefixCnt[remain]++; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ + subarraysDivByK(nums, k) { + let prefixSum = 0, res = 0; + const prefixCnt = new Map(); + prefixCnt.set(0, 1); + + for (let n of nums) { + prefixSum += n; + let remain = prefixSum % k; + if (remain < 0) remain += k; + + res += prefixCnt.get(remain) || 0; + prefixCnt.set(remain, (prefixCnt.get(remain) || 0) + 1); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(k)$ + +--- + +## 3. Prefix Sum + Array + +::tabs-start + +```python +class Solution: + def subarraysDivByK(self, nums: List[int], k: int) -> int: + count = [0] * k + count[0] = 1 + prefix = res = 0 + + for num in nums: + prefix = (prefix + num + k) % k + res += count[prefix] + count[prefix] += 1 + + return res +``` + +```java +public class Solution { + public int subarraysDivByK(int[] nums, int k) { + int[] count = new int[k]; + count[0] = 1; + int prefix = 0, res = 0; + + for (int num : nums) { + prefix = (prefix + num % k + k) % k; + res += count[prefix]; + count[prefix]++; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + int subarraysDivByK(vector& nums, int k) { + vector count(k, 0); + count[0] = 1; + int prefix = 0, res = 0; + + for (int num : nums) { + prefix = (prefix + num % k + k) % k; + res += count[prefix]; + count[prefix]++; + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ + subarraysDivByK(nums, k) { + const count = Array(k).fill(0); + count[0] = 1; + let prefix = 0, res = 0; + + for (let num of nums) { + prefix = (prefix + num % k + k) % k; + res += count[prefix]; + count[prefix]++; + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + k)$ +* Space complexity: $O(k)$ \ No newline at end of file From 5e1f3c5436a5f2917a2bdb285e8f59750477e9e6 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Mon, 7 Apr 2025 23:34:45 +0530 Subject: [PATCH 7/9] Batch-6/Neetcode-ALL/Added-articles --- articles/shifting-letters-ii.md | 481 ++++++++++++++++++ articles/sort-the-jumbled-numbers.md | 244 +++++++++ articles/uncommon-words-from-two-sentences.md | 183 +++++++ articles/word-subsets.md | 293 +++++++++++ 4 files changed, 1201 insertions(+) create mode 100644 articles/shifting-letters-ii.md create mode 100644 articles/sort-the-jumbled-numbers.md create mode 100644 articles/uncommon-words-from-two-sentences.md create mode 100644 articles/word-subsets.md diff --git a/articles/shifting-letters-ii.md b/articles/shifting-letters-ii.md new file mode 100644 index 000000000..12d3e9499 --- /dev/null +++ b/articles/shifting-letters-ii.md @@ -0,0 +1,481 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def shiftingLetters(self, s: str, shifts: List[List[int]]) -> str: + s = [ord(c) - ord('a') for c in s] + + for l, r, d in shifts: + for i in range(l, r + 1): + s[i] += 1 if d else -1 + s[i] %= 26 + + s = [chr(ord('a') + c) for c in s] + return "".join(s) +``` + +```java +class Solution { + public String shiftingLetters(String s, int[][] shifts) { + char[] arr = s.toCharArray(); + int[] letters = new int[arr.length]; + + for (int i = 0; i < arr.length; i++) { + letters[i] = arr[i] - 'a'; + } + + for (int[] shift : shifts) { + int l = shift[0], r = shift[1], d = shift[2]; + for (int i = l; i <= r; i++) { + letters[i] = (letters[i] + (d == 1 ? 1 : -1) + 26) % 26; + } + } + + for (int i = 0; i < arr.length; i++) { + arr[i] = (char) (letters[i] + 'a'); + } + + return new String(arr); + } +} +``` + +```cpp +class Solution { +public: + string shiftingLetters(string s, vector>& shifts) { + vector letters(s.size()); + for (int i = 0; i < s.size(); i++) { + letters[i] = s[i] - 'a'; + } + + for (const auto& shift : shifts) { + int l = shift[0], r = shift[1], d = shift[2]; + for (int i = l; i <= r; i++) { + letters[i] = (letters[i] + (d == 1 ? 1 : -1) + 26) % 26; + } + } + + for (int i = 0; i < s.size(); i++) { + s[i] = letters[i] + 'a'; + } + + return s; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @param {number[][]} shifts + * @return {string} + */ + shiftingLetters(s, shifts) { + let arr = Array.from(s).map(c => c.charCodeAt(0) - 97); + + for (const [l, r, d] of shifts) { + for (let i = l; i <= r; i++) { + arr[i] = (arr[i] + (d === 1 ? 1 : -1) + 26) % 26; + } + } + + return arr.map(c => String.fromCharCode(c + 97)).join(''); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * m)$ +* Space complexity: $O(n)$ + +> Where $n$ is the length of the string $s$ and $m$ is the size of the array $shifts$. + +--- + +## 2. Sweep Line Algorithm + +::tabs-start + +```python +class Solution: + def shiftingLetters(self, s: str, shifts: List[List[int]]) -> str: + prefix_diff = [0] * (len(s) + 1) + + for left, right, d in shifts: + val = 1 if d == 1 else -1 + prefix_diff[left] += val + prefix_diff[right + 1] -= val + + diff = 0 + res = [ord(c) - ord("a") for c in s] + + for i in range(len(s)): + diff += prefix_diff[i] + res[i] = (diff + res[i] + 26) % 26 + + s = [chr(ord("a") + n) for n in res] + return "".join(s) +``` + +```java +class Solution { + public String shiftingLetters(String s, int[][] shifts) { + int n = s.length(); + int[] prefix_diff = new int[n + 1]; + + for (int[] shift : shifts) { + int left = shift[0], right = shift[1], d = shift[2]; + int val = d == 1 ? 1 : -1; + prefix_diff[left] += val; + prefix_diff[right + 1] -= val; + } + + int[] res = new int[n]; + for (int i = 0; i < n; i++) { + res[i] = s.charAt(i) - 'a'; + } + + int diff = 0; + for (int i = 0; i < n; i++) { + diff += prefix_diff[i]; + res[i] = (res[i] + diff % 26 + 26) % 26; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + sb.append((char) ('a' + res[i])); + } + + return sb.toString(); + } +} +``` + +```cpp +class Solution { +public: + string shiftingLetters(string s, vector>& shifts) { + int n = s.size(); + vector prefix_diff(n + 1, 0); + + for (auto& shift : shifts) { + int left = shift[0], right = shift[1], d = shift[2]; + int val = d == 1 ? 1 : -1; + prefix_diff[left] += val; + prefix_diff[right + 1] -= val; + } + + int diff = 0; + vector res(n); + for (int i = 0; i < n; ++i) { + res[i] = s[i] - 'a'; + } + + for (int i = 0; i < n; ++i) { + diff += prefix_diff[i]; + res[i] = (diff % 26 + res[i] + 26) % 26; + } + + for (int i = 0; i < n; ++i) { + s[i] = 'a' + res[i]; + } + + return s; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @param {number[][]} shifts + * @return {string} + */ + shiftingLetters(s, shifts) { + const n = s.length; + const prefix_diff = Array(n + 1).fill(0); + + for (const [left, right, d] of shifts) { + const val = d === 1 ? 1 : -1; + prefix_diff[left] += val; + prefix_diff[right + 1] -= val; + } + + let diff = 0; + const res = Array.from(s).map(c => c.charCodeAt(0) - 'a'.charCodeAt(0)); + + for (let i = 0; i < n; i++) { + diff += prefix_diff[i]; + res[i] = (diff % 26 + res[i] + 26) % 26; + } + + return res.map(x => String.fromCharCode('a'.charCodeAt(0) + x)).join(''); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n)$ + +> Where $n$ is the length of the string $s$ and $m$ is the size of the array $shifts$. + +--- + +## 3. Binary Indexed Tree (Fenwick Tree) + +::tabs-start + +```python +class BIT: + def __init__(self, size): + self.n = size + 2 + self.tree = [0] * self.n + + def update(self, index, delta): + index += 1 + while index < self.n: + self.tree[index] += delta + index += index & -index + + def prefix_sum(self, index): + index += 1 + total = 0 + while index > 0: + total += self.tree[index] + index -= index & -index + return total + + def range_update(self, left, right, delta): + self.update(left, delta) + self.update(right + 1, -delta) + + +class Solution: + def shiftingLetters(self, s: str, shifts: List[List[int]]) -> str: + n = len(s) + bit = BIT(n) + + for left, right, d in shifts: + delta = 1 if d == 1 else -1 + bit.range_update(left, right, delta) + + res = [] + for i in range(n): + shift = bit.prefix_sum(i) % 26 + code = (ord(s[i]) - ord('a') + shift + 26) % 26 + res.append(chr(ord('a') + code)) + + return ''.join(res) +``` + +```java +class BIT { + int[] tree; + int n; + + public BIT(int size) { + n = size + 2; + tree = new int[n]; + } + + public void update(int index, int delta) { + index++; + while (index < n) { + tree[index] += delta; + index += index & -index; + } + } + + public int prefixSum(int index) { + index++; + int sum = 0; + while (index > 0) { + sum += tree[index]; + index -= index & -index; + } + return sum; + } + + public void rangeUpdate(int left, int right, int delta) { + update(left, delta); + update(right + 1, -delta); + } +} + +public class Solution { + public String shiftingLetters(String s, int[][] shifts) { + int n = s.length(); + BIT bit = new BIT(n); + + for (int[] shift : shifts) { + int left = shift[0], right = shift[1], d = shift[2]; + int delta = d == 1 ? 1 : -1; + bit.rangeUpdate(left, right, delta); + } + + StringBuilder res = new StringBuilder(); + for (int i = 0; i < n; i++) { + int shift = bit.prefixSum(i) % 26; + int code = (s.charAt(i) - 'a' + shift + 26) % 26; + res.append((char) ('a' + code)); + } + + return res.toString(); + } +} +``` + +```cpp +class BIT { + vector tree; + int n; +public: + BIT(int size) { + n = size + 2; + tree.assign(n, 0); + } + + void update(int index, int delta) { + index++; + while (index < n) { + tree[index] += delta; + index += index & -index; + } + } + + int prefixSum(int index) { + index++; + int sum = 0; + while (index > 0) { + sum += tree[index]; + index -= index & -index; + } + return sum; + } + + void rangeUpdate(int left, int right, int delta) { + update(left, delta); + update(right + 1, -delta); + } +}; + +class Solution { +public: + string shiftingLetters(string s, vector>& shifts) { + int n = s.size(); + BIT bit(n); + + for (auto& shift : shifts) { + int left = shift[0], right = shift[1], d = shift[2]; + int delta = d == 1 ? 1 : -1; + bit.rangeUpdate(left, right, delta); + } + + string res; + for (int i = 0; i < n; i++) { + int shift = bit.prefixSum(i) % 26; + int code = (s[i] - 'a' + shift + 26) % 26; + res += char('a' + code); + } + + return res; + } +}; +``` + +```javascript +class BIT { + /** + * @constructor + * @param {number} size + */ + constructor(size) { + this.n = size + 2; + this.tree = new Array(this.n).fill(0); + } + + /** + * @param {number} index + * @param {number} delta + * @return {void} + */ + update(index, delta) { + index++; + while (index < this.n) { + this.tree[index] += delta; + index += index & -index; + } + } + + /** + * @param {number} index + * @return {number} + */ + prefixSum(index) { + index++; + let sum = 0; + while (index > 0) { + sum += this.tree[index]; + index -= index & -index; + } + return sum; + } + + /** + * @param {number} left + * @param {number} right + * @param {number} delta + * @return {void} + */ + rangeUpdate(left, right, delta) { + this.update(left, delta); + this.update(right + 1, -delta); + } +} + +class Solution { + /** + * @param {string} s + * @param {number[][]} shifts + * @return {string} + */ + shiftingLetters(s, shifts) { + const n = s.length; + const bit = new BIT(n); + for (const [left, right, d] of shifts) { + const delta = d === 1 ? 1 : -1; + bit.rangeUpdate(left, right, delta); + } + + let res = ""; + for (let i = 0; i < n; i++) { + const shift = bit.prefixSum(i) % 26; + const code = (s.charCodeAt(i) - 97 + shift + 26) % 26; + res += String.fromCharCode(97 + code); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O((m + n) * \log n)$ +* Space complexity: $O(n)$ + +> Where $n$ is the length of the string $s$ and $m$ is the size of the array $shifts$. \ No newline at end of file diff --git a/articles/sort-the-jumbled-numbers.md b/articles/sort-the-jumbled-numbers.md new file mode 100644 index 000000000..b8c0cbf47 --- /dev/null +++ b/articles/sort-the-jumbled-numbers.md @@ -0,0 +1,244 @@ +## 1. Convert To Strings + Sorting + +::tabs-start + +```python +class Solution: + def sortJumbled(self, mapping: List[int], nums: List[int]) -> List[int]: + pairs = [] + + for i, n in enumerate(nums): + n = str(n) + mapped_n = 0 + for c in n: + mapped_n *= 10 + mapped_n += mapping[int(c)] + pairs.append((mapped_n, i)) + + pairs.sort() + return [nums[p[1]] for p in pairs] +``` + +```java +public class Solution { + public int[] sortJumbled(int[] mapping, int[] nums) { + int n = nums.length; + int[][] pairs = new int[n][2]; + + for (int i = 0; i < n; i++) { + String numStr = String.valueOf(nums[i]); + int mapped_n = 0; + for (char c : numStr.toCharArray()) { + mapped_n = mapped_n * 10 + mapping[c - '0']; + } + pairs[i][0] = mapped_n; + pairs[i][1] = i; + } + + Arrays.sort(pairs, (a, b) -> a[0] - b[0]); + + int[] res = new int[n]; + for (int i = 0; i < n; i++) { + res[i] = nums[pairs[i][1]]; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector sortJumbled(vector& mapping, vector& nums) { + vector> pairs; + + for (int i = 0; i < nums.size(); ++i) { + string numStr = to_string(nums[i]); + int mapped_n = 0; + for (char c : numStr) { + mapped_n = mapped_n * 10 + mapping[c - '0']; + } + pairs.push_back({mapped_n, i}); + } + + sort(pairs.begin(), pairs.end()); + + vector res; + for (auto& p : pairs) { + res.push_back(nums[p.second]); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} mapping + * @param {number[]} nums + * @return {number[]} + */ + sortJumbled(mapping, nums) { + let pairs = []; + + for (let i = 0; i < nums.length; i++) { + let numStr = nums[i].toString(); + let mapped_n = 0; + for (let c of numStr) { + mapped_n = mapped_n * 10 + mapping[parseInt(c)]; + } + pairs.push([mapped_n, i]); + } + + pairs.sort((a, b) => a[0] - b[0]); + + return pairs.map(p => nums[p[1]]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Iterate On Numbers + Sorting + +::tabs-start + +```python +class Solution: + def sortJumbled(self, mapping: List[int], nums: List[int]) -> List[int]: + pairs = [] + + for i, n in enumerate(nums): + mapped_n = 0 + base = 1 + + if n == 0: + mapped_n = mapping[0] + else: + while n > 0: + digit = n % 10 + n //= 10 + mapped_n += base * mapping[digit] + base *= 10 + + pairs.append((mapped_n, i)) + + pairs.sort() + return [nums[p[1]] for p in pairs] +``` + +```java +public class Solution { + public int[] sortJumbled(int[] mapping, int[] nums) { + int n = nums.length; + int[][] pairs = new int[n][2]; + + for (int i = 0; i < n; i++) { + int mapped_n = 0, base = 1; + int num = nums[i]; + + if (num == 0) { + mapped_n = mapping[0]; + } else { + while (num > 0) { + int digit = num % 10; + num /= 10; + mapped_n += base * mapping[digit]; + base *= 10; + } + } + + pairs[i][0] = mapped_n; + pairs[i][1] = i; + } + + Arrays.sort(pairs, (a, b) -> Integer.compare(a[0], b[0])); + + int[] res = new int[n]; + for (int i = 0; i < n; i++) { + res[i] = nums[pairs[i][1]]; + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector sortJumbled(vector& mapping, vector& nums) { + vector> pairs; + + for (int i = 0; i < nums.size(); i++) { + int mapped_n = 0, base = 1; + int num = nums[i]; + + if (num == 0) { + mapped_n = mapping[0]; + } else { + while (num > 0) { + int digit = num % 10; + num /= 10; + mapped_n += base * mapping[digit]; + base *= 10; + } + } + + pairs.push_back({mapped_n, i}); + } + + sort(pairs.begin(), pairs.end()); + + vector res; + for (auto& p : pairs) { + res.push_back(nums[p.second]); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} mapping + * @param {number[]} nums + * @return {number[]} + */ + sortJumbled(mapping, nums) { + let pairs = []; + + for (let i = 0; i < nums.length; i++) { + let numStr = nums[i].toString(); + let mapped_n = 0; + for (let c of numStr) { + mapped_n = mapped_n * 10 + mapping[parseInt(c)]; + } + pairs.push([mapped_n, i]); + } + + pairs.sort((a, b) => a[0] - b[0]); + + return pairs.map(p => nums[p[1]]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/uncommon-words-from-two-sentences.md b/articles/uncommon-words-from-two-sentences.md new file mode 100644 index 000000000..67be56a4b --- /dev/null +++ b/articles/uncommon-words-from-two-sentences.md @@ -0,0 +1,183 @@ +## 1. Hash Map - I + +::tabs-start + +```python +class Solution: + def uncommonFromSentences(self, s1: str, s2: str) -> List[str]: + count = defaultdict(int) + for w in s1.split(" ") + s2.split(" "): + count[w] += 1 + + res = [] + for w, cnt in count.items(): + if cnt == 1: + res.append(w) + return res +``` + +```java +public class Solution { + public String[] uncommonFromSentences(String s1, String s2) { + String[] words = (s1 + " " + s2).split(" "); + Map count = new HashMap<>(); + + for (String w : words) { + count.put(w, count.getOrDefault(w, 0) + 1); + } + + List res = new ArrayList<>(); + for (Map.Entry entry : count.entrySet()) { + if (entry.getValue() == 1) { + res.add(entry.getKey()); + } + } + + return res.toArray(new String[0]); + } +} +``` + +```cpp +class Solution { +public: + vector uncommonFromSentences(string s1, string s2) { + unordered_map count; + istringstream ss(s1 + " " + s2); + string w; + while (ss >> w) { + count[w]++; + } + + vector res; + for (auto& [word, freq] : count) { + if (freq == 1) { + res.push_back(word); + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s1 + * @param {string} s2 + * @return {string[]} + */ + uncommonFromSentences(s1, s2) { + const words = (s1 + " " + s2).split(" "); + const count = new Map(); + + for (const w of words) { + count.set(w, (count.get(w) || 0) + 1); + } + + const res = []; + for (const [w, c] of count.entries()) { + if (c === 1) { + res.push(w); + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ and $m$ are the lengths of the strings $s1$ and $s2$, respectively. + +--- + +## 2. Hash Map - II + +::tabs-start + +```python +class Solution: + def uncommonFromSentences(self, s1: str, s2: str) -> List[str]: + return [w for w, cnt in Counter(s1.split(" ") + s2.split(" ")).items() if cnt == 1] +``` + +```java +public class Solution { + public String[] uncommonFromSentences(String s1, String s2) { + String[] words = (s1 + " " + s2).split(" "); + Map count = new HashMap<>(); + + for (String w : words) { + count.put(w, count.getOrDefault(w, 0) + 1); + } + + return count.entrySet() + .stream() + .filter(e -> e.getValue() == 1) + .map(Map.Entry::getKey) + .toArray(String[]::new); + } +} +``` + +```cpp +class Solution { +public: + vector uncommonFromSentences(string s1, string s2) { + unordered_map count; + istringstream ss(s1 + " " + s2); + string w; + while (ss >> w) { + count[w]++; + } + + vector res; + for (auto& [w, c] : count) { + if (c == 1) { + res.push_back(w); + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s1 + * @param {string} s2 + * @return {string[]} + */ + uncommonFromSentences(s1, s2) { + const words = (s1 + " " + s2).split(" "); + const count = new Map(); + + for (const w of words) { + count.set(w, (count.get(w) || 0) + 1); + } + + return [...count.entries()] + .filter(([_, c]) => c === 1) + .map(([w]) => w); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(n + m)$ + +> Where $n$ and $m$ are the lengths of the strings $s1$ and $s2$, respectively. \ No newline at end of file diff --git a/articles/word-subsets.md b/articles/word-subsets.md new file mode 100644 index 000000000..d96eab686 --- /dev/null +++ b/articles/word-subsets.md @@ -0,0 +1,293 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def wordSubsets(self, words1: List[str], words2: List[str]) -> List[str]: + res = [] + for w1 in words1: + count1 = Counter(w1) + is_subset = True + + for w2 in words2: + count2 = Counter(w2) + for c in count2: + if count2[c] > count1[c]: + is_subset = False + break + + if not is_subset: break + + if is_subset: + res.append(w1) + + return res +``` + +```java +public class Solution { + public List wordSubsets(String[] words1, String[] words2) { + List res = new ArrayList<>(); + + for (String w1 : words1) { + int[] count1 = new int[26]; + for (char c : w1.toCharArray()) count1[c - 'a']++; + + boolean isSubset = true; + for (String w2 : words2) { + int[] count2 = new int[26]; + for (char c : w2.toCharArray()) count2[c - 'a']++; + + for (int i = 0; i < 26; i++) { + if (count2[i] > count1[i]) { + isSubset = false; + break; + } + } + + if (!isSubset) break; + } + + if (isSubset) res.add(w1); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector wordSubsets(vector& words1, vector& words2) { + vector res; + + for (const string& w1 : words1) { + vector count1(26, 0); + for (char c : w1) count1[c - 'a']++; + + bool isSubset = true; + for (const string& w2 : words2) { + vector count2(26, 0); + for (char c : w2) count2[c - 'a']++; + + for (int i = 0; i < 26; i++) { + if (count2[i] > count1[i]) { + isSubset = false; + break; + } + } + + if (!isSubset) break; + } + + if (isSubset) res.push_back(w1); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words1 + * @param {string[]} words2 + * @return {string[]} + */ + wordSubsets(words1, words2) { + const res = []; + + for (const w1 of words1) { + const count1 = Array(26).fill(0); + for (const c of w1) count1[c.charCodeAt(0) - 97]++; + + let isSubset = true; + for (const w2 of words2) { + const count2 = Array(26).fill(0); + for (const c of w2) count2[c.charCodeAt(0) - 97]++; + + for (let i = 0; i < 26; i++) { + if (count2[i] > count1[i]) { + isSubset = false; + break; + } + } + + if (!isSubset) break; + } + + if (isSubset) res.push(w1); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(N * n + N * M * m)$ +* Space complexity: + * $O(1)$ extra space, since we have at most $26$ different characters. + * $O(N * n)$ space for the output list. + +> Where $N$ is the size of the array $words1$, $n$ is the length of the longest word in $words1$, $M$ is the size of the array $words2$, and $m$ is the length of the longest word in $words2$. + +--- + +## 2. Greedy + Hash Map + +::tabs-start + +```python +class Solution: + def wordSubsets(self, words1: List[str], words2: List[str]) -> List[str]: + count_2 = defaultdict(int) + for w in words2: + count_w = Counter(w) + for c, cnt in count_w.items(): + count_2[c] = max(count_2[c], cnt) + + res = [] + for w in words1: + count_w = Counter(w) + flag = True + for c, cnt in count_2.items(): + if count_w[c] < cnt: + flag = False + break + if flag: + res.append(w) + + return res +``` + +```java +public class Solution { + public List wordSubsets(String[] words1, String[] words2) { + int[] count2 = new int[26]; + for (String w : words2) { + int[] countW = new int[26]; + for (char c : w.toCharArray()) { + countW[c - 'a']++; + } + for (int i = 0; i < 26; i++) { + count2[i] = Math.max(count2[i], countW[i]); + } + } + + List res = new ArrayList<>(); + for (String w : words1) { + int[] countW = new int[26]; + for (char c : w.toCharArray()) { + countW[c - 'a']++; + } + + boolean flag = true; + for (int i = 0; i < 26; i++) { + if (countW[i] < count2[i]) { + flag = false; + break; + } + } + + if (flag) { + res.add(w); + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector wordSubsets(vector& words1, vector& words2) { + vector count2(26, 0); + for (string& w : words2) { + vector countW(26, 0); + for (char c : w) countW[c - 'a']++; + for (int i = 0; i < 26; ++i) + count2[i] = max(count2[i], countW[i]); + } + + vector res; + for (string& w : words1) { + vector countW(26, 0); + for (char c : w) countW[c - 'a']++; + + bool flag = true; + for (int i = 0; i < 26; ++i) { + if (countW[i] < count2[i]) { + flag = false; + break; + } + } + + if (flag) res.push_back(w); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} words1 + * @param {string[]} words2 + * @return {string[]} + */ + wordSubsets(words1, words2) { + const count2 = new Array(26).fill(0); + for (let w of words2) { + const countW = new Array(26).fill(0); + for (let c of w) { + countW[c.charCodeAt(0) - 97]++; + } + for (let i = 0; i < 26; i++) { + count2[i] = Math.max(count2[i], countW[i]); + } + } + + const res = []; + for (let w of words1) { + const countW = new Array(26).fill(0); + for (let c of w) { + countW[c.charCodeAt(0) - 97]++; + } + + let flag = true; + for (let i = 0; i < 26; i++) { + if (countW[i] < count2[i]) { + flag = false; + break; + } + } + + if (flag) res.push(w); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(N * n + M * m)$ +* Space complexity: + * $O(1)$ extra space, since we have at most $26$ different characters. + * $O(N * n)$ space for the output list. + +> Where $N$ is the size of the array $words1$, $n$ is the length of the longest word in $words1$, $M$ is the size of the array $words2$, and $m$ is the length of the longest word in $words2$. \ No newline at end of file From 059df07009ecea6fe3287d7e5425f847c62f4e24 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Wed, 9 Apr 2025 20:24:21 +0530 Subject: [PATCH 8/9] Batch-6/Neetcode-ALL/Added-articles --- articles/count-number-of-bad-pairs.md | 157 ++++++++++++++++++ ...inimum-remove-to-make-valid-parentheses.md | 124 ++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 articles/count-number-of-bad-pairs.md diff --git a/articles/count-number-of-bad-pairs.md b/articles/count-number-of-bad-pairs.md new file mode 100644 index 000000000..936e3af7f --- /dev/null +++ b/articles/count-number-of-bad-pairs.md @@ -0,0 +1,157 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def countBadPairs(self, nums: List[int]) -> int: + n, res = len(nums), 0 + for i in range(n - 1): + for j in range(i + 1, n): + if j - i != nums[j] - nums[i]: + res += 1 + return res +``` + +```java +public class Solution { + public long countBadPairs(int[] nums) { + int n = nums.length; + long res = 0; + for (int i = 0; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + if (j - i != nums[j] - nums[i]) { + res++; + } + } + } + return res; + } +} +``` + +```cpp +class Solution { +public: + long long countBadPairs(vector& nums) { + int n = nums.size(); + long long res = 0; + for (int i = 0; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + if (j - i != nums[j] - nums[i]) { + res++; + } + } + } + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + countBadPairs(nums) { + let n = nums.length, res = 0; + for (let i = 0; i < n - 1; i++) { + for (let j = i + 1; j < n; j++) { + if (j - i !== nums[j] - nums[i]) { + res++; + } + } + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 2. Hash Map + +::tabs-start + +```python +class Solution: + def countBadPairs(self, nums: List[int]) -> int: + good_pairs = 0 + total_pairs = 0 + count = defaultdict(int) + + for i in range(len(nums)): + total_pairs += i + good_pairs += count[nums[i] - i] + count[nums[i] - i] += 1 + + return total_pairs - good_pairs +``` + +```java +public class Solution { + public long countBadPairs(int[] nums) { + Map count = new HashMap<>(); + long total = 0, good = 0; + for (int i = 0; i < nums.length; i++) { + int key = nums[i] - i; + good += count.getOrDefault(key, 0); + count.put(key, count.getOrDefault(key, 0) + 1); + total += i; + } + return total - good; + } +} +``` + +```cpp +class Solution { +public: + long long countBadPairs(vector& nums) { + unordered_map count; + long long total = 0, good = 0; + for (int i = 0; i < nums.size(); i++) { + int key = nums[i] - i; + good += count[key]; + count[key]++; + total += i; + } + return total - good; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + countBadPairs(nums) { + let count = new Map(); + let total = 0, good = 0; + for (let i = 0; i < nums.length; i++) { + let key = nums[i] - i; + good += count.get(key) || 0; + count.set(key, (count.get(key) || 0) + 1); + total += i; + } + return total - good; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/minimum-remove-to-make-valid-parentheses.md b/articles/minimum-remove-to-make-valid-parentheses.md index 23627cf72..43c6d5981 100644 --- a/articles/minimum-remove-to-make-valid-parentheses.md +++ b/articles/minimum-remove-to-make-valid-parentheses.md @@ -128,6 +128,39 @@ class Solution { } ``` +```csharp +public class Solution { + public string MinRemoveToMakeValid(string s) { + List res = new List(); + int cnt = 0; + + foreach (char c in s) { + if (c == '(') { + res.Add(c); + cnt++; + } else if (c == ')' && cnt > 0) { + res.Add(c); + cnt--; + } else if (c != ')') { + res.Add(c); + } + } + + List filtered = new List(); + for (int i = res.Count - 1; i >= 0; i--) { + if (res[i] == '(' && cnt > 0) { + cnt--; + } else { + filtered.Add(res[i]); + } + } + + filtered.Reverse(); + return new string(filtered.ToArray()); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -264,6 +297,37 @@ class Solution { } ``` +```csharp +public class Solution { + public string MinRemoveToMakeValid(string s) { + char[] arr = s.ToCharArray(); + int cnt = 0; + + for (int i = 0; i < s.Length; i++) { + if (s[i] == '(') { + cnt++; + } else if (s[i] == ')' && cnt > 0) { + cnt--; + } else if (s[i] == ')') { + arr[i] = '\0'; // mark invalid ')' + } + } + + List res = new List(); + for (int i = arr.Length - 1; i >= 0; i--) { + if (arr[i] == '(' && cnt > 0) { + cnt--; + } else if (arr[i] != '\0') { + res.Add(arr[i]); + } + } + + res.Reverse(); + return new string(res.ToArray()); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -393,6 +457,40 @@ class Solution { } ``` +```csharp +public class Solution { + public string MinRemoveToMakeValid(string s) { + char[] arr = s.ToCharArray(); + Stack stack = new Stack(); + + for (int i = 0; i < arr.Length; i++) { + if (arr[i] == '(') { + stack.Push(i); + } else if (arr[i] == ')') { + if (stack.Count > 0) { + stack.Pop(); + } else { + arr[i] = '\0'; + } + } + } + + while (stack.Count > 0) { + arr[stack.Pop()] = '\0'; + } + + StringBuilder result = new StringBuilder(); + foreach (char c in arr) { + if (c != '\0') { + result.Append(c); + } + } + + return result.ToString(); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -512,6 +610,32 @@ class Solution { } ``` +```csharp +public class Solution { + public string MinRemoveToMakeValid(string s) { + int openCnt = 0, closeCnt = 0; + foreach (char c in s) { + if (c == ')') closeCnt++; + } + + StringBuilder res = new StringBuilder(); + foreach (char c in s) { + if (c == '(') { + if (openCnt == closeCnt) continue; + openCnt++; + } else if (c == ')') { + closeCnt--; + if (openCnt == 0) continue; + openCnt--; + } + res.Append(c); + } + + return res.ToString(); + } +} +``` + ::tabs-end ### Time & Space Complexity From 6f155616c9051004b48679397298fdf279ae0545 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Mon, 14 Apr 2025 20:39:09 +0530 Subject: [PATCH 9/9] Batch-6/Neetcode-ALL/Added-articles --- .../binary-tree-vertical-order-traversal.md | 837 ++++++++++++++++++ articles/buildings-with-an-ocean-view.md | 339 +++++++ articles/valid-palindrome-ii.md | 81 ++ articles/valid-word-abbreviation.md | 163 ++++ 4 files changed, 1420 insertions(+) create mode 100644 articles/binary-tree-vertical-order-traversal.md create mode 100644 articles/buildings-with-an-ocean-view.md create mode 100644 articles/valid-word-abbreviation.md diff --git a/articles/binary-tree-vertical-order-traversal.md b/articles/binary-tree-vertical-order-traversal.md new file mode 100644 index 000000000..506fdad2c --- /dev/null +++ b/articles/binary-tree-vertical-order-traversal.md @@ -0,0 +1,837 @@ +## 1. Breadth First Search + Sorting + +::tabs-start + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def verticalOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + cols = defaultdict(list) + que = deque([(root, 0)]) + + while que: + node, pos = que.popleft() + if node: + cols[pos].append(node.val) + que.append((node.left, pos - 1)) + que.append((node.right, pos + 1)) + + return [cols[x] for x in sorted(cols)] +``` + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + public List> verticalOrder(TreeNode root) { + if (root == null) return new ArrayList<>(); + + Map> cols = new TreeMap<>(); + Queue> queue = new LinkedList<>(); + queue.offer(new Pair<>(root, 0)); + + while (!queue.isEmpty()) { + Pair p = queue.poll(); + TreeNode node = p.getKey(); + int pos = p.getValue(); + + cols.computeIfAbsent(pos, k -> new ArrayList<>()).add(node.val); + + if (node.left != null) queue.offer(new Pair<>(node.left, pos - 1)); + if (node.right != null) queue.offer(new Pair<>(node.right, pos + 1)); + } + + return new ArrayList<>(cols.values()); + } +} +``` + +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector> verticalOrder(TreeNode* root) { + if (!root) return {}; + map> cols; + queue> q; + q.push({root, 0}); + + while (!q.empty()) { + auto [node, pos] = q.front(); q.pop(); + cols[pos].push_back(node->val); + if (node->left) q.push({node->left, pos - 1}); + if (node->right) q.push({node->right, pos + 1}); + } + + vector> res; + for (auto& [_, vec] : cols) + res.push_back(vec); + return res; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + /** + * @param {TreeNode} root + * @return {number[][]} + */ + verticalOrder(root) { + if (!root) return []; + + const cols = new Map(); + const queue = new Queue([[root, 0]]); + + while (!queue.isEmpty()) { + const [node, pos] = queue.pop(); + if (!cols.has(pos)) cols.set(pos, []); + cols.get(pos).push(node.val); + + if (node.left) queue.push([node.left, pos - 1]); + if (node.right) queue.push([node.right, pos + 1]); + } + + const sortedKeys = Array.from(cols.keys()).sort((a, b) => a - b); + return sortedKeys.map(k => cols.get(k)); + } +} +``` + +```csharp +/** + * Definition for a binary tree node. + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + public IList> VerticalOrder(TreeNode root) { + if (root == null) return new List>(); + + var cols = new SortedDictionary>(); + var queue = new Queue<(TreeNode node, int pos)>(); + queue.Enqueue((root, 0)); + + while (queue.Count > 0) { + var (node, pos) = queue.Dequeue(); + + if (!cols.ContainsKey(pos)) + cols[pos] = new List(); + cols[pos].Add(node.val); + + if (node.left != null) queue.Enqueue((node.left, pos - 1)); + if (node.right != null) queue.Enqueue((node.right, pos + 1)); + } + + return cols.Values.ToList>(); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Depth First Search + Sorting + +::tabs-start + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def verticalOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + cols = defaultdict(list) + + def dfs(node, row, col): + if not node: + return + cols[col].append((row, node.val)) + dfs(node.left, row + 1, col - 1) + dfs(node.right, row + 1, col + 1) + + dfs(root, 0, 0) + + res = [] + for col in sorted(cols): + col_vals = sorted(cols[col], key=lambda x: x[0]) + res.append([val for _, val in col_vals]) + return res +``` + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + private Map> cols = new TreeMap<>(); + + public List> verticalOrder(TreeNode root) { + dfs(root, 0, 0); + List> res = new ArrayList<>(); + + for (List list : cols.values()) { + list.sort(Comparator.comparingInt(a -> a[0])); + List colVals = new ArrayList<>(); + for (int[] p : list) colVals.add(p[1]); + res.add(colVals); + } + + return res; + } + + private void dfs(TreeNode node, int row, int col) { + if (node == null) return; + cols.computeIfAbsent(col, k -> new ArrayList<>()).add(new int[]{row, node.val}); + dfs(node.left, row + 1, col - 1); + dfs(node.right, row + 1, col + 1); + } +} +``` + +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { + map>> cols; + + void dfs(TreeNode* node, int row, int col) { + if (!node) return; + cols[col].push_back({row, node->val}); + dfs(node->left, row + 1, col - 1); + dfs(node->right, row + 1, col + 1); + } + +public: + vector> verticalOrder(TreeNode* root) { + dfs(root, 0, 0); + vector> res; + + for (auto& [col, vec] : cols) { + stable_sort(vec.begin(), vec.end(), + [](const pair& a, const pair& b) { + return a.first < b.first; // sort ONLY by row + }); + + vector colVals; + for (auto& [_, val] : vec) + colVals.push_back(val); + res.push_back(colVals); + } + + return res; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + /** + * @param {TreeNode} root + * @return {number[][]} + */ + verticalOrder(root) { + const cols = new Map(); + + const dfs = (node, row, col) => { + if (!node) return; + if (!cols.has(col)) cols.set(col, []); + cols.get(col).push([row, node.val]); + dfs(node.left, row + 1, col - 1); + dfs(node.right, row + 1, col + 1); + }; + + dfs(root, 0, 0); + + const sortedCols = Array.from(cols.entries()).sort((a, b) => a[0] - b[0]); + return sortedCols.map(([_, vec]) => + vec.sort((a, b) => a[0] - b[0]).map(([_, val]) => val) + ); + } +} +``` + +```csharp +/** + * Definition for a binary tree node. + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + private SortedDictionary> cols = new(); + + public IList> VerticalOrder(TreeNode root) { + DFS(root, 0, 0); + + List> res = new(); + foreach (var entry in cols) { + var list = entry.Value.OrderBy(x => x.Item1).Select(x => x.Item2).ToList(); + res.Add(list); + } + + return res; + } + + private void DFS(TreeNode node, int row, int col) { + if (node == null) return; + if (!cols.ContainsKey(col)) cols[col] = new List<(int, int)>(); + cols[col].Add((row, node.val)); + DFS(node.left, row + 1, col - 1); + DFS(node.right, row + 1, col + 1); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n \log n)$ + +--- + +## 3. Breadth First Search (Optimal) + +::tabs-start + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def verticalOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + if not root: + return [] + + cols = defaultdict(list) + queue = deque([(root, 0)]) + minCol = maxCol = 0 + + while queue: + node, col = queue.popleft() + cols[col].append(node.val) + minCol = min(minCol, col) + maxCol = max(maxCol, col) + + if node.left: + queue.append((node.left, col - 1)) + if node.right: + queue.append((node.right, col + 1)) + + return [cols[c] for c in range(minCol, maxCol + 1)] +``` + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + public List> verticalOrder(TreeNode root) { + if (root == null) return new ArrayList<>(); + + Map> cols = new HashMap<>(); + Queue> queue = new LinkedList<>(); + queue.offer(new Pair<>(root, 0)); + int minCol = 0, maxCol = 0; + + while (!queue.isEmpty()) { + Pair p = queue.poll(); + TreeNode node = p.getKey(); + int col = p.getValue(); + + cols.computeIfAbsent(col, x -> new ArrayList<>()).add(node.val); + minCol = Math.min(minCol, col); + maxCol = Math.max(maxCol, col); + + if (node.left != null) queue.offer(new Pair<>(node.left, col - 1)); + if (node.right != null) queue.offer(new Pair<>(node.right, col + 1)); + } + + List> res = new ArrayList<>(); + for (int c = minCol; c <= maxCol; c++) { + res.add(cols.get(c)); + } + return res; + } +} +``` + +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector> verticalOrder(TreeNode* root) { + if (!root) return {}; + + unordered_map> cols; + queue> q; + q.push({root, 0}); + int minCol = 0, maxCol = 0; + + while (!q.empty()) { + auto [node, col] = q.front(); q.pop(); + cols[col].push_back(node->val); + minCol = min(minCol, col); + maxCol = max(maxCol, col); + + if (node->left) q.push({node->left, col - 1}); + if (node->right) q.push({node->right, col + 1}); + } + + vector> res; + for (int c = minCol; c <= maxCol; ++c) + res.push_back(cols[c]); + + return res; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + /** + * @param {TreeNode} root + * @return {number[][]} + */ + verticalOrder(root) { + if (!root) return []; + + const cols = new Map(); + const queue = new Queue([[root, 0]]); + let minCol = 0, maxCol = 0; + + while (!queue.isEmpty()) { + const [node, col] = queue.pop(); + if (!cols.has(col)) cols.set(col, []); + cols.get(col).push(node.val); + minCol = Math.min(minCol, col); + maxCol = Math.max(maxCol, col); + + if (node.left) queue.push([node.left, col - 1]); + if (node.right) queue.push([node.right, col + 1]); + } + + const res = []; + for (let c = minCol; c <= maxCol; c++) { + res.push(cols.get(c)); + } + return res; + } +} +``` + +```csharp +/** + * Definition for a binary tree node. + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + public IList> VerticalOrder(TreeNode root) { + if (root == null) return new List>(); + + Dictionary> cols = new(); + Queue<(TreeNode node, int col)> queue = new(); + queue.Enqueue((root, 0)); + int minCol = 0, maxCol = 0; + + while (queue.Count > 0) { + var (node, col) = queue.Dequeue(); + if (!cols.ContainsKey(col)) + cols[col] = new List(); + cols[col].Add(node.val); + minCol = Math.Min(minCol, col); + maxCol = Math.Max(maxCol, col); + + if (node.left != null) queue.Enqueue((node.left, col - 1)); + if (node.right != null) queue.Enqueue((node.right, col + 1)); + } + + var res = new List>(); + for (int c = minCol; c <= maxCol; c++) { + res.Add(cols[c]); + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. Depth First Search (Optimal) + +::tabs-start + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def verticalOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + if not root: + return [] + + cols = defaultdict(list) + minCol = maxCol = 0 + + def dfs(node, row, col): + nonlocal minCol, maxCol + if not node: + return + cols[col].append((row, node.val)) + minCol = min(minCol, col) + maxCol = max(maxCol, col) + dfs(node.left, row + 1, col - 1) + dfs(node.right, row + 1, col + 1) + + dfs(root, 0, 0) + + res = [] + for c in range(minCol, maxCol + 1): + # sort by row only + col_vals = sorted(cols[c], key=lambda x: x[0]) + res.append([val for _, val in col_vals]) + return res +``` + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + private Map> cols = new HashMap<>(); + private int minCol = 0, maxCol = 0; + + public List> verticalOrder(TreeNode root) { + if (root == null) return new ArrayList<>(); + dfs(root, 0, 0); + + List> res = new ArrayList<>(); + for (int c = minCol; c <= maxCol; c++) { + List list = cols.getOrDefault(c, new ArrayList<>()); + list.sort(Comparator.comparingInt(a -> a[0])); // sort by row + List colVals = new ArrayList<>(); + for (int[] p : list) colVals.add(p[1]); + res.add(colVals); + } + return res; + } + + private void dfs(TreeNode node, int row, int col) { + if (node == null) return; + cols.computeIfAbsent(col, k -> new ArrayList<>()).add(new int[]{row, node.val}); + minCol = Math.min(minCol, col); + maxCol = Math.max(maxCol, col); + dfs(node.left, row + 1, col - 1); + dfs(node.right, row + 1, col + 1); + } +} +``` + +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { + unordered_map>> cols; + int minCol = 0, maxCol = 0; + + void dfs(TreeNode* node, int row, int col) { + if (!node) return; + cols[col].emplace_back(row, node->val); + minCol = min(minCol, col); + maxCol = max(maxCol, col); + dfs(node->left, row + 1, col - 1); + dfs(node->right, row + 1, col + 1); + } + +public: + vector> verticalOrder(TreeNode* root) { + if (!root) return {}; + dfs(root, 0, 0); + vector> res; + + for (int c = minCol; c <= maxCol; ++c) { + auto& vec = cols[c]; + stable_sort(vec.begin(), vec.end(), + [](const pair& a, const pair& b) { + return a.first < b.first; // sort by row only + }); + vector colVals; + for (auto& [_, val] : vec) + colVals.push_back(val); + res.push_back(colVals); + } + + return res; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + /** + * @param {TreeNode} root + * @return {number[][]} + */ + verticalOrder(root) { + if (!root) return []; + + const cols = new Map(); + let minCol = 0, maxCol = 0; + + const dfs = (node, row, col) => { + if (!node) return; + if (!cols.has(col)) cols.set(col, []); + cols.get(col).push([row, node.val]); + minCol = Math.min(minCol, col); + maxCol = Math.max(maxCol, col); + dfs(node.left, row + 1, col - 1); + dfs(node.right, row + 1, col + 1); + }; + + dfs(root, 0, 0); + + const res = []; + for (let c = minCol; c <= maxCol; c++) { + let entries = cols.get(c) || []; + entries.sort((a, b) => a[0] - b[0]); // sort by row only + res.push(entries.map(([_, val]) => val)); + } + + return res; + } +} +``` + +```csharp +/** + * Definition for a binary tree node. + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + private Dictionary> cols = new(); + private int minCol = 0, maxCol = 0; + + public IList> VerticalOrder(TreeNode root) { + if (root == null) return new List>(); + DFS(root, 0, 0); + var res = new List>(); + + for (int c = minCol; c <= maxCol; c++) { + var list = cols.ContainsKey(c) ? cols[c] : new List<(int, int)>(); + list.Sort((a, b) => a.Item1.CompareTo(b.Item1)); // sort by row + res.Add(list.Select(p => p.Item2).ToList()); + } + + return res; + } + + private void DFS(TreeNode node, int row, int col) { + if (node == null) return; + if (!cols.ContainsKey(col)) cols[col] = new List<(int, int)>(); + cols[col].Add((row, node.val)); + minCol = Math.Min(minCol, col); + maxCol = Math.Max(maxCol, col); + DFS(node.left, row + 1, col - 1); + DFS(node.right, row + 1, col + 1); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(w * h \log h)$ +* Space complexity: $O(n)$ + +> Where $n$ is the number of nodes, $h$ is the height of the tree (i.e. maximum number of nodes in any vertical line of the tree), and $w$ is the width of the tree (i.e. maximum number of nodes in any of the levels of the tree). \ No newline at end of file diff --git a/articles/buildings-with-an-ocean-view.md b/articles/buildings-with-an-ocean-view.md new file mode 100644 index 000000000..9c418c11c --- /dev/null +++ b/articles/buildings-with-an-ocean-view.md @@ -0,0 +1,339 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def findBuildings(self, heights: List[int]) -> List[int]: + n = len(heights) + res = [] + + for i in range(n): + flag = True + for j in range(i + 1, n): + if heights[i] <= heights[j]: + flag = False + break + if flag: + res.append(i) + + return res +``` + +```java +public class Solution { + public int[] findBuildings(int[] heights) { + int n = heights.length; + List temp = new ArrayList<>(); + + for (int i = 0; i < n; i++) { + boolean flag = true; + for (int j = i + 1; j < n; j++) { + if (heights[i] <= heights[j]) { + flag = false; + break; + } + } + if (flag) temp.add(i); + } + + int[] res = new int[temp.size()]; + for (int i = 0; i < temp.size(); i++) { + res[i] = temp.get(i); + } + return res; + } +} +``` + +```cpp +class Solution { +public: + vector findBuildings(vector& heights) { + int n = heights.size(); + vector res; + + for (int i = 0; i < n; i++) { + bool flag = true; + for (int j = i + 1; j < n; j++) { + if (heights[i] <= heights[j]) { + flag = false; + break; + } + } + if (flag) res.push_back(i); + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} heights + * @return {number[]} + */ + findBuildings(heights) { + const n = heights.length; + const res = []; + + for (let i = 0; i < n; i++) { + let flag = true; + for (let j = i + 1; j < n; j++) { + if (heights[i] <= heights[j]) { + flag = false; + break; + } + } + if (flag) res.push(i); + } + + return res; + } +} +``` + +```csharp +public class Solution { + public int[] FindBuildings(int[] heights) { + int n = heights.Length; + List temp = new List(); + + for (int i = 0; i < n; i++) { + bool flag = true; + for (int j = i + 1; j < n; j++) { + if (heights[i] <= heights[j]) { + flag = false; + break; + } + } + if (flag) temp.Add(i); + } + + return temp.ToArray(); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n)$ for the output array. + +--- + +## 2. Monotonic Stack + +::tabs-start + +```python +class Solution: + def findBuildings(self, heights: List[int]) -> List[int]: + stack = [] + + for i, h in enumerate(heights): + while stack and heights[stack[-1]] <= h: + stack.pop() + stack.append(i) + + return stack +``` + +```java +public class Solution { + public int[] findBuildings(int[] heights) { + int n = heights.length; + Stack stack = new Stack<>(); + + for (int i = 0; i < n; i++) { + while (!stack.isEmpty() && heights[stack.peek()] <= heights[i]) { + stack.pop(); + } + stack.push(i); + } + + int[] res = new int[stack.size()]; + for (int i = stack.size() - 1; i >= 0; i--) { + res[i] = stack.get(i); + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + vector findBuildings(vector& heights) { + vector stack; + + for (int i = 0; i < heights.size(); i++) { + while (!stack.empty() && heights[stack.back()] <= heights[i]) { + stack.pop_back(); + } + stack.push_back(i); + } + + return stack; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} heights + * @return {number[]} + */ + findBuildings(heights) { + const stack = []; + + for (let i = 0; i < heights.length; i++) { + while (stack.length && heights[stack[stack.length - 1]] <= heights[i]) { + stack.pop(); + } + stack.push(i); + } + + return stack; + } +} +``` + +```csharp +public class Solution { + public int[] FindBuildings(int[] heights) { + List stack = new List(); + + for (int i = 0; i < heights.Length; i++) { + while (stack.Count > 0 && heights[stack[stack.Count - 1]] <= heights[i]) { + stack.RemoveAt(stack.Count - 1); + } + stack.Add(i); + } + + return stack.ToArray(); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Greedy + +::tabs-start + +```python +class Solution: + def findBuildings(self, heights: List[int]) -> List[int]: + res = [len(heights) - 1] + for i in range(len(heights) - 2, -1, -1): + if heights[i] > heights[res[-1]]: + res.append(i) + res.reverse() + return res +``` + +```java +public class Solution { + public int[] findBuildings(int[] heights) { + List res = new ArrayList<>(); + int n = heights.length; + res.add(n - 1); + + for (int i = n - 2; i >= 0; i--) { + if (heights[i] > heights[res.get(res.size() - 1)]) { + res.add(i); + } + } + + Collections.reverse(res); + int[] ans = new int[res.size()]; + for (int i = 0; i < res.size(); i++) { + ans[i] = res.get(i); + } + + return ans; + } +} +``` + +```cpp +class Solution { +public: + vector findBuildings(vector& heights) { + vector res; + int n = heights.size(); + res.push_back(n - 1); + + for (int i = n - 2; i >= 0; i--) { + if (heights[i] > heights[res.back()]) { + res.push_back(i); + } + } + + reverse(res.begin(), res.end()); + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} heights + * @return {number[]} + */ + findBuildings(heights) { + const n = heights.length; + const res = [n - 1]; + + for (let i = n - 2; i >= 0; i--) { + if (heights[i] > heights[res[res.length - 1]]) { + res.push(i); + } + } + + return res.reverse(); + } +} +``` + +```csharp +public class Solution { + public int[] FindBuildings(int[] heights) { + int n = heights.Length; + List res = new List { n - 1 }; + + for (int i = n - 2; i >= 0; i--) { + if (heights[i] > heights[res[res.Count - 1]]) { + res.Add(i); + } + } + + res.Reverse(); + return res.ToArray(); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ for the output array. \ No newline at end of file diff --git a/articles/valid-palindrome-ii.md b/articles/valid-palindrome-ii.md index 05367b687..6b1fbf303 100644 --- a/articles/valid-palindrome-ii.md +++ b/articles/valid-palindrome-ii.md @@ -119,6 +119,31 @@ class Solution { } ``` +```csharp +public class Solution { + public bool ValidPalindrome(string s) { + if (IsPalindrome(s)) return true; + + for (int i = 0; i < s.Length; i++) { + string newS = s.Substring(0, i) + s.Substring(i + 1); + if (IsPalindrome(newS)) return true; + } + + return false; + } + + private bool IsPalindrome(string str) { + int left = 0, right = str.Length - 1; + while (left < right) { + if (str[left] != str[right]) return false; + left++; + right--; + } + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -250,6 +275,36 @@ class Solution { } ``` +```csharp +public class Solution { + public bool ValidPalindrome(string s) { + int l = 0, r = s.Length - 1; + + while (l < r) { + if (s[l] != s[r]) { + string skipL = s.Substring(l + 1, r - l); + string skipR = s.Substring(l, r - l); + return IsPalindrome(skipL) || IsPalindrome(skipR); + } + l++; + r--; + } + + return true; + } + + private bool IsPalindrome(string str) { + int left = 0, right = str.Length - 1; + while (left < right) { + if (str[left] != str[right]) return false; + left++; + right--; + } + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -387,6 +442,32 @@ class Solution { } ``` +```csharp +public class Solution { + public bool ValidPalindrome(string s) { + bool IsPalindrome(int l, int r) { + while (l < r) { + if (s[l] != s[r]) return false; + l++; + r--; + } + return true; + } + + int left = 0, right = s.Length - 1; + while (left < right) { + if (s[left] != s[right]) { + return IsPalindrome(left + 1, right) || IsPalindrome(left, right - 1); + } + left++; + right--; + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/valid-word-abbreviation.md b/articles/valid-word-abbreviation.md new file mode 100644 index 000000000..79c44a2e7 --- /dev/null +++ b/articles/valid-word-abbreviation.md @@ -0,0 +1,163 @@ +## 1. Two Pointers + +::tabs-start + +```python +class Solution: + def validWordAbbreviation(self, word: str, abbr: str) -> bool: + n, m = len(word), len(abbr) + i = j = 0 + + while i < n and j < m: + if abbr[j] == '0': + return False + + if word[i] == abbr[j]: + i, j = i + 1, j + 1 + elif abbr[j].isalpha(): + return False + else: + subLen = 0 + while j < m and abbr[j].isdigit(): + subLen = subLen * 10 + int(abbr[j]) + j += 1 + i += subLen + + return i == n and j == m +``` + +```java +public class Solution { + public boolean validWordAbbreviation(String word, String abbr) { + int n = word.length(), m = abbr.length(); + int i = 0, j = 0; + + while (i < n && j < m) { + if (abbr.charAt(j) == '0') return false; + + if (Character.isLetter(abbr.charAt(j))) { + if (i < n && word.charAt(i) == abbr.charAt(j)) { + i++; + j++; + } else { + return false; + } + } else { + int subLen = 0; + while (j < m && Character.isDigit(abbr.charAt(j))) { + subLen = subLen * 10 + (abbr.charAt(j) - '0'); + j++; + } + i += subLen; + } + } + + return i == n && j == m; + } +} +``` + +```cpp +class Solution { +public: + bool validWordAbbreviation(string word, string abbr) { + int n = word.length(), m = abbr.length(); + int i = 0, j = 0; + + while (i < n && j < m) { + if (abbr[j] == '0') return false; + + if (isalpha(abbr[j])) { + if (word[i] == abbr[j]) { + i++; j++; + } else { + return false; + } + } else { + int subLen = 0; + while (j < m && isdigit(abbr[j])) { + subLen = subLen * 10 + (abbr[j] - '0'); + j++; + } + i += subLen; + } + } + + return i == n && j == m; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} word + * @param {string} abbr + * @return {boolean} + */ + validWordAbbreviation(word, abbr) { + let n = word.length, m = abbr.length; + let i = 0, j = 0; + + while (i < n && j < m) { + if (abbr[j] === '0') return false; + + if (isNaN(abbr[j])) { + if (word[i] === abbr[j]) { + i++; j++; + } else { + return false; + } + } else { + let subLen = 0; + while (j < m && !isNaN(abbr[j]) && abbr[j] !== ' ') { + subLen = subLen * 10 + parseInt(abbr[j]); + j++; + } + i += subLen; + } + } + + return i === n && j === m; + } +} +``` + +```csharp +public class Solution { + public bool ValidWordAbbreviation(string word, string abbr) { + int n = word.Length, m = abbr.Length; + int i = 0, j = 0; + + while (i < n && j < m) { + if (abbr[j] == '0') return false; + + if (char.IsLetter(abbr[j])) { + if (i < n && word[i] == abbr[j]) { + i++; j++; + } else { + return false; + } + } else { + int subLen = 0; + while (j < m && char.IsDigit(abbr[j])) { + subLen = subLen * 10 + (abbr[j] - '0'); + j++; + } + i += subLen; + } + } + + return i == n && j == m; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + m)$ +* Space complexity: $O(1)$ + +> Where $n$ and $m$ are the lengths of the strings $word$ and $abbr$, respectively. \ No newline at end of file