diff --git a/articles/4sum.md b/articles/4sum.md index f99c11ddd..b590cf39e 100644 --- a/articles/4sum.md +++ b/articles/4sum.md @@ -96,6 +96,35 @@ class Solution { } ``` +```csharp +public class Solution { + public List> FourSum(int[] nums, int target) { + int n = nums.Length; + Array.Sort(nums); + HashSet<(int, int, int, int)> res = new HashSet<(int, int, int, int)>(); + + for (int a = 0; a < n; a++) { + for (int b = a + 1; b < n; b++) { + for (int c = b + 1; c < n; c++) { + for (int d = c + 1; d < n; d++) { + long sum = (long)nums[a] + nums[b] + nums[c] + nums[d]; + if (sum == target) { + res.Add((nums[a], nums[b], nums[c], nums[d])); + } + } + } + } + } + + var result = new List>(); + foreach (var quad in res) { + result.Add(new List { quad.Item1, quad.Item2, quad.Item3, quad.Item4 }); + } + return result; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -287,6 +316,58 @@ class Solution { } ``` +```csharp +public class Solution { + public List> FourSum(int[] nums, int target) { + Array.Sort(nums); + Dictionary count = new Dictionary(); + + foreach (int num in nums) { + if (!count.ContainsKey(num)) { + count[num] = 0; + } + count[num]++; + } + + List> res = new List>(); + + for (int i = 0; i < nums.Length; i++) { + count[nums[i]]--; + if (i > 0 && nums[i] == nums[i - 1]) continue; + + for (int j = i + 1; j < nums.Length; j++) { + count[nums[j]]--; + if (j > i + 1 && nums[j] == nums[j - 1]) continue; + + for (int k = j + 1; k < nums.Length; k++) { + count[nums[k]]--; + if (k > j + 1 && nums[k] == nums[k - 1]) continue; + + long fourth = (long)target - (long)nums[i] - (long)nums[j] - (long)nums[k]; + if (fourth > int.MaxValue || fourth < int.MinValue) { + continue; + } + + if (count.ContainsKey((int)fourth) && count[(int)fourth] > 0) { + res.Add(new List { nums[i], nums[j], nums[k], (int)fourth }); + } + } + + for (int k = j + 1; k < nums.Length; k++) { + count[nums[k]]++; + } + } + + for (int j = i + 1; j < nums.Length; j++) { + count[nums[j]]++; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -448,6 +529,42 @@ class Solution { } ``` +```csharp +public class Solution { + public List> FourSum(int[] nums, int target) { + Array.Sort(nums); + List> res = new List>(); + int n = nums.Length; + + for (int i = 0; i < n; i++) { + if (i > 0 && nums[i] == nums[i - 1]) continue; + + for (int j = i + 1; j < n; j++) { + if (j > i + 1 && nums[j] == nums[j - 1]) continue; + + int left = j + 1, right = n - 1; + while (left < right) { + long sum = (long)nums[i] + nums[j] + nums[left] + nums[right]; + if (sum == target) { + res.Add(new List { nums[i], nums[j], nums[left], nums[right] }); + left++; + right--; + while (left < right && nums[left] == nums[left - 1]) left++; + while (left < right && nums[right] == nums[right + 1]) right--; + } else if (sum < target) { + left++; + } else { + right--; + } + } + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -637,6 +754,52 @@ class Solution { } ``` +```csharp +public class Solution { + private List> res; + private List quad; + + public List> FourSum(int[] nums, int target) { + Array.Sort(nums); + res = new List>(); + quad = new List(); + KSum(nums, 4, 0, target); + return res; + } + + private void KSum(int[] nums, int k, int start, long target) { + if (k == 2) { + int l = start, r = nums.Length - 1; + while (l < r) { + long sum = (long)nums[l] + nums[r]; + if (sum < target) { + l++; + } else if (sum > target) { + r--; + } else { + List newQuad = new List(quad); + newQuad.Add(nums[l]); + newQuad.Add(nums[r]); + res.Add(newQuad); + l++; + r--; + while (l < r && nums[l] == nums[l - 1]) l++; + while (l < r && nums[r] == nums[r + 1]) r--; + } + } + return; + } + + for (int i = start; i < nums.Length - k + 1; i++) { + if (i > start && nums[i] == nums[i - 1]) continue; + quad.Add(nums[i]); + KSum(nums, k - 1, i + 1, target - nums[i]); + quad.RemoveAt(quad.Count - 1); + } + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/accounts-merge.md b/articles/accounts-merge.md index 665334798..15b8e9881 100644 --- a/articles/accounts-merge.md +++ b/articles/accounts-merge.md @@ -284,6 +284,79 @@ class Solution { } ``` +```csharp +public class Solution { + private Dictionary emailIdx = new Dictionary(); + private List emails = new List(); + private List> adj; + private bool[] visited; + private Dictionary> components = new Dictionary>(); + private Dictionary componentName = new Dictionary(); + + public List> AccountsMerge(List> accounts) { + int m = 0; + + for (int accId = 0; accId < accounts.Count; accId++) { + var account = accounts[accId]; + for (int i = 1; i < account.Count; i++) { + string email = account[i]; + if (!emailIdx.ContainsKey(email)) { + emailIdx[email] = m++; + emails.Add(email); + } + } + } + + adj = new List>(); + for (int i = 0; i < m; i++) adj.Add(new List()); + + foreach (var account in accounts) { + for (int i = 2; i < account.Count; i++) { + int u = emailIdx[account[i - 1]]; + int v = emailIdx[account[i]]; + adj[u].Add(v); + adj[v].Add(u); + } + } + + visited = new bool[m]; + + foreach (var account in accounts) { + string name = account[0]; + foreach (var email in account.Skip(1)) { + int idx = emailIdx[email]; + if (!visited[idx]) { + components[idx] = new List(); + componentName[idx] = name; + Dfs(idx, idx); + } + } + } + + var res = new List>(); + foreach (var kvp in components) { + var group = kvp.Value; + group.Sort(StringComparer.Ordinal); + var merged = new List { componentName[kvp.Key] }; + merged.AddRange(group); + res.Add(merged); + } + + return res; + } + + private void Dfs(int node, int root) { + visited[node] = true; + components[root].Add(emails[node]); + foreach (int nei in adj[node]) { + if (!visited[nei]) { + Dfs(nei, root); + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -607,6 +680,85 @@ class Solution { } ``` +```csharp +public class Solution { + public List> AccountsMerge(List> accounts) { + int n = accounts.Count; + Dictionary emailIdx = new Dictionary(); + List emails = new List(); + Dictionary emailToAcc = new Dictionary(); + + int m = 0; + for (int accId = 0; accId < n; accId++) { + var account = accounts[accId]; + for (int i = 1; i < account.Count; i++) { + string email = account[i]; + if (!emailIdx.ContainsKey(email)) { + emailIdx[email] = m; + emails.Add(email); + emailToAcc[m] = accId; + m++; + } + } + } + + List> adj = new List>(); + for (int i = 0; i < m; i++) adj.Add(new List()); + + foreach (var account in accounts) { + for (int i = 2; i < account.Count; i++) { + int id1 = emailIdx[account[i]]; + int id2 = emailIdx[account[i - 1]]; + adj[id1].Add(id2); + adj[id2].Add(id1); + } + } + + Dictionary> emailGroup = new Dictionary>(); + bool[] visited = new bool[m]; + + void Bfs(int start, int accId) { + Queue queue = new Queue(); + queue.Enqueue(start); + visited[start] = true; + + if (!emailGroup.ContainsKey(accId)) + emailGroup[accId] = new List(); + + while (queue.Count > 0) { + int node = queue.Dequeue(); + emailGroup[accId].Add(emails[node]); + + foreach (int nei in adj[node]) { + if (!visited[nei]) { + visited[nei] = true; + queue.Enqueue(nei); + } + } + } + } + + for (int i = 0; i < m; i++) { + if (!visited[i]) { + Bfs(i, emailToAcc[i]); + } + } + + List> res = new List>(); + foreach (var kvp in emailGroup) { + int accId = kvp.Key; + string name = accounts[accId][0]; + List merged = new List { name }; + kvp.Value.Sort(StringComparer.Ordinal); + merged.AddRange(kvp.Value); + res.Add(merged); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -922,6 +1074,87 @@ class Solution { } ``` +```csharp +public class UnionFind { + private int[] parent; + private int[] rank; + + public UnionFind(int n) { + parent = new int[n]; + rank = new int[n]; + for (int i = 0; i < n; i++) { + parent[i] = i; + rank[i] = 1; + } + } + + public int Find(int x) { + if (x != parent[x]) { + parent[x] = Find(parent[x]); + } + return parent[x]; + } + + public bool Union(int x, int y) { + int rootX = Find(x); + int rootY = Find(y); + + if (rootX == rootY) return false; + + if (rank[rootX] > rank[rootY]) { + parent[rootY] = rootX; + rank[rootX] += rank[rootY]; + } else { + parent[rootX] = rootY; + rank[rootY] += rank[rootX]; + } + + return true; + } +} + +public class Solution { + public List> AccountsMerge(List> accounts) { + int n = accounts.Count; + UnionFind uf = new UnionFind(n); + Dictionary emailToAcc = new Dictionary(); + + for (int i = 0; i < n; i++) { + for (int j = 1; j < accounts[i].Count; j++) { + string email = accounts[i][j]; + if (emailToAcc.ContainsKey(email)) { + uf.Union(i, emailToAcc[email]); + } else { + emailToAcc[email] = i; + } + } + } + + Dictionary> emailGroup = new Dictionary>(); + foreach (var kvp in emailToAcc) { + string email = kvp.Key; + int leader = uf.Find(kvp.Value); + if (!emailGroup.ContainsKey(leader)) { + emailGroup[leader] = new List(); + } + emailGroup[leader].Add(email); + } + + List> res = new List>(); + foreach (var kvp in emailGroup) { + int accId = kvp.Key; + List emails = kvp.Value; + emails.Sort(StringComparer.Ordinal); + List merged = new List { accounts[accId][0] }; + merged.AddRange(emails); + res.Add(merged); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/add-two-numbers.md b/articles/add-two-numbers.md index 6225ac227..118adab49 100644 --- a/articles/add-two-numbers.md +++ b/articles/add-two-numbers.md @@ -303,6 +303,40 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + private func add(_ l1: ListNode?, _ l2: ListNode?, _ carry: Int) -> ListNode? { + if l1 == nil && l2 == nil && carry == 0 { + return nil + } + + let v1 = l1?.val ?? 0 + let v2 = l2?.val ?? 0 + + let sum = v1 + v2 + carry + let newCarry = sum / 10 + let val = sum % 10 + + let nextNode = add(l1?.next, l2?.next, newCarry) + return ListNode(val, nextNode) + } + + func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? { + return add(l1, l2, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -577,11 +611,49 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? { + let dummy = ListNode(0) + var cur = dummy + var l1 = l1, l2 = l2 + var carry = 0 + + while l1 != nil || l2 != nil || carry != 0 { + let v1 = l1?.val ?? 0 + let v2 = l2?.val ?? 0 + + let sum = v1 + v2 + carry + carry = sum / 10 + let val = sum % 10 + cur.next = ListNode(val) + + cur = cur.next! + l1 = l1?.next + l2 = l2?.next + } + return dummy.next + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(m + n)$ -* Space complexity: $O(1)$ +* Space complexity: + * $O(1)$ extra space. + * $O(max(m, n))$ for the output list. > Where $m$ is the length of $l1$ and $n$ is the length of $l2$. \ No newline at end of file diff --git a/articles/anagram-groups.md b/articles/anagram-groups.md index a0aae3216..bf41aaa79 100644 --- a/articles/anagram-groups.md +++ b/articles/anagram-groups.md @@ -125,6 +125,21 @@ class Solution { } ``` +```swift +class Solution { + func groupAnagrams(_ strs: [String]) -> [[String]] { + var res = [String: [String]]() + + for s in strs { + let sortedS = String(s.sorted()) + res[sortedS, default: []].append(s) + } + + return Array(res.values) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -277,11 +292,31 @@ class Solution { } ``` +```swift +class Solution { + func groupAnagrams(_ strs: [String]) -> [[String]] { + var res = [Array: [String]]() + + for s in strs { + var count = [Int](repeating: 0, count: 26) + for c in s { + count[Int(c.asciiValue!) - 97] += 1 + } + res[count, default: []].append(s) + } + + return Array(res.values) + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(m * n)$ -* Space complexity: $O(m)$ +* Space complexity: + * $O(m)$ extra space. + * $O(m * n)$ space for the output list. -> Where $m$ is the number of strings and $n$ is the length of the longest string. +> Where $m$ is the number of strings and $n$ is the length of the longest string. \ No newline at end of file diff --git a/articles/analyze-user-website-visit-pattern.md b/articles/analyze-user-website-visit-pattern.md new file mode 100644 index 000000000..c43fce6ba --- /dev/null +++ b/articles/analyze-user-website-visit-pattern.md @@ -0,0 +1,224 @@ +## 1. Hash Map + +::tabs-start + +```python +class Solution: + def mostVisitedPattern(self, username: List[str], timestamp: List[int], website: List[str]) -> List[str]: + arr = list(zip(timestamp, username, website)) + arr.sort() + + mp = defaultdict(list) + for time, user, site in arr: + mp[user].append(site) + + count = defaultdict(int) + for user in mp: + patterns = set() + cur = mp[user] + for i in range(len(cur)): + for j in range(i + 1, len(cur)): + for k in range(j + 1, len(cur)): + patterns.add((cur[i], cur[j], cur[k])) + for p in patterns: + count[p] += 1 + + max_count = 0 + res = tuple() + for pattern in count: + if count[pattern] > max_count or (count[pattern] == max_count and pattern < res): + max_count = count[pattern] + res = pattern + + return list(res) +``` + +```java +public class Solution { + public List mostVisitedPattern(String[] username, int[] timestamp, String[] website) { + int n = timestamp.length; + List arr = new ArrayList<>(); + for (int i = 0; i < n; i++) arr.add(new int[]{timestamp[i], i}); + arr.sort((a, b) -> Integer.compare(a[0], b[0])); + + Map> mp = new HashMap<>(); + for (int[] p : arr) { + int idx = p[1]; + mp.computeIfAbsent(username[idx], k -> new ArrayList<>()).add(website[idx]); + } + + Map count = new HashMap<>(); + for (String user : mp.keySet()) { + List cur = mp.get(user); + Set patterns = new HashSet<>(); + for (int i = 0; i < cur.size(); i++) + for (int j = i + 1; j < cur.size(); j++) + for (int k = j + 1; k < cur.size(); k++) + patterns.add(cur.get(i) + "#" + cur.get(j) + "#" + cur.get(k)); + for (String p : patterns) + count.put(p, count.getOrDefault(p, 0) + 1); + } + + String res = ""; + int max_count = 0; + for (String p : count.keySet()) { + int c = count.get(p); + if (c > max_count || (c == max_count && p.compareTo(res) < 0)) { + max_count = c; + res = p; + } + } + return Arrays.asList(res.split("#")); + } +} +``` + +```cpp +class Solution { +public: + vector mostVisitedPattern(vector& username, vector& timestamp, vector& website) { + int n = timestamp.size(); + vector> arr; + for (int i = 0; i < n; ++i) arr.push_back({timestamp[i], i}); + sort(arr.begin(), arr.end(), + [](auto& a, auto& b){ return a.first < b.first; }); + + unordered_map> mp; + for (auto& p : arr) mp[username[p.second]].push_back(website[p.second]); + + unordered_map count; + for (auto& kv : mp) { + auto& cur = kv.second; + unordered_set patterns; + for (int i = 0; i < (int)cur.size(); ++i) + for (int j = i + 1; j < (int)cur.size(); ++j) + for (int k = j + 1; k < (int)cur.size(); ++k) + patterns.insert(cur[i] + "#" + cur[j] + "#" + cur[k]); + for (auto& p : patterns) ++count[p]; + } + + int maxCnt = 0; + string res; + for (auto& kv : count) + if (kv.second > maxCnt || + (kv.second == maxCnt && (res.empty() || kv.first < res))) { + maxCnt = kv.second; + res = kv.first; + } + + vector ans; + string tmp; + for (char ch : res) { + if (ch == '#') { + ans.push_back(tmp); + tmp.clear(); + } else { + tmp += ch; + } + } + ans.push_back(tmp); + return ans; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string[]} username + * @param {number[]} timestamp + * @param {string[]} website + * @return {string[]} + */ + mostVisitedPattern(username, timestamp, website) { + const n = timestamp.length; + const arr = []; + for (let i = 0; i < n; i++) arr.push([timestamp[i], i]); + arr.sort((a, b) => a[0] - b[0]); + + const mp = new Map(); + for (const [, idx] of arr) { + const user = username[idx], site = website[idx]; + if (!mp.has(user)) mp.set(user, []); + mp.get(user).push(site); + } + + const count = new Map(); + for (const user of mp.keys()) { + const cur = mp.get(user); + const patterns = new Set(); + for (let i = 0; i < cur.length; i++) { + for (let j = i + 1; j < cur.length; j++) { + for (let k = j + 1; k < cur.length; k++) { + patterns.add(`${cur[i]}#${cur[j]}#${cur[k]}`); + } + } + } + for (const p of patterns) { + count.set(p, (count.get(p) || 0) + 1); + } + } + + let maxCnt = 0, res = ""; + for (const [pat, c] of count.entries()) { + if (c > maxCnt || (c === maxCnt && (res === "" || pat < res))) { + maxCnt = c; + res = pat; + } + } + return res.split("#"); + } +} +``` + +```csharp +public class Solution { + public List MostVisitedPattern(string[] username, int[] timestamp, string[] website) { + int n = timestamp.Length; + var arr = new List<(int t, int i)>(); + for (int i = 0; i < n; i++) arr.Add((timestamp[i], i)); + arr.Sort((a, b) => a.t.CompareTo(b.t)); + + var mp = new Dictionary>(); + foreach (var (t, idx) in arr) { + string user = username[idx], site = website[idx]; + if (!mp.ContainsKey(user)) mp[user] = new List(); + mp[user].Add(site); + } + + var count = new Dictionary(); + foreach (var kv in mp) { + var cur = kv.Value; + var patterns = new HashSet(); + for (int i = 0; i < cur.Count; i++) + for (int j = i + 1; j < cur.Count; j++) + for (int k = j + 1; k < cur.Count; k++) + patterns.Add($"{cur[i]}#{cur[j]}#{cur[k]}"); + foreach (var p in patterns) { + count[p] = count.ContainsKey(p) ? count[p] + 1 : 1; + } + } + + int maxCnt = 0; + string res = ""; + foreach (var kv in count) { + if (kv.Value > maxCnt || + (kv.Value == maxCnt && + (res == "" || string.Compare(kv.Key, res, StringComparison.Ordinal) < 0))) { + maxCnt = kv.Value; + res = kv.Key; + } + } + return new List(res.Split('#')); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n + n * u + n ^ 3 * w)$ +* Space complexity: $O(n * u + n ^ 3 * w)$ + +> Where $n$ is the size of the array $timestamp$, $u$ is the maximum length of any string in the array $username$, and $w$ is the maximum length of any string in the array $website$. \ No newline at end of file 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/asteroid-collision.md b/articles/asteroid-collision.md index e9634e9e8..94a5993d3 100644 --- a/articles/asteroid-collision.md +++ b/articles/asteroid-collision.md @@ -101,6 +101,35 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] AsteroidCollision(int[] asteroids) { + Stack stack = new Stack(); + + foreach (int a in asteroids) { + int current = a; + while (stack.Count > 0 && current < 0 && stack.Peek() > 0) { + int diff = current + stack.Peek(); + if (diff < 0) { + stack.Pop(); + } else if (diff > 0) { + current = 0; + } else { + current = 0; + stack.Pop(); + } + } + if (current != 0) { + stack.Push(current); + } + } + + int[] result = stack.Reverse().ToArray(); + return result; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -231,6 +260,40 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] AsteroidCollision(int[] asteroids) { + int n = asteroids.Length; + int j = -1; + + foreach (int a in asteroids) { + int current = a; + + while (j >= 0 && asteroids[j] > 0 && current < 0) { + if (asteroids[j] > Math.Abs(current)) { + current = 0; + break; + } else if (asteroids[j] == Math.Abs(current)) { + j--; + current = 0; + break; + } else { + j--; + } + } + + if (current != 0) { + asteroids[++j] = current; + } + } + + int[] result = new int[j + 1]; + Array.Copy(asteroids, 0, result, 0, j + 1); + return result; + } +} +``` + ::tabs-end ### Time & Space Complexity 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/balanced-binary-tree.md b/articles/balanced-binary-tree.md index c9c407ed0..21715bc6f 100644 --- a/articles/balanced-binary-tree.md +++ b/articles/balanced-binary-tree.md @@ -254,6 +254,43 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func isBalanced(_ root: TreeNode?) -> Bool { + guard let root = root else { return true } + + let left = height(root.left) + let right = height(root.right) + + if abs(left - right) > 1 { + return false + } + + return isBalanced(root.left) && isBalanced(root.right) + } + + private func height(_ root: TreeNode?) -> Int { + guard let root = root else { return 0 } + return 1 + max(height(root.left), height(root.right)) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -521,6 +558,39 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func isBalanced(_ root: TreeNode?) -> Bool { + return dfs(root).0 + } + + private func dfs(_ root: TreeNode?) -> (Bool, Int) { + guard let root = root else { return (true, 0) } + + let left = dfs(root.left) + let right = dfs(root.right) + + let balanced = left.0 && right.0 && abs(left.1 - right.1) <= 1 + return (balanced, 1 + max(left.1, right.1)) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -534,7 +604,7 @@ class Solution { --- -## 3. Depth First Search (Stack) +## 3. Iterative DFS ::tabs-start @@ -866,6 +936,58 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func isBalanced(_ root: TreeNode?) -> Bool { + var stack = [TreeNode]() + var node = root + var last: TreeNode? = nil + var depths = [ObjectIdentifier: Int]() + + while !stack.isEmpty || node != nil { + if let current = node { + stack.append(current) + node = current.left + } else { + guard let current = stack.last else { break } + if current.right == nil || last === current.right { + stack.removeLast() + + let leftDepth = current.left != nil ? depths[ObjectIdentifier(current.left!)] ?? 0 : 0 + let rightDepth = current.right != nil ? depths[ObjectIdentifier(current.right!)] ?? 0 : 0 + if abs(leftDepth - rightDepth) > 1 { + return false + } + + depths[ObjectIdentifier(current)] = 1 + max(leftDepth, rightDepth) + last = current + node = nil + } else { + node = current.right + } + } + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/baseball-game.md b/articles/baseball-game.md index 2d04f4311..ac8e53feb 100644 --- a/articles/baseball-game.md +++ b/articles/baseball-game.md @@ -1,4 +1,4 @@ -## 1. Stack +## 1. Stack - I ::tabs-start @@ -96,6 +96,36 @@ class Solution { } ``` +```csharp +public class Solution { + public int CalPoints(string[] operations) { + Stack stack = new Stack(); + + foreach (var op in operations) { + if (op == "+") { + int top = stack.Pop(); + int newTop = top + stack.Peek(); + stack.Push(top); + stack.Push(newTop); + } else if (op == "D") { + stack.Push(2 * stack.Peek()); + } else if (op == "C") { + stack.Pop(); + } else { + stack.Push(int.Parse(op)); + } + } + + int total = 0; + foreach (var val in stack) { + total += val; + } + + return total; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -215,6 +245,38 @@ class Solution { } ``` +```csharp +public class Solution { + public int CalPoints(string[] operations) { + Stack stack = new Stack(); + int res = 0; + + foreach (var op in operations) { + if (op == "+") { + int top = stack.Pop(); + int second = stack.Peek(); + int sum = top + second; + stack.Push(top); + stack.Push(sum); + res += sum; + } else if (op == "D") { + int doubleVal = 2 * stack.Peek(); + stack.Push(doubleVal); + res += doubleVal; + } else if (op == "C") { + res -= stack.Pop(); + } else { + int num = int.Parse(op); + stack.Push(num); + res += num; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/best-time-to-buy-and-sell-stock-ii.md b/articles/best-time-to-buy-and-sell-stock-ii.md index e6abb861a..6562e3544 100644 --- a/articles/best-time-to-buy-and-sell-stock-ii.md +++ b/articles/best-time-to-buy-and-sell-stock-ii.md @@ -85,6 +85,30 @@ class Solution { } ``` +```csharp +public class Solution { + public int MaxProfit(int[] prices) { + return Rec(prices, 0, false); + } + + private int Rec(int[] prices, int i, bool bought) { + if (i == prices.Length) { + return 0; + } + + int res = Rec(prices, i + 1, bought); + + if (bought) { + res = Math.Max(res, prices[i] + Rec(prices, i + 1, false)); + } else { + res = Math.Max(res, -prices[i] + Rec(prices, i + 1, true)); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -211,6 +235,43 @@ class Solution { } ``` +```csharp +public class Solution { + public int MaxProfit(int[] prices) { + int n = prices.Length; + int[,] dp = new int[n, 2]; + + for (int i = 0; i < n; i++) { + dp[i, 0] = -1; + dp[i, 1] = -1; + } + + return Rec(prices, 0, 0, dp); + } + + private int Rec(int[] prices, int i, int bought, int[,] dp) { + if (i == prices.Length) { + return 0; + } + + if (dp[i, bought] != -1) { + return dp[i, bought]; + } + + int res = Rec(prices, i + 1, bought, dp); + + if (bought == 1) { + res = Math.Max(res, prices[i] + Rec(prices, i + 1, 0, dp)); + } else { + res = Math.Max(res, -prices[i] + Rec(prices, i + 1, 1, dp)); + } + + dp[i, bought] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -290,6 +351,22 @@ class Solution { } ``` +```csharp +public class Solution { + public int MaxProfit(int[] prices) { + int n = prices.Length; + int[,] dp = new int[n + 1, 2]; + + for (int i = n - 1; i >= 0; i--) { + dp[i, 0] = Math.Max(dp[i + 1, 0], -prices[i] + dp[i + 1, 1]); + dp[i, 1] = Math.Max(dp[i + 1, 1], prices[i] + dp[i + 1, 0]); + } + + return dp[0, 0]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -378,6 +455,24 @@ class Solution { } ``` +```csharp +public class Solution { + public int MaxProfit(int[] prices) { + int nextBuy = 0, nextSell = 0; + int curBuy = 0, curSell = 0; + + for (int i = prices.Length - 1; i >= 0; i--) { + curBuy = Math.Max(nextBuy, -prices[i] + nextSell); + curSell = Math.Max(nextSell, prices[i] + nextBuy); + nextBuy = curBuy; + nextSell = curSell; + } + + return curBuy; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -450,6 +545,20 @@ class Solution { } ``` +```csharp +public class Solution { + public int MaxProfit(int[] prices) { + int profit = 0; + for (int i = 1; i < prices.Length; i++) { + if (prices[i] > prices[i - 1]) { + profit += prices[i] - prices[i - 1]; + } + } + return profit; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/binary-search.md b/articles/binary-search.md index 5e88782ce..59a970a26 100644 --- a/articles/binary-search.md +++ b/articles/binary-search.md @@ -139,6 +139,29 @@ class Solution { } ``` +```swift +class Solution { + func binarySearch(_ l: Int, _ r: Int, _ nums: [Int], _ target: Int) -> Int { + if l > r { + return -1 + } + let m = l + (r - l) / 2 + + if nums[m] == target { + return m + } + if nums[m] < target { + return binarySearch(m + 1, r, nums, target) + } + return binarySearch(l, m - 1, nums, target) + } + + func search(_ nums: [Int], _ target: Int) -> Int { + return binarySearch(0, nums.count - 1, nums, target) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -296,6 +319,28 @@ class Solution { } ``` +```swift +class Solution { + func search(_ nums: [Int], _ target: Int) -> Int { + var l = 0, r = nums.count - 1 + + while l <= r { + // (l + r) // 2 can lead to overflow + let m = l + (r - l) / 2 + + if nums[m] > target { + r = m - 1 + } else if nums[m] < target { + l = m + 1 + } else { + return m + } + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -439,6 +484,24 @@ class Solution { } ``` +```swift +class Solution { + func search(_ nums: [Int], _ target: Int) -> Int { + var l = 0, r = nums.count + + while l < r { + let m = l + (r - l) / 2 + if nums[m] > target { + r = m + } else { + l = m + 1 + } + } + return (l > 0 && nums[l - 1] == target) ? l - 1 : -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -582,6 +645,24 @@ class Solution { } ``` +```swift +class Solution { + func search(_ nums: [Int], _ target: Int) -> Int { + var l = 0, r = nums.count + + while l < r { + let m = l + (r - l) / 2 + if nums[m] >= target { + r = m + } else { + l = m + 1 + } + } + return (l < nums.count && nums[l] == target) ? l : -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -664,6 +745,15 @@ class Solution { } ``` +```swift +class Solution { + func search(_ nums: [Int], _ target: Int) -> Int { + let index = nums.partitioningIndex { $0 >= target } + return (index < nums.count && nums[index] == target) ? index : -1 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/binary-tree-diameter.md b/articles/binary-tree-diameter.md index 3c73fbe92..b11c3e40e 100644 --- a/articles/binary-tree-diameter.md +++ b/articles/binary-tree-diameter.md @@ -259,6 +259,41 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func diameterOfBinaryTree(_ root: TreeNode?) -> Int { + guard let root = root else { return 0 } + + let leftHeight = maxHeight(root.left) + let rightHeight = maxHeight(root.right) + let diameter = leftHeight + rightHeight + let sub = max(diameterOfBinaryTree(root.left), diameterOfBinaryTree(root.right)) + + return max(diameter, sub) + } + + private func maxHeight(_ root: TreeNode?) -> Int { + guard let root = root else { return 0 } + return 1 + max(maxHeight(root.left), maxHeight(root.right)) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -515,6 +550,40 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func diameterOfBinaryTree(_ root: TreeNode?) -> Int { + var res = 0 + + func dfs(_ root: TreeNode?) -> Int { + guard let root = root else { return 0 } + let left = dfs(root.left) + let right = dfs(root.right) + res = max(res, left + right) + return 1 + max(left, right) + } + + dfs(root) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -876,6 +945,49 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func diameterOfBinaryTree(_ root: TreeNode?) -> Int { + guard let root = root else { return 0 } + var stack: [TreeNode] = [root] + var mp = [ObjectIdentifier: (Int, Int)]() + + while !stack.isEmpty { + let node = stack.last! + if let left = node.left, mp[ObjectIdentifier(left)] == nil { + stack.append(left) + } else if let right = node.right, mp[ObjectIdentifier(right)] == nil { + stack.append(right) + } else { + let node = stack.removeLast() + let leftTuple = node.left != nil ? mp[ObjectIdentifier(node.left!)]! : (0, 0) + let rightTuple = node.right != nil ? mp[ObjectIdentifier(node.right!)]! : (0, 0) + let height = 1 + max(leftTuple.0, rightTuple.0) + let diameter = max(leftTuple.0 + rightTuple.0, leftTuple.1, rightTuple.1) + mp[ObjectIdentifier(node)] = (height, diameter) + } + } + + return mp[ObjectIdentifier(root)]!.1 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/binary-tree-from-preorder-and-inorder-traversal.md b/articles/binary-tree-from-preorder-and-inorder-traversal.md index 621fc91cd..b21106a35 100644 --- a/articles/binary-tree-from-preorder-and-inorder-traversal.md +++ b/articles/binary-tree-from-preorder-and-inorder-traversal.md @@ -235,6 +235,49 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? { + if preorder.isEmpty || inorder.isEmpty { + return nil + } + + let rootValue = preorder[0] + let root = TreeNode(rootValue) + guard let mid = inorder.firstIndex(of: rootValue) else { + return root + } + + root.left = buildTree( + Array(preorder[1..<(mid + 1)]), + Array(inorder[0.. TreeNode? { + for (index, value) in inorder.enumerated() { + indexMap[value] = index + } + return dfs(preorder, 0, inorder.count - 1) + } + + private func dfs(_ preorder: [Int], _ left: Int, _ right: Int) -> TreeNode? { + if left > right { + return nil + } + + let rootVal = preorder[preIndex] + preIndex += 1 + let root = TreeNode(rootVal) + let mid = indexMap[rootVal]! + + root.left = dfs(preorder, left, mid - 1) + root.right = dfs(preorder, mid + 1, right) + + return root + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -775,6 +863,48 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + var preIdx = 0 + var inIdx = 0 + + func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? { + return dfs(preorder, inorder, Int.max) + } + + private func dfs(_ preorder: [Int], _ inorder: [Int], _ limit: Int) -> TreeNode? { + if preIdx >= preorder.count { + return nil + } + if inorder[inIdx] == limit { + inIdx += 1 + return nil + } + + let root = TreeNode(preorder[preIdx]) + preIdx += 1 + root.left = dfs(preorder, inorder, root.val) + root.right = dfs(preorder, inorder, limit) + return root + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/binary-tree-inorder-traversal.md b/articles/binary-tree-inorder-traversal.md index 4735f8400..84e525d71 100644 --- a/articles/binary-tree-inorder-traversal.md +++ b/articles/binary-tree-inorder-traversal.md @@ -126,6 +126,35 @@ class Solution { } ``` +```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 List InorderTraversal(TreeNode root) { + List res = new List(); + void Inorder(TreeNode node) { + if (node == null) return; + Inorder(node.left); + res.Add(node.val); + Inorder(node.right); + } + Inorder(root); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -273,6 +302,41 @@ class Solution { } ``` +```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 InorderTraversal(TreeNode root) { + List res = new List(); + Stack stack = new Stack(); + TreeNode cur = root; + + while (cur != null || stack.Count > 0) { + while (cur != null) { + stack.Push(cur); + cur = cur.left; + } + cur = stack.Pop(); + res.Add(cur.val); + cur = cur.right; + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -457,6 +521,51 @@ class Solution { } ``` +```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 List InorderTraversal(TreeNode root) { + List res = new List(); + TreeNode cur = root; + + while (cur != null) { + if (cur.left == null) { + res.Add(cur.val); + cur = cur.right; + } else { + TreeNode prev = cur.left; + while (prev.right != null && prev.right != cur) { + prev = prev.right; + } + + if (prev.right == null) { + prev.right = cur; + cur = cur.left; + } else { + prev.right = null; + res.Add(cur.val); + cur = cur.right; + } + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/binary-tree-maximum-path-sum.md b/articles/binary-tree-maximum-path-sum.md index af442201a..ebd5467bc 100644 --- a/articles/binary-tree-maximum-path-sum.md +++ b/articles/binary-tree-maximum-path-sum.md @@ -290,6 +290,49 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + var res = Int.min + + func maxPathSum(_ root: TreeNode?) -> Int { + dfs(root) + return res + } + + private func dfs(_ root: TreeNode?) { + guard let node = root else { return } + let left = getMax(node.left) + let right = getMax(node.right) + res = max(res, node.val + left + right) + dfs(node.left) + dfs(node.right) + } + + private func getMax(_ root: TreeNode?) -> Int { + guard let node = root else { return 0 } + let left = getMax(node.left) + let right = getMax(node.right) + let path = node.val + max(left, right) + return max(0, path) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -560,6 +603,42 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func maxPathSum(_ root: TreeNode?) -> Int { + var res = root!.val + + func dfs(_ root: TreeNode?) -> Int { + guard let node = root else { return 0 } + + let leftMax = max(dfs(node.left), 0) + let rightMax = max(dfs(node.right), 0) + + res = max(res, node.val + leftMax + rightMax) + return node.val + max(leftMax, rightMax) + } + + dfs(root) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/binary-tree-postorder-traversal.md b/articles/binary-tree-postorder-traversal.md index 554c3006a..8853be764 100644 --- a/articles/binary-tree-postorder-traversal.md +++ b/articles/binary-tree-postorder-traversal.md @@ -126,6 +126,37 @@ class Solution { } ``` +```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 List PostorderTraversal(TreeNode root) { + List res = new List(); + + void Postorder(TreeNode node) { + if (node == null) return; + Postorder(node.left); + Postorder(node.right); + res.Add(node.val); + } + + Postorder(root); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -309,6 +340,52 @@ class Solution { } ``` +```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 List PostorderTraversal(TreeNode root) { + var stack = new Stack(); + var visit = new Stack(); + var res = new List(); + + stack.Push(root); + visit.Push(false); + + while (stack.Count > 0) { + var cur = stack.Pop(); + var v = visit.Pop(); + + if (cur != null) { + if (v) { + res.Add(cur.val); + } else { + stack.Push(cur); + visit.Push(true); + stack.Push(cur.right); + visit.Push(false); + stack.Push(cur.left); + visit.Push(false); + } + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -464,6 +541,43 @@ class Solution { } ``` +```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 List PostorderTraversal(TreeNode root) { + List res = new List(); + Stack stack = new Stack(); + TreeNode cur = root; + + while (cur != null || stack.Count > 0) { + if (cur != null) { + res.Add(cur.val); + stack.Push(cur); + cur = cur.right; + } else { + cur = stack.Pop(); + cur = cur.left; + } + } + + res.Reverse(); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -652,6 +766,52 @@ class Solution { } ``` +```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 List PostorderTraversal(TreeNode root) { + List res = new List(); + TreeNode cur = root; + + while (cur != null) { + if (cur.right == null) { + res.Add(cur.val); + cur = cur.left; + } else { + TreeNode prev = cur.right; + while (prev.left != null && prev.left != cur) { + prev = prev.left; + } + + if (prev.left == null) { + res.Add(cur.val); + prev.left = cur; + cur = cur.right; + } else { + prev.left = null; + cur = cur.left; + } + } + } + + res.Reverse(); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/binary-tree-preorder-traversal.md b/articles/binary-tree-preorder-traversal.md index fbcc8b4d6..f7f86ffb9 100644 --- a/articles/binary-tree-preorder-traversal.md +++ b/articles/binary-tree-preorder-traversal.md @@ -126,6 +126,37 @@ class Solution { } ``` +```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 List PreorderTraversal(TreeNode root) { + List res = new List(); + Preorder(root, res); + return res; + } + + private void Preorder(TreeNode node, List res) { + if (node == null) return; + + res.Add(node.val); + Preorder(node.left, res); + Preorder(node.right, res); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -274,6 +305,41 @@ class Solution { } ``` +```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 List PreorderTraversal(TreeNode root) { + List res = new List(); + Stack stack = new Stack(); + TreeNode cur = root; + + while (cur != null || stack.Count > 0) { + if (cur != null) { + res.Add(cur.val); + stack.Push(cur.right); + cur = cur.left; + } else { + cur = stack.Pop(); + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -458,6 +524,51 @@ class Solution { } ``` +```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 List PreorderTraversal(TreeNode root) { + List res = new List(); + TreeNode cur = root; + + while (cur != null) { + if (cur.left == null) { + res.Add(cur.val); + cur = cur.right; + } else { + TreeNode prev = cur.left; + while (prev.right != null && prev.right != cur) { + prev = prev.right; + } + + if (prev.right == null) { + res.Add(cur.val); + prev.right = cur; + cur = cur.left; + } else { + prev.right = null; + cur = cur.right; + } + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/binary-tree-right-side-view.md b/articles/binary-tree-right-side-view.md index e17b22299..4d8a68b19 100644 --- a/articles/binary-tree-right-side-view.md +++ b/articles/binary-tree-right-side-view.md @@ -236,6 +236,42 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func rightSideView(_ root: TreeNode?) -> [Int] { + var res = [Int]() + + func dfs(_ node: TreeNode?, _ depth: Int) { + guard let node = node else { return } + if depth == res.count { + res.append(node.val) + } + + dfs(node.right, depth + 1) + dfs(node.left, depth + 1) + } + + dfs(root, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -530,6 +566,48 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func rightSideView(_ root: TreeNode?) -> [Int] { + var res = [Int]() + var q = Deque() + q.append(root) + + while !q.isEmpty { + var rightSide: TreeNode? + let qLen = q.count + + for _ in 0.. 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 List> 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 List> 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 List> 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 List> 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/boats-to-save-people.md b/articles/boats-to-save-people.md index 8abd6a9a7..ce0498e89 100644 --- a/articles/boats-to-save-people.md +++ b/articles/boats-to-save-people.md @@ -73,6 +73,27 @@ class Solution { } ``` +```csharp +public class Solution { + public int NumRescueBoats(int[] people, int limit) { + Array.Sort(people); + int res = 0, l = 0, r = people.Length - 1; + + while (l <= r) { + int remain = limit - people[r]; + r--; + res++; + + if (l <= r && remain >= people[l]) { + l++; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -211,6 +232,44 @@ class Solution { } ``` +```csharp +public class Solution { + public int NumRescueBoats(int[] people, int limit) { + int m = 0; + foreach (int p in people) { + m = Math.Max(m, p); + } + + int[] count = new int[m + 1]; + foreach (int p in people) { + count[p]++; + } + + int idx = 0, iVal = 1; + while (idx < people.Length) { + while (count[iVal] == 0) { + iVal++; + } + people[idx] = iVal; + count[iVal]--; + idx++; + } + + int res = 0, l = 0, r = people.Length - 1; + while (l <= r) { + int remain = limit - people[r]; + r--; + res++; + if (l <= r && remain >= people[l]) { + l++; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity 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/burst-balloons.md b/articles/burst-balloons.md index 3febbdd81..a52c66027 100644 --- a/articles/burst-balloons.md +++ b/articles/burst-balloons.md @@ -189,6 +189,30 @@ class Solution { } ``` +```swift +class Solution { + func maxCoins(_ nums: [Int]) -> Int { + var nums = [1] + nums + [1] + + func dfs(_ nums: [Int]) -> Int { + if nums.count == 2 { + return 0 + } + + var maxCoins = 0 + for i in 1..<(nums.count - 1) { + let coins = nums[i - 1] * nums[i] * nums[i + 1] + + dfs(Array(nums[.. Int { + var nums = [1] + nums + [1] + let n = nums.count + var dp = Array(repeating: Array(repeating: -1, count: n), count: n) + + func dfs(_ l: Int, _ r: Int) -> Int { + if l > r { + return 0 + } + if dp[l][r] != -1 { + return dp[l][r] + } + + dp[l][r] = 0 + for i in l...r { + let coins = nums[l - 1] * nums[i] * nums[r + 1] + dfs(l, i - 1) + dfs(i + 1, r) + dp[l][r] = max(dp[l][r], coins) + } + return dp[l][r] + } + + return dfs(1, n - 2) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -621,6 +673,29 @@ class Solution { } ``` +```swift +class Solution { + func maxCoins(_ nums: [Int]) -> Int { + let n = nums.count + var newNums = [1] + nums + [1] + + var dp = Array(repeating: Array(repeating: 0, count: n + 2), count: n + 2) + + for l in stride(from: n, through: 1, by: -1) { + for r in l...n { + for i in l...r { + let coins = (newNums[l - 1] * newNums[i] * newNums[r + 1]) + + dp[l][i - 1] + dp[i + 1][r] + dp[l][r] = max(dp[l][r], coins) + } + } + } + + return dp[1][n] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/buy-and-sell-crypto-with-cooldown.md b/articles/buy-and-sell-crypto-with-cooldown.md index 366028454..9c4ae550b 100644 --- a/articles/buy-and-sell-crypto-with-cooldown.md +++ b/articles/buy-and-sell-crypto-with-cooldown.md @@ -171,6 +171,31 @@ class Solution { } ``` +```swift +class Solution { + func maxProfit(_ prices: [Int]) -> Int { + let n = prices.count + + func dfs(_ i: Int, _ buying: Bool) -> Int { + if i >= n { + return 0 + } + + let cooldown = dfs(i + 1, buying) + if buying { + let buy = dfs(i + 1, false) - prices[i] + return max(buy, cooldown) + } else { + let sell = dfs(i + 2, true) + prices[i] + return max(sell, cooldown) + } + } + + return dfs(0, true) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -412,6 +437,36 @@ class Solution { } ``` +```swift +class Solution { + func maxProfit(_ prices: [Int]) -> Int { + let n = prices.count + var dp = [[Int?]](repeating: [Int?](repeating: nil, count: 2), count: n) + + func dfs(_ i: Int, _ buying: Int) -> Int { + if i >= n { + return 0 + } + if let cached = dp[i][buying] { + return cached + } + + let cooldown = dfs(i + 1, buying) + if buying == 1 { + let buy = dfs(i + 1, 0) - prices[i] + dp[i][buying] = max(buy, cooldown) + } else { + let sell = dfs(i + 2, 1) + prices[i] + dp[i][buying] = max(sell, cooldown) + } + return dp[i][buying]! + } + + return dfs(0, 1) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -611,6 +666,31 @@ class Solution { } ``` +```swift +class Solution { + func maxProfit(_ prices: [Int]) -> Int { + let n = prices.count + var dp = Array(repeating: [0, 0], count: n + 1) + + for i in stride(from: n - 1, through: 0, by: -1) { + for buying in 0...1 { + if buying == 1 { + let buy = (i + 1 < n ? dp[i + 1][0] - prices[i] : -prices[i]) + let cooldown = (i + 1 < n ? dp[i + 1][1] : 0) + dp[i][1] = max(buy, cooldown) + } else { + let sell = (i + 2 < n ? dp[i + 2][1] + prices[i] : prices[i]) + let cooldown = (i + 1 < n ? dp[i + 1][0] : 0) + dp[i][0] = max(sell, cooldown) + } + } + } + + return dp[0][1] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -769,6 +849,26 @@ class Solution { } ``` +```swift +class Solution { + func maxProfit(_ prices: [Int]) -> Int { + let n = prices.count + var dp1Buy = 0, dp1Sell = 0 + var dp2Buy = 0 + + for i in stride(from: n - 1, through: 0, by: -1) { + let dpBuy = max(dp1Sell - prices[i], dp1Buy) + let dpSell = max(dp2Buy + prices[i], dp1Sell) + dp2Buy = dp1Buy + dp1Buy = dpBuy + dp1Sell = dpSell + } + + return dp1Buy + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/buy-and-sell-crypto.md b/articles/buy-and-sell-crypto.md index 0e618efd5..b983fd272 100644 --- a/articles/buy-and-sell-crypto.md +++ b/articles/buy-and-sell-crypto.md @@ -120,6 +120,22 @@ class Solution { } ``` +```swift +class Solution { + func maxProfit(_ prices: [Int]) -> Int { + var res = 0 + for i in 0.. Int { + var l = 0, r = 1 + var maxP = 0 + + while r < prices.count { + if prices[l] < prices[r] { + let profit = prices[r] - prices[l] + maxP = max(maxP, profit) + } else { + l = r + } + r += 1 + } + return maxP + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -397,6 +433,21 @@ class Solution { } ``` +```swift +class Solution { + func maxProfit(_ prices: [Int]) -> Int { + var maxP = 0 + var minBuy = prices[0] + + for sell in prices { + maxP = max(maxP, sell - minBuy) + minBuy = min(minBuy, sell) + } + return maxP + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/capacity-to-ship-packages-within-d-days.md b/articles/capacity-to-ship-packages-within-d-days.md index 9a5d4e777..dfc4f2146 100644 --- a/articles/capacity-to-ship-packages-within-d-days.md +++ b/articles/capacity-to-ship-packages-within-d-days.md @@ -97,6 +97,29 @@ class Solution { } ``` +```csharp +public class Solution { + public int ShipWithinDays(int[] weights, int days) { + int res = weights.Max(); + while (true) { + int ships = 1; + int cap = res; + foreach (int w in weights) { + if (cap - w < 0) { + ships++; + cap = res; + } + cap -= w; + } + if (ships <= days) { + return res; + } + res++; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -258,6 +281,44 @@ class Solution { } ``` +```csharp +public class Solution { + public int ShipWithinDays(int[] weights, int days) { + int l = weights.Max(); + int r = weights.Sum(); + int res = r; + + bool CanShip(int cap) { + int ships = 1; + int currCap = cap; + + foreach (int w in weights) { + if (currCap - w < 0) { + ships++; + if (ships > days) return false; + currCap = cap; + } + currCap -= w; + } + + return true; + } + + while (l <= r) { + int cap = (l + r) / 2; + if (CanShip(cap)) { + res = Math.Min(res, cap); + r = cap - 1; + } else { + l = cap + 1; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/car-fleet.md b/articles/car-fleet.md index 2d4e2ef35..22c7a9d0f 100644 --- a/articles/car-fleet.md +++ b/articles/car-fleet.md @@ -150,6 +150,26 @@ class Solution { } ``` +```swift +class Solution { + func carFleet(_ target: Int, _ position: [Int], _ speed: [Int]) -> Int { + var pair = zip(position, speed).map { ($0, $1) } + pair.sort { $0.0 > $1.0 } // Sort in descending order by position + + var stack = [Double]() + + for (p, s) in pair { + stack.append(Double(target - p) / Double(s)) + if stack.count >= 2 && stack.last! <= stack[stack.count - 2] { + stack.removeLast() + } + } + + return stack.count + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -327,6 +347,30 @@ class Solution { } ``` +```swift +class Solution { + func carFleet(_ target: Int, _ position: [Int], _ speed: [Int]) -> Int { + var pair = zip(position, speed).map { ($0, $1) } + pair.sort { $0.0 > $1.0 } // Sort in descending order by position + + var fleets = 1 + var prevTime = Double(target - pair[0].0) / Double(pair[0].1) + + for i in 1.. prevTime { + fleets += 1 + prevTime = currTime + } + } + + return fleets + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/car-pooling.md b/articles/car-pooling.md index 3eac0695d..df5745d6d 100644 --- a/articles/car-pooling.md +++ b/articles/car-pooling.md @@ -92,6 +92,28 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CarPooling(int[][] trips, int capacity) { + Array.Sort(trips, (a, b) => a[1].CompareTo(b[1])); + + for (int i = 0; i < trips.Length; i++) { + int curPass = trips[i][0]; + for (int j = 0; j < i; j++) { + if (trips[j][2] > trips[i][1]) { + curPass += trips[j][0]; + } + } + if (curPass > capacity) { + return false; + } + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -196,12 +218,12 @@ class Solution { carPooling(trips, capacity) { trips.sort((a, b) => a[1] - b[1]); - const minHeap = new MinPriorityQueue({ priority: x => x[0] }); // [end, numPassengers] + const minHeap = new MinPriorityQueue(x => x[0]); // [end, numPassengers] let curPass = 0; for (const [numPass, start, end] of trips) { - while (!minHeap.isEmpty() && minHeap.front().element[0] <= start) { - curPass -= minHeap.dequeue().element[1]; + while (!minHeap.isEmpty() && minHeap.front()[0] <= start) { + curPass -= minHeap.dequeue()[1]; } curPass += numPass; @@ -217,6 +239,36 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CarPooling(int[][] trips, int capacity) { + Array.Sort(trips, (a, b) => a[1].CompareTo(b[1])); + + var minHeap = new PriorityQueue(); + int curPass = 0; + + foreach (var trip in trips) { + int numPass = trip[0]; + int start = trip[1]; + int end = trip[2]; + + while (minHeap.Count > 0 && minHeap.Peek()[0] <= start) { + curPass -= minHeap.Dequeue()[1]; + } + + curPass += numPass; + if (curPass > capacity) { + return false; + } + + minHeap.Enqueue(new int[] { end, numPass }, end); + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -330,6 +382,36 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CarPooling(int[][] trips, int capacity) { + List points = new List(); + + foreach (var trip in trips) { + int passengers = trip[0]; + int start = trip[1]; + int end = trip[2]; + + points.Add(new int[] { start, passengers }); + points.Add(new int[] { end, -passengers }); + } + + points.Sort((a, b) => { + if (a[0] == b[0]) return a[1] - b[1]; + return a[0] - b[0]; + }); + + int curPass = 0; + foreach (var point in points) { + curPass += point[1]; + if (curPass > capacity) return false; + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -459,6 +541,40 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CarPooling(int[][] trips, int capacity) { + int L = int.MaxValue, R = int.MinValue; + + foreach (var trip in trips) { + int start = trip[1], end = trip[2]; + L = Math.Min(L, start); + R = Math.Max(R, end); + } + + int N = R - L + 1; + int[] passChange = new int[N + 1]; + + foreach (var trip in trips) { + int passengers = trip[0]; + int start = trip[1]; + int end = trip[2]; + + passChange[start - L] += passengers; + passChange[end - L] -= passengers; + } + + int curPass = 0; + foreach (int change in passChange) { + curPass += change; + if (curPass > capacity) return false; + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/cheapest-flight-path.md b/articles/cheapest-flight-path.md index 6c23351be..976640249 100644 --- a/articles/cheapest-flight-path.md +++ b/articles/cheapest-flight-path.md @@ -258,6 +258,53 @@ class Solution { } ``` +```swift +struct Item: Comparable { + let cost: Int + let node: Int + let stops: Int + + static func < (lhs: Item, rhs: Item) -> Bool { + return lhs.cost < rhs.cost + } +} + +class Solution { + func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ k: Int) -> Int { + let INF = Int.max + var adj = Array(repeating: [(Int, Int)](), count: n) + var dist = Array(repeating: Array(repeating: INF, count: k + 5), count: n) + + for flight in flights { + let u = flight[0], v = flight[1], cst = flight[2] + adj[u].append((v, cst)) + } + + var minHeap = Heap() + minHeap.insert(Item(cost: 0, node: src, stops: -1)) + dist[src][0] = 0 + + while !minHeap.isEmpty { + let item = minHeap.removeMin() + let cst = item.cost, node = item.node, stops = item.stops + if node == dst { return cst } + if stops == k || dist[node][stops + 1] < cst { continue } + + for (nei, w) in adj[node] { + let nextCst = cst + w + let nextStops = stops + 1 + if dist[nei][nextStops + 1] > nextCst { + dist[nei][nextStops + 1] = nextCst + minHeap.insert(Item(cost: nextCst, node: nei, stops: nextStops)) + } + } + } + + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -471,6 +518,31 @@ class Solution { } ``` +```swift +class Solution { + func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ k: Int) -> Int { + var prices = Array(repeating: Int.max, count: n) + prices[src] = 0 + + for _ in 0...k { + var tmpPrices = prices + + for flight in flights { + let s = flight[0], d = flight[1], p = flight[2] + if prices[s] == Int.max { + continue + } + if prices[s] + p < tmpPrices[d] { + tmpPrices[d] = prices[s] + p + } + } + prices = tmpPrices + } + return prices[dst] == Int.max ? -1 : prices[dst] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -727,6 +799,41 @@ class Solution { } ``` +```swift +class Solution { + func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ k: Int) -> Int { + var prices = Array(repeating: Int.max, count: n) + prices[src] = 0 + var adj = Array(repeating: [(Int, Int)](), count: n) + + for flight in flights { + let u = flight[0], v = flight[1], cst = flight[2] + adj[u].append((v, cst)) + } + + var queue = Deque<(Int, Int, Int)>() + queue.append((0, src, 0)) + + while !queue.isEmpty { + let (cst, node, stops) = queue.popFirst()! + if stops > k { + continue + } + + for (nei, w) in adj[node] { + let nextCost = cst + w + if nextCost < prices[nei] { + prices[nei] = nextCost + queue.append((nextCost, nei, stops + 1)) + } + } + } + + return prices[dst] == Int.max ? -1 : prices[dst] + } +} +``` + ::tabs-end ### Time & Space Complexity 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/climbing-stairs.md b/articles/climbing-stairs.md index a1a70e0fa..126511582 100644 --- a/articles/climbing-stairs.md +++ b/articles/climbing-stairs.md @@ -99,6 +99,21 @@ class Solution { } ``` +```swift +class Solution { + func climbStairs(_ n: Int) -> Int { + func dfs(_ i: Int) -> Int { + if i >= n { + return i == n ? 1 : 0 + } + return dfs(i + 1) + dfs(i + 2) + } + + return dfs(0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -240,6 +255,27 @@ class Solution { } ``` +```swift +class Solution { + func climbStairs(_ n: Int) -> Int { + var cache = Array(repeating: -1, count: n) + + func dfs(_ i: Int) -> Int { + if i >= n { + return i == n ? 1 : 0 + } + if cache[i] != -1 { + return cache[i] + } + cache[i] = dfs(i + 1) + dfs(i + 2) + return cache[i] + } + + return dfs(0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -368,6 +404,23 @@ class Solution { } ``` +```swift +class Solution { + func climbStairs(_ n: Int) -> Int { + if n <= 2 { + return n + } + var dp = Array(repeating: 0, count: n + 1) + dp[1] = 1 + dp[2] = 2 + for i in 3...n { + dp[i] = dp[i - 1] + dp[i - 2] + } + return dp[n] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -495,6 +548,22 @@ class Solution { } ``` +```swift +class Solution { + func climbStairs(_ n: Int) -> Int { + var one = 1, two = 1 + + for _ in 0..<(n - 1) { + let temp = one + one = one + two + two = temp + } + + return one + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -764,6 +833,45 @@ class Solution { } ``` +```swift +class Solution { + func climbStairs(_ n: Int) -> Int { + if n == 1 { + return 1 + } + + func matrixMult(_ A: [[Int]], _ B: [[Int]]) -> [[Int]] { + return [ + [A[0][0] * B[0][0] + A[0][1] * B[1][0], + A[0][0] * B[0][1] + A[0][1] * B[1][1]], + [A[1][0] * B[0][0] + A[1][1] * B[1][0], + A[1][0] * B[0][1] + A[1][1] * B[1][1]] + ] + } + + func matrixPow(_ M: [[Int]], _ p: Int) -> [[Int]] { + var result = [[1, 0], [0, 1]] + var base = M + var power = p + + while power > 0 { + if power % 2 == 1 { + result = matrixMult(result, base) + } + base = matrixMult(base, base) + power /= 2 + } + + return result + } + + let M = [[1, 1], [1, 0]] + let result = matrixPow(M, n) + return result[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -865,6 +973,18 @@ class Solution { } ``` +```swift +class Solution { + func climbStairs(_ n: Int) -> Int { + let sqrt5 = sqrt(5.0) + let phi = (1.0 + sqrt5) / 2.0 + let psi = (1.0 - sqrt5) / 2.0 + let n = n + 1 + return Int(round((pow(phi, Double(n)) - pow(psi, Double(n))) / sqrt5)) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/clone-graph.md b/articles/clone-graph.md index ff2612c4c..e71e55184 100644 --- a/articles/clone-graph.md +++ b/articles/clone-graph.md @@ -290,6 +290,47 @@ class Solution { } ``` +```swift +/** + * Definition for a Node. + * public class Node { + * public var val: Int + * public var neighbors: [Node?] + * public init(_ val: Int) { + * self.val = val + * self.neighbors = [] + * } + * } + */ + +class Solution { + func cloneGraph(_ node: Node?) -> Node? { + var oldToNew = [Node: Node]() + + func dfs(_ node: Node?) -> Node? { + guard let node = node else { return nil } + + if let existingCopy = oldToNew[node] { + return existingCopy + } + + let copy = Node(node.val) + oldToNew[node] = copy + + for neighbor in node.neighbors { + if let clonedNeighbor = dfs(neighbor) { + copy.neighbors.append(clonedNeighbor) + } + } + + return copy + } + + return dfs(node) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -582,6 +623,49 @@ class Solution { } ``` +```swift +/** + * Definition for a Node. + * public class Node { + * public var val: Int + * public var neighbors: [Node?] + * public init(_ val: Int) { + * self.val = val + * self.neighbors = [] + * } + * } + */ + +class Solution { + func cloneGraph(_ node: Node?) -> Node? { + if node == nil { + return nil + } + + var oldToNew: [Node: Node] = [:] + let newNode = Node(node!.val) + oldToNew[node!] = newNode + var queue = Deque() + queue.append(node!) + + while !queue.isEmpty { + let cur = queue.popFirst()! + for nei in cur.neighbors { + if let nei = nei { + if oldToNew[nei] == nil { + oldToNew[nei] = Node(nei.val) + queue.append(nei) + } + oldToNew[cur]!.neighbors.append(oldToNew[nei]!) + } + } + } + + return oldToNew[node!] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/coin-change-ii.md b/articles/coin-change-ii.md index cdfd83983..6e4cce788 100644 --- a/articles/coin-change-ii.md +++ b/articles/coin-change-ii.md @@ -178,6 +178,32 @@ class Solution { } ``` +```swift +class Solution { + func change(_ amount: Int, _ coins: [Int]) -> Int { + let coins = coins.sorted() + + func dfs(_ i: Int, _ a: Int) -> Int { + if a == 0 { + return 1 + } + if i >= coins.count { + return 0 + } + + var res = 0 + if a >= coins[i] { + res = dfs(i + 1, a) + res += dfs(i, a - coins[i]) + } + return res + } + + return dfs(0, amount) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -399,6 +425,38 @@ class Solution { } ``` +```swift +class Solution { + func change(_ amount: Int, _ coins: [Int]) -> Int { + let coins = coins.sorted() + var memo = Array(repeating: Array(repeating: -1, count: amount + 1), count: coins.count + 1) + + func dfs(_ i: Int, _ a: Int) -> Int { + if a == 0 { + return 1 + } + if i >= coins.count { + return 0 + } + if memo[i][a] != -1 { + return memo[i][a] + } + + var res = 0 + if a >= coins[i] { + res = dfs(i + 1, a) + res += dfs(i, a - coins[i]) + } + + memo[i][a] = res + return res + } + + return dfs(0, amount) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -464,8 +522,8 @@ public: int change(int amount, vector& coins) { int n = coins.size(); sort(coins.begin(), coins.end()); - vector> dp(n + 1, vector(amount + 1, 0)); - + vector> dp(n + 1, vector(amount + 1, 0)); + for (int i = 0; i <= n; i++) { dp[i][0] = 1; } @@ -592,6 +650,41 @@ class Solution { } ``` +```swift +class Solution { + func change(_ amount: Int, _ coins: [Int]) -> Int { + let n = coins.count + let sortedCoins = coins.sorted() + var dp = Array( + repeating: Array(repeating: 0, count: amount + 1), + count: n + 1 + ) + + for i in 0...n { + dp[i][0] = 1 + } + + for i in stride(from: n - 1, through: 0, by: -1) { + for a in 0...amount { + let base = dp[i + 1][a] + if a >= sortedCoins[i] { + let addend = dp[i][a - sortedCoins[i]] + if base > Int.max - addend { + dp[i][a] = 0 + } else { + dp[i][a] = base + addend + } + } else { + dp[i][a] = base + } + } + } + + return dp[0][amount] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -650,10 +743,10 @@ public class Solution { class Solution { public: int change(int amount, vector& coins) { - vector dp(amount + 1, 0); + vector dp(amount + 1, 0); dp[0] = 1; for (int i = coins.size() - 1; i >= 0; i--) { - vector nextDP(amount + 1, 0); + vector nextDP(amount + 1, 0); nextDP[0] = 1; for (int a = 1; a <= amount; a++) { @@ -764,6 +857,36 @@ class Solution { } ``` +```swift +class Solution { + func change(_ amount: Int, _ coins: [Int]) -> Int { + var dp = [Int](repeating: 0, count: amount + 1) + dp[0] = 1 + + for i in stride(from: coins.count - 1, through: 0, by: -1) { + var nextDP = [Int](repeating: 0, count: amount + 1) + nextDP[0] = 1 + + for a in 1..<(amount + 1) { + nextDP[a] = dp[a] + if a - coins[i] >= 0 { + let addend = nextDP[a - coins[i]] + if nextDP[a] > Int.max - addend { + nextDP[a] = 0 + } else { + nextDP[a] += addend + } + } + } + + dp = nextDP + } + + return dp[amount] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -807,7 +930,7 @@ public class Solution { class Solution { public: int change(int amount, vector& coins) { - vector dp(amount + 1, 0); + vector dp(amount + 1, 0); dp[0] = 1; for (int i = coins.size() - 1; i >= 0; i--) { for (int a = 1; a <= amount; a++) { @@ -890,6 +1013,30 @@ class Solution { } ``` +```swift +class Solution { + func change(_ amount: Int, _ coins: [Int]) -> Int { + var dp = [Int](repeating: 0, count: amount + 1) + dp[0] = 1 + + for i in stride(from: coins.count - 1, through: 0, by: -1) { + for a in 1..<(amount + 1) { + if coins[i] <= a { + let addend = dp[a - coins[i]] + if dp[a] > Int.max - addend { + dp[a] = 0 + } else { + dp[a] += addend + } + } + } + } + + return dp[amount] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/coin-change.md b/articles/coin-change.md index eb1f7e715..f61f99922 100644 --- a/articles/coin-change.md +++ b/articles/coin-change.md @@ -170,6 +170,29 @@ class Solution { } ``` +```swift +class Solution { + func coinChange(_ coins: [Int], _ amount: Int) -> Int { + func dfs(_ amount: Int) -> Int { + if amount == 0 { + return 0 + } + + var res = Int(1e9) + for coin in coins { + if amount - coin >= 0 { + res = min(res, 1 + dfs(amount - coin)) + } + } + return res + } + + let minCoins = dfs(amount) + return minCoins >= Int(1e9) ? -1 : minCoins + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -393,6 +416,36 @@ class Solution { } ``` +```swift +class Solution { + func coinChange(_ coins: [Int], _ amount: Int) -> Int { + var memo = [Int: Int]() + + func dfs(_ amount: Int) -> Int { + if amount == 0 { + return 0 + } + if let cached = memo[amount] { + return cached + } + + var res = Int(1e9) + for coin in coins { + if amount - coin >= 0 { + res = min(res, 1 + dfs(amount - coin)) + } + } + + memo[amount] = res + return res + } + + let minCoins = dfs(amount) + return minCoins >= Int(1e9) ? -1 : minCoins + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -542,6 +595,29 @@ class Solution { } ``` +```swift +class Solution { + func coinChange(_ coins: [Int], _ amount: Int) -> Int { + if amount == 0 { + return 0 + } + + var dp = [Int](repeating: amount + 1, count: amount + 1) + dp[0] = 0 + + for a in 1...amount { + for coin in coins { + if a - coin >= 0 { + dp[a] = min(dp[a], 1 + dp[a - coin]) + } + } + } + + return dp[amount] == amount + 1 ? -1 : dp[amount] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -772,6 +848,41 @@ class Solution { } ``` +```swift +class Solution { + func coinChange(_ coins: [Int], _ amount: Int) -> Int { + if amount == 0 { + return 0 + } + + var q = Deque([0]) + var seen = Array(repeating: false, count: amount + 1) + seen[0] = true + var res = 0 + + while !q.isEmpty { + res += 1 + for _ in 0.. amount || seen[nxt] { + continue + } + seen[nxt] = true + q.append(nxt) + } + } + } + + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/combination-sum-iv.md b/articles/combination-sum-iv.md index 3a607251c..b2d2c5386 100644 --- a/articles/combination-sum-iv.md +++ b/articles/combination-sum-iv.md @@ -97,6 +97,31 @@ class Solution { } ``` +```csharp +public class Solution { + public int CombinationSum4(int[] nums, int target) { + Array.Sort(nums); + return Dfs(nums, target); + } + + private int Dfs(int[] nums, int total) { + if (total == 0) { + return 1; + } + + int res = 0; + foreach (int num in nums) { + if (total < num) { + break; + } + res += Dfs(nums, total - num); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -222,6 +247,36 @@ class Solution { } ``` +```csharp +public class Solution { + private Dictionary memo; + + public int CombinationSum4(int[] nums, int target) { + Array.Sort(nums); + memo = new Dictionary(); + memo[0] = 1; + return Dfs(nums, target); + } + + private int Dfs(int[] nums, int total) { + if (memo.ContainsKey(total)) { + return memo[total]; + } + + int res = 0; + foreach (int num in nums) { + if (total < num) { + break; + } + res += Dfs(nums, total - num); + } + + memo[total] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -310,6 +365,26 @@ class Solution { } ``` +```csharp +public class Solution { + public int CombinationSum4(int[] nums, int target) { + Dictionary dp = new Dictionary(); + dp[0] = 1; + + for (int total = 1; total <= target; total++) { + dp[total] = 0; + foreach (int num in nums) { + if (dp.ContainsKey(total - num)) { + dp[total] += dp[total - num]; + } + } + } + + return dp[target]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -403,6 +478,30 @@ class Solution { } ``` +```csharp +public class Solution { + public int CombinationSum4(int[] nums, int target) { + Array.Sort(nums); + Dictionary dp = new Dictionary(); + dp[target] = 1; + + for (int total = target; total > 0; total--) { + if (!dp.ContainsKey(total)) continue; + foreach (int num in nums) { + if (total < num) break; + int key = total - num; + if (!dp.ContainsKey(key)) { + dp[key] = 0; + } + dp[key] += dp[total]; + } + } + + return dp.ContainsKey(0) ? dp[0] : 0; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/combination-target-sum-ii.md b/articles/combination-target-sum-ii.md index 0c9a90f24..3b35aab6d 100644 --- a/articles/combination-target-sum-ii.md +++ b/articles/combination-target-sum-ii.md @@ -216,6 +216,35 @@ class Solution { } ``` +```swift +class Solution { + func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] { + var res = Set<[Int]>() + let sortedCandidates = candidates.sorted() + + func generateSubsets(_ i: Int, _ cur: inout [Int], _ total: Int) { + if total == target { + res.insert(cur) + return + } + if total > target || i == sortedCandidates.count { + return + } + + cur.append(sortedCandidates[i]) + generateSubsets(i + 1, &cur, total + sortedCandidates[i]) + cur.removeLast() + + generateSubsets(i + 1, &cur, total) + } + + var cur: [Int] = [] + generateSubsets(0, &cur, 0) + return Array(res) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -464,6 +493,39 @@ class Solution { } ``` +```swift +class Solution { + func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] { + var res = [[Int]]() + let sortedCandidates = candidates.sorted() + + func dfs(_ i: Int, _ cur: inout [Int], _ total: Int) { + if total == target { + res.append(cur) + return + } + if total > target || i == sortedCandidates.count { + return + } + + cur.append(sortedCandidates[i]) + dfs(i + 1, &cur, total + sortedCandidates[i]) + cur.removeLast() + + var j = i + while j + 1 < sortedCandidates.count && sortedCandidates[j] == sortedCandidates[j + 1] { + j += 1 + } + dfs(j + 1, &cur, total) + } + + var cur: [Int] = [] + dfs(0, &cur, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -772,6 +834,47 @@ class Solution { } ``` +```swift +class Solution { + func combinationSum2(_ nums: [Int], _ target: Int) -> [[Int]] { + var res = [[Int]]() + var count = [Int: Int]() + var uniqueNums = [Int]() + + for num in nums { + if count[num] == nil { + uniqueNums.append(num) + } + count[num, default: 0] += 1 + } + + func backtrack(_ nums: [Int], _ target: Int, _ cur: inout [Int], _ i: Int) { + if target == 0 { + res.append(cur) + return + } + if target < 0 || i >= nums.count { + return + } + + if count[nums[i], default: 0] > 0 { + cur.append(nums[i]) + count[nums[i], default: 0] -= 1 + backtrack(nums, target - nums[i], &cur, i) + count[nums[i], default: 0] += 1 + cur.removeLast() + } + + backtrack(nums, target, &cur, i + 1) + } + + var cur: [Int] = [] + backtrack(uniqueNums, target, &cur, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1008,6 +1111,39 @@ class Solution { } ``` +```swift +class Solution { + func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] { + var res = [[Int]]() + let sortedCandidates = candidates.sorted() + + func dfs(_ idx: Int, _ path: inout [Int], _ cur: Int) { + if cur == target { + res.append(path) + return + } + + for i in idx.. idx && sortedCandidates[i] == sortedCandidates[i - 1] { + continue + } + if cur + sortedCandidates[i] > target { + break + } + + path.append(sortedCandidates[i]) + dfs(i + 1, &path, cur + sortedCandidates[i]) + path.removeLast() + } + } + + var path: [Int] = [] + dfs(0, &path, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/combination-target-sum.md b/articles/combination-target-sum.md index 43a9f3cd1..46436ad64 100644 --- a/articles/combination-target-sum.md +++ b/articles/combination-target-sum.md @@ -194,6 +194,33 @@ class Solution { } ``` +```swift +class Solution { + func combinationSum(_ nums: [Int], _ target: Int) -> [[Int]] { + var res: [[Int]] = [] + + func dfs(_ i: Int, _ cur: inout [Int], _ total: Int) { + if total == target { + res.append(cur) + return + } + if i >= nums.count || total > target { + return + } + + cur.append(nums[i]) + dfs(i, &cur, total + nums[i]) + cur.removeLast() + dfs(i + 1, &cur, total) + } + + var cur: [Int] = [] + dfs(0, &cur, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -406,6 +433,35 @@ class Solution { } ``` +```swift +class Solution { + func combinationSum(_ nums: [Int], _ target: Int) -> [[Int]] { + var res: [[Int]] = [] + let sortedNums = nums.sorted() + + func dfs(_ i: Int, _ cur: inout [Int], _ total: Int) { + if total == target { + res.append(cur) + return + } + + for j in i.. target { + return + } + cur.append(sortedNums[j]) + dfs(j, &cur, total + sortedNums[j]) + cur.removeLast() + } + } + + var cur: [Int] = [] + dfs(0, &cur, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/combinations-of-a-phone-number.md b/articles/combinations-of-a-phone-number.md index 941f7ebf6..51796e3f7 100644 --- a/articles/combinations-of-a-phone-number.md +++ b/articles/combinations-of-a-phone-number.md @@ -1,4 +1,4 @@ -## 1. Bactracking +## 1. Backtracking ::tabs-start @@ -212,12 +212,45 @@ class Solution { } ``` +```swift +class Solution { + func letterCombinations(_ digits: String) -> [String] { + guard !digits.isEmpty else { return [] } + + let digitToChar: [Character: String] = [ + "2": "abc", "3": "def", "4": "ghi", "5": "jkl", + "6": "mno", "7": "pqrs", "8": "tuv", "9": "wxyz" + ] + + var res = [String]() + let digitsArray = Array(digits) + + func backtrack(_ i: Int, _ curStr: String) { + if curStr.count == digits.count { + res.append(curStr) + return + } + if let letters = digitToChar[digitsArray[i]] { + for c in letters { + backtrack(i + 1, curStr + String(c)) + } + } + } + + backtrack(0, "") + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * 4 ^ n)$ -* Space complexity: $O(n)$ +* Space complexity: + * $O(n)$ extra space. + * $O(n * 4 ^ n)$ space for the output list. --- @@ -429,9 +462,39 @@ class Solution { } ``` +```swift +class Solution { + func letterCombinations(_ digits: String) -> [String] { + guard !digits.isEmpty else { return [] } + + let digitToChar: [Character: String] = [ + "2": "abc", "3": "def", "4": "ghi", "5": "jkl", + "6": "mno", "7": "pqrs", "8": "tuv", "9": "wxyz" + ] + + var res = [""] + + for digit in digits { + guard let letters = digitToChar[digit] else { continue } + var tmp = [String]() + for curStr in res { + for c in letters { + tmp.append(curStr + String(c)) + } + } + res = tmp + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * 4 ^ n)$ -* Space complexity: $O(n)$ \ No newline at end of file +* Space complexity: + * $O(n)$ extra space. + * $O(n * 4 ^ n)$ space for the output list. diff --git a/articles/combinations.md b/articles/combinations.md index d5e838baf..321ffeab1 100644 --- a/articles/combinations.md +++ b/articles/combinations.md @@ -105,6 +105,31 @@ class Solution { } ``` +```csharp +public class Solution { + public List> Combine(int n, int k) { + List> res = new List>(); + + void Backtrack(int i, List comb) { + if (i > n) { + if (comb.Count == k) { + res.Add(new List(comb)); + } + return; + } + + comb.Add(i); + Backtrack(i + 1, comb); + comb.RemoveAt(comb.Count - 1); + Backtrack(i + 1, comb); + } + + Backtrack(1, new List()); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -220,6 +245,30 @@ class Solution { } ``` +```csharp +public class Solution { + public List> Combine(int n, int k) { + List> res = new List>(); + + void Backtrack(int start, List comb) { + if (comb.Count == k) { + res.Add(new List(comb)); + return; + } + + for (int i = start; i <= n; i++) { + comb.Add(i); + Backtrack(i + 1, comb); + comb.RemoveAt(comb.Count - 1); + } + } + + Backtrack(1, new List()); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -348,6 +397,33 @@ class Solution { } ``` +```csharp +public class Solution { + public List> Combine(int n, int k) { + List> res = new List>(); + int[] comb = new int[k]; + int i = 0; + + while (i >= 0) { + comb[i]++; + if (comb[i] > n) { + i--; + continue; + } + + if (i == k - 1) { + res.Add(new List(comb)); + } else { + i++; + comb[i] = comb[i - 1]; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -446,6 +522,28 @@ class Solution { } ``` +```csharp +public class Solution { + public List> Combine(int n, int k) { + List> res = new List>(); + + for (int mask = 0; mask < (1 << n); mask++) { + List comb = new List(); + for (int bit = 0; bit < n; bit++) { + if ((mask & (1 << bit)) != 0) { + comb.Add(bit + 1); + } + } + if (comb.Count == k) { + res.Add(comb); + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/concatenation-of-array.md b/articles/concatenation-of-array.md index 3ea2a1e68..f3740ed68 100644 --- a/articles/concatenation-of-array.md +++ b/articles/concatenation-of-array.md @@ -15,7 +15,7 @@ class Solution: ```java public class Solution { public int[] getConcatenation(int[] nums) { - int[] ans=new int[2 * nums.length]; + int[] ans = new int[2 * nums.length]; int idx = 0; for (int i = 0; i < 2; i++) { for (int num : nums) { @@ -60,6 +60,21 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] GetConcatenation(int[] nums) { + int[] ans = new int[2 * nums.Length]; + int idx = 0; + for (int i = 0; i < 2; i++) { + foreach (int num in nums) { + ans[idx++] = num; + } + } + return ans; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -127,6 +142,19 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] GetConcatenation(int[] nums) { + int n = nums.Length; + int[] ans = new int[2 * n]; + for (int i = 0; i < n; i++) { + ans[i] = ans[i + n] = nums[i]; + } + return ans; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/construct-quad-tree.md b/articles/construct-quad-tree.md index 48e117a86..5e2b91594 100644 --- a/articles/construct-quad-tree.md +++ b/articles/construct-quad-tree.md @@ -237,6 +237,76 @@ class Solution { } ``` +```csharp +/* +// Definition for a QuadTree node. +public class Node { + public bool val; + public bool isLeaf; + public Node topLeft; + public Node topRight; + public Node bottomLeft; + public Node bottomRight; + + public Node() { + val = false; + isLeaf = false; + topLeft = null; + topRight = null; + bottomLeft = null; + bottomRight = null; + } + + public Node(bool _val, bool _isLeaf) { + val = _val; + isLeaf = _isLeaf; + topLeft = null; + topRight = null; + bottomLeft = null; + bottomRight = null; + } + + public Node(bool _val,bool _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) { + val = _val; + isLeaf = _isLeaf; + topLeft = _topLeft; + topRight = _topRight; + bottomLeft = _bottomLeft; + bottomRight = _bottomRight; + } +} +*/ + +public class Solution { + public Node Construct(int[][] grid) { + return Dfs(grid, grid.Length, 0, 0); + } + + private Node Dfs(int[][] grid, int n, int r, int c) { + bool allSame = true; + for (int i = 0; i < n && allSame; i++) { + for (int j = 0; j < n && allSame; j++) { + if (grid[r][c] != grid[r + i][c + j]) { + allSame = false; + } + } + } + + if (allSame) { + return new Node(grid[r][c] == 1, true); + } + + int half = n / 2; + Node topLeft = Dfs(grid, half, r, c); + Node topRight = Dfs(grid, half, r, c + half); + Node bottomLeft = Dfs(grid, half, r + half, c); + Node bottomRight = Dfs(grid, half, r + half, c + half); + + return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -475,6 +545,75 @@ class Solution { } ``` +```csharp +/* +// Definition for a QuadTree node. +public class Node { + public bool val; + public bool isLeaf; + public Node topLeft; + public Node topRight; + public Node bottomLeft; + public Node bottomRight; + + public Node() { + val = false; + isLeaf = false; + topLeft = null; + topRight = null; + bottomLeft = null; + bottomRight = null; + } + + public Node(bool _val, bool _isLeaf) { + val = _val; + isLeaf = _isLeaf; + topLeft = null; + topRight = null; + bottomLeft = null; + bottomRight = null; + } + + public Node(bool _val,bool _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) { + val = _val; + isLeaf = _isLeaf; + topLeft = _topLeft; + topRight = _topRight; + bottomLeft = _bottomLeft; + bottomRight = _bottomRight; + } +} +*/ + +public class Solution { + public Node Construct(int[][] grid) { + return Dfs(grid, grid.Length, 0, 0); + } + + private Node Dfs(int[][] grid, int n, int r, int c) { + if (n == 1) { + return new Node(grid[r][c] == 1, true); + } + + int mid = n / 2; + Node topLeft = Dfs(grid, mid, r, c); + Node topRight = Dfs(grid, mid, r, c + mid); + Node bottomLeft = Dfs(grid, mid, r + mid, c); + Node bottomRight = Dfs(grid, mid, r + mid, c + mid); + + if (topLeft.isLeaf && topRight.isLeaf && + bottomLeft.isLeaf && bottomRight.isLeaf && + topLeft.val == topRight.val && + topRight.val == bottomLeft.val && + bottomLeft.val == bottomRight.val) { + return new Node(topLeft.val, true); + } + + return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -725,6 +864,79 @@ class Solution { } ``` +```csharp +/* +// Definition for a QuadTree node. +public class Node { + public bool val; + public bool isLeaf; + public Node topLeft; + public Node topRight; + public Node bottomLeft; + public Node bottomRight; + + public Node() { + val = false; + isLeaf = false; + topLeft = null; + topRight = null; + bottomLeft = null; + bottomRight = null; + } + + public Node(bool _val, bool _isLeaf) { + val = _val; + isLeaf = _isLeaf; + topLeft = null; + topRight = null; + bottomLeft = null; + bottomRight = null; + } + + public Node(bool _val,bool _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) { + val = _val; + isLeaf = _isLeaf; + topLeft = _topLeft; + topRight = _topRight; + bottomLeft = _bottomLeft; + bottomRight = _bottomRight; + } +} +*/ + +public class Solution { + private readonly Node falseLeaf = new Node(false, true); + private readonly Node trueLeaf = new Node(true, true); + + public Node Construct(int[][] grid) { + int n = grid.Length; + return Dfs(grid, n, 0, 0); + } + + private Node Dfs(int[][] grid, int n, int r, int c) { + if (n == 1) { + return grid[r][c] == 1 ? trueLeaf : falseLeaf; + } + + int half = n / 2; + Node topLeft = Dfs(grid, half, r, c); + Node topRight = Dfs(grid, half, r, c + half); + Node bottomLeft = Dfs(grid, half, r + half, c); + Node bottomRight = Dfs(grid, half, r + half, c + half); + + if (topLeft.isLeaf && topRight.isLeaf && + bottomLeft.isLeaf && bottomRight.isLeaf && + topLeft.val == topRight.val && + topLeft.val == bottomLeft.val && + topLeft.val == bottomRight.val) { + return topLeft; + } + + return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/contains-duplicate-ii.md b/articles/contains-duplicate-ii.md index 9e1c9367e..cc98d9da1 100644 --- a/articles/contains-duplicate-ii.md +++ b/articles/contains-duplicate-ii.md @@ -63,6 +63,21 @@ class Solution { } ``` +```csharp +public class Solution { + public bool ContainsNearbyDuplicate(int[] nums, int k) { + for (int L = 0; L < nums.Length; L++) { + for (int R = L + 1; R < Math.Min(nums.Length, L + k + 1); R++) { + if (nums[L] == nums[R]) { + return true; + } + } + } + return false; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -148,6 +163,23 @@ class Solution { } ``` +```csharp +public class Solution { + public bool ContainsNearbyDuplicate(int[] nums, int k) { + Dictionary mp = new Dictionary(); + + for (int i = 0; i < nums.Length; i++) { + if (mp.ContainsKey(nums[i]) && i - mp[nums[i]] <= k) { + return true; + } + mp[nums[i]] = i; + } + + return false; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -249,6 +281,28 @@ class Solution { } ``` +```csharp +public class Solution { + public bool ContainsNearbyDuplicate(int[] nums, int k) { + HashSet window = new HashSet(); + int L = 0; + + for (int R = 0; R < nums.Length; R++) { + if (R - L > k) { + window.Remove(nums[L]); + L++; + } + if (window.Contains(nums[R])) { + return true; + } + window.Add(nums[R]); + } + + return false; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/copy-linked-list-with-random-pointer.md b/articles/copy-linked-list-with-random-pointer.md index 2c8acaed9..0b595bf64 100644 --- a/articles/copy-linked-list-with-random-pointer.md +++ b/articles/copy-linked-list-with-random-pointer.md @@ -1,4 +1,4 @@ -## 1. Hash Map (Recursion) +## 1. Recursion + Hash Map ::tabs-start @@ -223,6 +223,44 @@ class Solution { } ``` +```swift +/** + * Definition for a Node. + * public class Node { + * public var val: Int + * public var next: Node? + * public var random: Node? + * public init(_ val: Int) { + * self.val = val + * self.next = nil + * self.random = nil + * } + * } + */ + +class Solution { + private var map = [Node: Node]() + + func copyRandomList(_ head: Node?) -> Node? { + if head == nil { + return nil + } + + if let copied = map[head!] { + return copied + } + + let copy = Node(head!.val) + map[head!] = copy + + copy.next = copyRandomList(head!.next) + copy.random = copyRandomList(head!.random) + + return copy + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -494,6 +532,45 @@ class Solution { } ``` +```swift +/** + * Definition for a Node. + * public class Node { + * public var val: Int + * public var next: Node? + * public var random: Node? + * public init(_ val: Int) { + * self.val = val + * self.next = nil + * self.random = nil + * } + * } + */ + +class Solution { + func copyRandomList(_ head: Node?) -> Node? { + var oldToCopy: [Node?: Node?] = [nil: nil] + + var cur = head + while cur != nil { + let copy = Node(cur!.val) + oldToCopy[cur] = copy + cur = cur?.next + } + + cur = head + while cur != nil { + let copy = oldToCopy[cur]! + copy?.next = oldToCopy[cur?.next]! + copy?.random = oldToCopy[cur?.random]! + cur = cur?.next + } + + return oldToCopy[head]! + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -789,6 +866,46 @@ class Solution { } ``` +```swift +/** + * Definition for a Node. + * public class Node { + * public var val: Int + * public var next: Node? + * public var random: Node? + * public init(_ val: Int) { + * self.val = val + * self.next = nil + * self.random = nil + * } + * } + */ + +class Solution { + func copyRandomList(_ head: Node?) -> Node? { + var oldToCopy = [Node?: Node?]() + + func getNode(_ node: Node?) -> Node? { + if node == nil { return nil } + if oldToCopy[node] == nil { + oldToCopy[node] = Node(0) + } + return oldToCopy[node]! + } + + var cur = head + while cur != nil { + getNode(cur)!.val = cur!.val + getNode(cur)!.next = getNode(cur!.next) + getNode(cur)!.random = getNode(cur!.random) + cur = cur!.next + } + + return getNode(head) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1161,12 +1278,67 @@ class Solution { } ``` +```swift +/** + * Definition for a Node. + * public class Node { + * public var val: Int + * public var next: Node? + * public var random: Node? + * public init(_ val: Int) { + * self.val = val + * self.next = nil + * self.random = nil + * } + * } + */ + +class Solution { + func copyRandomList(_ head: Node?) -> Node? { + if head == nil { + return nil + } + + var l1 = head + while l1 != nil { + let l2 = Node(l1!.val) + l2.next = l1?.next + l1?.next = l2 + l1 = l2.next + } + + let newHead = head?.next + l1 = head + while l1 != nil { + if let random = l1?.random { + l1?.next?.random = random.next + } + l1 = l1?.next?.next + } + + l1 = head + while l1 != nil { + let l2 = l1?.next + l1?.next = l2?.next + if l2?.next != nil { + l2?.next = l2?.next?.next + } + l1 = l1?.next + } + + return newHead + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ for the output. --- @@ -1525,9 +1697,62 @@ class Solution { } ``` +```swift +/** + * Definition for a Node. + * public class Node { + * public var val: Int + * public var next: Node? + * public var random: Node? + * public init(_ val: Int) { + * self.val = val + * self.next = nil + * self.random = nil + * } + * } + */ + +class Solution { + func copyRandomList(_ head: Node?) -> Node? { + if head == nil { + return nil + } + + var l1 = head + while l1 != nil { + let l2 = Node(l1!.val) + l2.next = l1?.random + l1?.random = l2 + l1 = l1?.next + } + + let newHead = head?.random + + l1 = head + while l1 != nil { + let l2 = l1?.random + l2?.random = l2?.next?.random + l1 = l1?.next + } + + l1 = head + while l1 != nil { + let l2 = l1?.random + l1?.random = l2?.next + l2?.next = l1?.next?.random + l1 = l1?.next + } + + return newHead + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ \ No newline at end of file +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ for the output. \ No newline at end of file diff --git a/articles/count-connected-components.md b/articles/count-connected-components.md index 0f0dc28ba..c31580864 100644 --- a/articles/count-connected-components.md +++ b/articles/count-connected-components.md @@ -229,6 +229,41 @@ class Solution { } ``` +```swift +class Solution { + func countComponents(_ n: Int, _ edges: [[Int]]) -> Int { + var adj = Array(repeating: [Int](), count: n) + var visit = Array(repeating: false, count: n) + + for edge in edges { + let u = edge[0], v = edge[1] + adj[u].append(v) + adj[v].append(u) + } + + func dfs(_ node: Int) { + for nei in adj[node] { + if !visit[nei] { + visit[nei] = true + dfs(nei) + } + } + } + + var res = 0 + for node in 0.. Int { + var adj = Array(repeating: [Int](), count: n) + var visit = Array(repeating: false, count: n) + for edge in edges { + let u = edge[0], v = edge[1] + adj[u].append(v) + adj[v].append(u) + } + + func bfs(_ node: Int) { + var q = Deque() + q.append(node) + visit[node] = true + while !q.isEmpty { + let cur = q.removeFirst() + for nei in adj[cur] { + if !visit[nei] { + visit[nei] = true + q.append(nei) + } + } + } + } + + var res = 0 + for node in 0.. Int { + var cur = node + while cur != parent[cur] { + parent[cur] = parent[parent[cur]] + cur = parent[cur] + } + return cur + } + + func union(_ u: Int, _ v: Int) -> Bool { + let pu = find(u) + let pv = find(v) + if pu == pv { return false } + var rootU = pu + var rootV = pv + if rank[rootV] > rank[rootU] { + swap(&rootU, &rootV) + } + parent[rootV] = rootU + rank[rootU] += rank[rootV] + return true + } +} + +class Solution { + func countComponents(_ n: Int, _ edges: [[Int]]) -> Int { + let dsu = DSU(n) + var res = n + for edge in edges { + let u = edge[0], v = edge[1] + if dsu.union(u, v) { + res -= 1 + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/count-good-nodes-in-binary-tree.md b/articles/count-good-nodes-in-binary-tree.md index 1eda1a860..d9356f32c 100644 --- a/articles/count-good-nodes-in-binary-tree.md +++ b/articles/count-good-nodes-in-binary-tree.md @@ -250,6 +250,39 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func goodNodes(_ root: TreeNode?) -> Int { + func dfs(_ node: TreeNode?, _ maxVal: Int) -> Int { + guard let node = node else { return 0 } + + var res = node.val >= maxVal ? 1 : 0 + let newMaxVal = max(maxVal, node.val) + res += dfs(node.left, newMaxVal) + res += dfs(node.right, newMaxVal) + return res + } + + return dfs(root, root?.val ?? Int.min) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -545,6 +578,51 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func goodNodes(_ root: TreeNode?) -> Int { + guard let root = root else { return 0 } + + var res = 0 + var q = Deque<(TreeNode, Int)>() + q.append((root, Int.min)) + + while !q.isEmpty { + let (node, maxVal) = q.popFirst()! + if node.val >= maxVal { + res += 1 + } + + let newMaxVal = max(maxVal, node.val) + + if let left = node.left { + q.append((left, newMaxVal)) + } + if let right = node.right { + q.append((right, newMaxVal)) + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity 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/count-number-of-islands.md b/articles/count-number-of-islands.md index cee406700..042d79082 100644 --- a/articles/count-number-of-islands.md +++ b/articles/count-number-of-islands.md @@ -236,6 +236,40 @@ class Solution { } ``` +```swift +class Solution { + func numIslands(_ grid: [[Character]]) -> Int { + let directions = [[1, 0], [-1, 0], [0, 1], [0, -1]] + let ROWS = grid.count + let COLS = grid[0].count + var islands = 0 + var grid = grid + + func dfs(_ r: Int, _ c: Int) { + if r < 0 || c < 0 || r >= ROWS || c >= COLS || grid[r][c] == "0" { + return + } + + grid[r][c] = "0" + for dir in directions { + dfs(r + dir[0], c + dir[1]) + } + } + + for r in 0.. Int { + let directions = [[1, 0], [-1, 0], [0, 1], [0, -1]] + let ROWS = grid.count + let COLS = grid[0].count + var islands = 0 + var grid = grid + + func bfs(_ r: Int, _ c: Int) { + var queue = Deque<(Int, Int)>() + grid[r][c] = "0" + queue.append((r, c)) + + while !queue.isEmpty { + let (row, col) = queue.popFirst()! + for dir in directions { + let nr = row + dir[0] + let nc = col + dir[1] + if nr < 0 || nc < 0 || nr >= ROWS || nc >= COLS || grid[nr][nc] == "0" { + continue + } + queue.append((nr, nc)) + grid[nr][nc] = "0" + } + } + } + + for r in 0.. Int { + if parent[node] != node { + parent[node] = find(parent[node]) + } + return parent[node] + } + + func union(_ u: Int, _ v: Int) -> Bool { + let pu = find(u) + let pv = find(v) + if pu == pv { + return false + } + if size[pu] >= size[pv] { + size[pu] += size[pv] + parent[pv] = pu + } else { + size[pv] += size[pu] + parent[pu] = pv + } + return true + } +} + +class Solution { + func numIslands(_ grid: [[Character]]) -> Int { + let ROWS = grid.count + let COLS = grid[0].count + let dsu = DSU(ROWS * COLS) + + func index(_ r: Int, _ c: Int) -> Int { + return r * COLS + c + } + + let directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] + var islands = 0 + var grid = grid + + for r in 0..= ROWS || nc >= COLS || grid[nr][nc] == "0" { + continue + } + if dsu.union(index(r, c), index(nr, nc)) { + islands -= 1 + } + } + } + } + } + + return islands + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/count-paths.md b/articles/count-paths.md index 61ab8e148..5db166df2 100644 --- a/articles/count-paths.md +++ b/articles/count-paths.md @@ -121,6 +121,24 @@ class Solution { } ``` +```swift +class Solution { + func uniquePaths(_ m: Int, _ n: Int) -> Int { + func dfs(_ i: Int, _ j: Int) -> Int { + if i == m - 1 && j == n - 1 { + return 1 + } + if i >= m || j >= n { + return 0 + } + return dfs(i, j + 1) + dfs(i + 1, j) + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -304,6 +322,31 @@ class Solution { } ``` +```swift +class Solution { + func uniquePaths(_ m: Int, _ n: Int) -> Int { + var memo = Array(repeating: Array(repeating: -1, count: n), count: m) + + func dfs(_ i: Int, _ j: Int) -> Int { + if i == m - 1 && j == n - 1 { + return 1 + } + if i >= m || j >= n { + return 0 + } + if memo[i][j] != -1 { + return memo[i][j] + } + + memo[i][j] = dfs(i, j + 1) + dfs(i + 1, j) + return memo[i][j] + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -442,6 +485,23 @@ class Solution { } ``` +```swift +class Solution { + func uniquePaths(_ m: Int, _ n: Int) -> Int { + var dp = Array(repeating: Array(repeating: 0, count: n + 1), count: m + 1) + dp[m - 1][n - 1] = 1 + + for i in stride(from: m - 1, through: 0, by: -1) { + for j in stride(from: n - 1, through: 0, by: -1) { + dp[i][j] += dp[i + 1][j] + dp[i][j + 1] + } + } + + return dp[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -585,6 +645,23 @@ class Solution { } ``` +```swift +class Solution { + func uniquePaths(_ m: Int, _ n: Int) -> Int { + var row = Array(repeating: 1, count: n) + + for _ in 0..<(m - 1) { + var newRow = Array(repeating: 1, count: n) + for j in stride(from: n - 2, through: 0, by: -1) { + newRow[j] = newRow[j + 1] + row[j] + } + row = newRow + } + return row[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -716,6 +793,22 @@ class Solution { } ``` +```swift +class Solution { + func uniquePaths(_ m: Int, _ n: Int) -> Int { + var dp = Array(repeating: 1, count: n) + + for _ in stride(from: m - 2, through: 0, by: -1) { + for j in stride(from: n - 2, through: 0, by: -1) { + dp[j] += dp[j + 1] + } + } + + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -896,6 +989,30 @@ class Solution { } ``` +```swift +class Solution { + func uniquePaths(_ m: Int, _ n: Int) -> Int { + if m == 1 || n == 1 { + return 1 + } + var m = m, n = n + if m < n { + swap(&m, &n) + } + + var res = 1 + var j = 1 + for i in m..<(m + n - 1) { + res *= i + res /= j + j += 1 + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/count-squares.md b/articles/count-squares.md index 6b27ebb50..1b5defe8c 100644 --- a/articles/count-squares.md +++ b/articles/count-squares.md @@ -240,6 +240,40 @@ class CountSquares() { } ``` +```swift +class CountSquares { + private var ptsCount: [String: Int] + private var pts: [[Int]] + + init() { + self.ptsCount = [:] + self.pts = [] + } + + func add(_ point: [Int]) { + let key = "\(point[0]),\(point[1])" + ptsCount[key, default: 0] += 1 + pts.append(point) + } + + func count(_ point: [Int]) -> Int { + var res = 0 + let px = point[0], py = point[1] + + for pt in pts { + let x = pt[0], y = pt[1] + if abs(py - y) != abs(px - x) || x == px || y == py { + continue + } + let key1 = "\(x),\(py)" + let key2 = "\(px),\(y)" + res += (ptsCount[key1] ?? 0) * (ptsCount[key2] ?? 0) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -320,10 +354,9 @@ public class CountSquares { ```cpp class CountSquares { unordered_map> ptsCount; + public: - CountSquares() { - - } + CountSquares() {} void add(vector point) { ptsCount[point[0]][point[1]]++; @@ -531,6 +564,40 @@ class CountSquares { } ``` +```swift +class CountSquares { + var ptsCount: [Int: [Int: Int]] + + init() { + ptsCount = [:] + } + + func add(_ point: [Int]) { + let x = point[0] + let y = point[1] + ptsCount[x, default: [:]][y, default: 0] += 1 + } + + func count(_ point: [Int]) -> Int { + var res = 0 + let x1 = point[0] + let y1 = point[1] + + if let yMap = ptsCount[x1] { + for (y2, countXY2) in yMap { + let side = y2 - y1 + if side == 0 { continue } + let x3 = x1 + side + let x4 = x1 - side + res += countXY2 * (ptsCount[x3]?[y1] ?? 0) * (ptsCount[x3]?[y2] ?? 0) + res += countXY2 * (ptsCount[x4]?[y1] ?? 0) * (ptsCount[x4]?[y2] ?? 0) + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/count-subsequences.md b/articles/count-subsequences.md index 04fd77389..241876a84 100644 --- a/articles/count-subsequences.md +++ b/articles/count-subsequences.md @@ -181,6 +181,29 @@ class Solution { } ``` +```swift +class Solution { + func numDistinct(_ s: String, _ t: String) -> Int { + let sArray = Array(s), tArray = Array(t) + let sLen = sArray.count, tLen = tArray.count + if tLen > sLen { return 0 } + + func dfs(_ i: Int, _ j: Int) -> Int { + if j == tLen { return 1 } + if i == sLen { return 0 } + + var res = dfs(i + 1, j) + if sArray[i] == tArray[j] { + res += dfs(i + 1, j + 1) + } + return res + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -188,6 +211,8 @@ class Solution { * Time complexity: $O(2 ^ m)$ * Space complexity: $O(m)$ +> Where $m$ is the length of the string $s$. + --- ## 2. Dynamic Programming (Top-Down) @@ -396,6 +421,33 @@ class Solution { } ``` +```swift +class Solution { + func numDistinct(_ s: String, _ t: String) -> Int { + let sArray = Array(s), tArray = Array(t) + let sLen = sArray.count, tLen = tArray.count + if tLen > sLen { return 0 } + + var dp = [[Int]: Int]() + + func dfs(_ i: Int, _ j: Int) -> Int { + if j == tLen { return 1 } + if i == sLen { return 0 } + if let val = dp[[i, j]] { return val } + + var res = dfs(i + 1, j) + if sArray[i] == tArray[j] { + res += dfs(i + 1, j + 1) + } + dp[[i, j]] = res + return res + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -458,7 +510,7 @@ class Solution { public: int numDistinct(string s, string t) { int m = s.length(), n = t.length(); - vector> dp(m + 1, vector(n + 1, 0)); + vector> dp(m + 1, vector(n + 1, 0)); for (int i = 0; i <= m; i++) { dp[i][n] = 1; @@ -582,6 +634,42 @@ class Solution { } ``` +```swift +class Solution { + func numDistinct(_ s: String, _ t: String) -> Int { + let m = s.count, n = t.count + var dp = Array( + repeating: Array(repeating: 0, count: n + 1), + count: m + 1 + ) + + let sArray = Array(s) + let tArray = Array(t) + + for i in 0...m { + dp[i][n] = 1 + } + + for i in stride(from: m - 1, through: 0, by: -1) { + for j in stride(from: n - 1, through: 0, by: -1) { + let base = dp[i + 1][j] + dp[i][j] = base + if sArray[i] == tArray[j] { + let addend = dp[i + 1][j + 1] + if base > Int.max - addend { + dp[i][j] = 0 + } else { + dp[i][j] += addend + } + } + } + } + + return dp[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -643,8 +731,8 @@ class Solution { public: int numDistinct(string s, string t) { int m = s.size(), n = t.size(); - vector dp(n + 1, 0); - vector nextDp(n + 1, 0); + vector dp(n + 1, 0); + vector nextDp(n + 1, 0); dp[n] = nextDp[n] = 1; for (int i = m - 1; i >= 0; i--) { @@ -762,6 +850,38 @@ class Solution { } ``` +```swift +class Solution { + func numDistinct(_ s: String, _ t: String) -> Int { + let m = s.count, n = t.count + var dp = [Int](repeating: 0, count: n + 1) + var nextDp = [Int](repeating: 0, count: n + 1) + dp[n] = 1 + nextDp[n] = 1 + + let sArr = Array(s) + let tArr = Array(t) + + for i in stride(from: m - 1, through: 0, by: -1) { + for j in stride(from: n - 1, through: 0, by: -1) { + nextDp[j] = dp[j] + if sArr[i] == tArr[j] { + let addend = dp[j + 1] + if nextDp[j] > Int.max - addend { + nextDp[j] = 0 + } else { + nextDp[j] += addend + } + } + } + dp = nextDp + } + + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -827,13 +947,13 @@ class Solution { public: int numDistinct(string s, string t) { int m = s.size(), n = t.size(); - vector dp(n + 1, 0); + vector dp(n + 1, 0); dp[n] = 1; for (int i = m - 1; i >= 0; i--) { int prev = 1; for (int j = n - 1; j >= 0; j--) { - int res = dp[j]; + uint res = dp[j]; if (s[i] == t[j]) { res += prev; } @@ -950,6 +1070,37 @@ class Solution { } ``` +```swift +class Solution { + func numDistinct(_ s: String, _ t: String) -> Int { + let m = s.count, n = t.count + var dp = [Int](repeating: 0, count: n + 1) + dp[n] = 1 + let sArr = Array(s) + let tArr = Array(t) + + for i in stride(from: m - 1, through: 0, by: -1) { + var prev = 1 + for j in stride(from: n - 1, through: 0, by: -1) { + let base = dp[j] + var res = base + if sArr[i] == tArr[j] { + if base > Int.max - prev { + res = 0 + } else { + res += prev + } + } + prev = dp[j] + dp[j] = res + } + } + + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity 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/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/counting-bits.md b/articles/counting-bits.md index 514bef953..66b5db885 100644 --- a/articles/counting-bits.md +++ b/articles/counting-bits.md @@ -120,12 +120,32 @@ class Solution { } ``` +```swift +class Solution { + func countBits(_ n: Int) -> [Int] { + var res = [Int]() + for num in 0...n { + var one = 0 + for i in 0..<32 { + if num & (1 << i) != 0 { + one += 1 + } + } + res.append(one) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity -* Time complexity: $O(n)$ -* Space complexity: $O(1)$ +* Time complexity: $O(n \log n)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output array. --- @@ -244,12 +264,30 @@ class Solution { } ``` +```swift +class Solution { + func countBits(_ n: Int) -> [Int] { + var res = [Int](repeating: 0, count: n + 1) + for i in 1..<(n + 1) { + var num = i + while num != 0 { + res[i] += 1 + num &= (num - 1) + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity -* Time complexity: $O(n)$ -* Space complexity: $O(1)$ +* Time complexity: $O(n \log n)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output array. --- @@ -334,12 +372,26 @@ class Solution { } ``` +```swift +class Solution { + func countBits(_ n: Int) -> [Int] { + var res = [Int](repeating: 0, count: n + 1) + for num in 1..<(n + 1) { + res[num] = num.nonzeroBitCount + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity -* Time complexity: $O(n)$ -* Space complexity: $O(1)$ +* Time complexity: $O(n \log n)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output array. --- @@ -465,12 +517,31 @@ class Solution { } ``` +```swift +class Solution { + func countBits(_ n: Int) -> [Int] { + var dp = [Int](repeating: 0, count: n + 1) + var offset = 1 + + for i in 1..<(n + 1) { + if offset * 2 == i { + offset = i + } + dp[i] = 1 + dp[i - offset] + } + return dp + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output array. --- @@ -562,9 +633,23 @@ class Solution { } ``` +```swift +class Solution { + func countBits(_ n: Int) -> [Int] { + var dp = [Int](repeating: 0, count: n + 1) + for i in 0..<(n + 1) { + dp[i] = dp[i >> 1] + (i & 1) + } + return dp + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ \ No newline at end of file +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output array. \ No newline at end of file diff --git a/articles/course-schedule-ii.md b/articles/course-schedule-ii.md index 7980e9e5e..6a3e85924 100644 --- a/articles/course-schedule-ii.md +++ b/articles/course-schedule-ii.md @@ -329,6 +329,51 @@ class Solution { } ``` +```swift +class Solution { + func findOrder(_ numCourses: Int, _ prerequisites: [[Int]]) -> [Int] { + var prereq = [Int: [Int]]() + for c in 0..() + var cycle = Set() + + func dfs(_ crs: Int) -> Bool { + if cycle.contains(crs) { + return false + } + if visit.contains(crs) { + return true + } + + cycle.insert(crs) + for pre in prereq[crs]! { + if !dfs(pre) { + return false + } + } + cycle.remove(crs) + visit.insert(crs) + output.append(crs) + return true + } + + for c in 0.. [Int] { + var indegree = Array(repeating: 0, count: numCourses) + var adj = Array(repeating: [Int](), count: numCourses) + + for pair in prerequisites { + let src = pair[0] + let dst = pair[1] + indegree[dst] += 1 + adj[src].append(dst) + } + + var queue = Deque() + for n in 0.. [Int] { + var adj = Array(repeating: [Int](), count: numCourses) + var indegree = Array(repeating: 0, count: numCourses) + + for pair in prerequisites { + let nxt = pair[0] + let pre = pair[1] + indegree[nxt] += 1 + adj[pre].append(nxt) + } + + var output = [Int]() + + func dfs(_ node: Int) { + output.append(node) + indegree[node] -= 1 + for nei in adj[node] { + indegree[nei] -= 1 + if indegree[nei] == 0 { + dfs(nei) + } + } + } + + for i in 0.. CheckIfPrerequisite(int numCourses, int[][] prerequisites, int[][] queries) { + List[] adj = new List[numCourses]; + for (int i = 0; i < numCourses; i++) { + adj[i] = new List(); + } + + foreach (var pre in prerequisites) { + adj[pre[0]].Add(pre[1]); + } + + bool Dfs(int node, int target) { + if (node == target) return true; + foreach (var nei in adj[node]) { + if (Dfs(nei, target)) return true; + } + return false; + } + + var res = new List(); + foreach (var q in queries) { + res.Add(Dfs(q[0], q[1])); + } + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -259,6 +288,46 @@ class Solution { } ``` +```csharp +public class Solution { + public List CheckIfPrerequisite(int numCourses, int[][] prerequisites, int[][] queries) { + Dictionary> adj = new Dictionary>(); + for (int i = 0; i < numCourses; i++) { + adj[i] = new List(); + } + + foreach (var pair in prerequisites) { + int prereq = pair[0], crs = pair[1]; + adj[crs].Add(prereq); + } + + Dictionary> prereqMap = new Dictionary>(); + + HashSet Dfs(int crs) { + if (!prereqMap.ContainsKey(crs)) { + prereqMap[crs] = new HashSet(); + foreach (var prereq in adj[crs]) { + prereqMap[crs].UnionWith(Dfs(prereq)); + } + prereqMap[crs].Add(crs); + } + return prereqMap[crs]; + } + + for (int crs = 0; crs < numCourses; crs++) { + Dfs(crs); + } + + List res = new List(); + foreach (var q in queries) { + res.Add(prereqMap.ContainsKey(q[1]) && prereqMap[q[1]].Contains(q[0])); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -416,6 +485,53 @@ class Solution { } ``` +```csharp +public class Solution { + public List CheckIfPrerequisite(int numCourses, int[][] prerequisites, int[][] queries) { + List[] adj = new List[numCourses]; + for (int i = 0; i < numCourses; i++) { + adj[i] = new List(); + } + + int[,] isPrereq = new int[numCourses, numCourses]; + for (int i = 0; i < numCourses; i++) { + for (int j = 0; j < numCourses; j++) { + isPrereq[i, j] = -1; + } + } + + foreach (var pair in prerequisites) { + int prereq = pair[0], crs = pair[1]; + adj[crs].Add(prereq); + isPrereq[crs, prereq] = 1; + } + + bool Dfs(int crs, int prereq) { + if (isPrereq[crs, prereq] != -1) { + return isPrereq[crs, prereq] == 1; + } + + foreach (int pre in adj[crs]) { + if (pre == prereq || Dfs(pre, prereq)) { + isPrereq[crs, prereq] = 1; + return true; + } + } + + isPrereq[crs, prereq] = 0; + return false; + } + + List res = new List(); + foreach (var q in queries) { + res.Add(Dfs(q[1], q[0])); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -572,6 +688,56 @@ class Solution { } ``` +```csharp +public class Solution { + public List CheckIfPrerequisite(int numCourses, int[][] prerequisites, int[][] queries) { + List> adj = new List>(); + List> isPrereq = new List>(); + int[] indegree = new int[numCourses]; + + for (int i = 0; i < numCourses; i++) { + adj.Add(new HashSet()); + isPrereq.Add(new HashSet()); + } + + foreach (var pair in prerequisites) { + int pre = pair[0], crs = pair[1]; + adj[pre].Add(crs); + indegree[crs]++; + } + + Queue q = new Queue(); + for (int i = 0; i < numCourses; i++) { + if (indegree[i] == 0) { + q.Enqueue(i); + } + } + + while (q.Count > 0) { + int node = q.Dequeue(); + foreach (int neighbor in adj[node]) { + isPrereq[neighbor].Add(node); + foreach (int p in isPrereq[node]) { + isPrereq[neighbor].Add(p); + } + indegree[neighbor]--; + if (indegree[neighbor] == 0) { + q.Enqueue(neighbor); + } + } + } + + List result = new List(); + foreach (var query in queries) { + int u = query[0], v = query[1]; + result.Add(isPrereq[v].Contains(u)); + } + + return result; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -695,6 +861,35 @@ class Solution { } ``` +```csharp +public class Solution { + public List CheckIfPrerequisite(int numCourses, int[][] prerequisites, int[][] queries) { + bool[,] adj = new bool[numCourses, numCourses]; + + foreach (var pair in prerequisites) { + int pre = pair[0], crs = pair[1]; + adj[pre, crs] = true; + } + + for (int k = 0; k < numCourses; k++) { + for (int i = 0; i < numCourses; i++) { + for (int j = 0; j < numCourses; j++) { + adj[i, j] = adj[i, j] || (adj[i, k] && adj[k, j]); + } + } + } + + List res = new List(); + foreach (var query in queries) { + int u = query[0], v = query[1]; + res.Add(adj[u, v]); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/course-schedule.md b/articles/course-schedule.md index b499babdf..d57ce12c1 100644 --- a/articles/course-schedule.md +++ b/articles/course-schedule.md @@ -310,6 +310,51 @@ class Solution { } ``` +```swift +class Solution { + func canFinish(_ numCourses: Int, _ prerequisites: [[Int]]) -> Bool { + // Map each course to its prerequisites + var preMap = [Int: [Int]]() + for i in 0..() + + func dfs(_ crs: Int) -> Bool { + if visiting.contains(crs) { + // Cycle detected + return false + } + if preMap[crs]!.isEmpty { + return true + } + + visiting.insert(crs) + for pre in preMap[crs]! { + if !dfs(pre) { + return false + } + } + visiting.remove(crs) + preMap[crs] = [] + return true + } + + for c in 0.. Bool { + var indegree = Array(repeating: 0, count: numCourses) + var adj = Array(repeating: [Int](), count: numCourses) + + for pair in prerequisites { + let src = pair[0] + let dst = pair[1] + indegree[dst] += 1 + adj[src].append(dst) + } + + var queue = Deque() + for n in 0.. [Int] { + let n = temperatures.count + var res = [Int]() + + for i in 0.. temperatures[i] { + break + } + j += 1 + count += 1 + } + count = (j == n) ? 0 : count + res.append(count) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n ^ 2)$ -* Space complexity: $O(1)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output array. --- @@ -323,6 +349,24 @@ class Solution { } ``` +```swift +class Solution { + func dailyTemperatures(_ temperatures: [Int]) -> [Int] { + var res = [Int](repeating: 0, count: temperatures.count) + var stack = [(Int, Int)]() // Pair: (temperature, index) + + for (i, t) in temperatures.enumerated() { + while !stack.isEmpty && t > stack.last!.0 { + let (stackT, stackInd) = stack.removeLast() + res[stackInd] = i - stackInd + } + stack.append((t, i)) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -508,9 +552,36 @@ class Solution { } ``` +```swift +class Solution { + func dailyTemperatures(_ temperatures: [Int]) -> [Int] { + let n = temperatures.count + var res = [Int](repeating: 0, count: n) + + for i in stride(from: n - 2, through: 0, by: -1) { + var j = i + 1 + while j < n && temperatures[j] <= temperatures[i] { + if res[j] == 0 { + j = n + break + } + j += res[j] + } + + if j < n { + res[i] = j - i + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ \ No newline at end of file +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output array. \ No newline at end of file diff --git a/articles/decode-string.md b/articles/decode-string.md index c5363f71b..c86b9b8f1 100644 --- a/articles/decode-string.md +++ b/articles/decode-string.md @@ -143,6 +143,46 @@ class Solution { } ``` +```csharp +public class Solution { + private int i; + + public string DecodeString(string s) { + i = 0; + return Helper(s); + } + + private string Helper(string s) { + string res = ""; + int k = 0; + + while (i < s.Length) { + char c = s[i]; + + if (char.IsDigit(c)) { + k = k * 10 + (c - '0'); + } else if (c == '[') { + i++; + string inner = Helper(s); + res += new string(' ', 0).PadLeft(0); + for (int j = 0; j < k; j++) { + res += inner; + } + k = 0; + } else if (c == ']') { + return res; + } else { + res += c; + } + + i++; + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -290,6 +330,41 @@ class Solution { } ``` +```csharp +public class Solution { + public string DecodeString(string s) { + Stack stack = new Stack(); + + for (int i = 0; i < s.Length; i++) { + if (s[i] != ']') { + stack.Push(s[i].ToString()); + } else { + string substr = ""; + while (stack.Peek() != "[") { + substr = stack.Pop() + substr; + } + stack.Pop(); // remove '[' + + string k = ""; + while (stack.Count > 0 && char.IsDigit(stack.Peek()[0])) { + k = stack.Pop() + k; + } + + int repeat = int.Parse(k); + string expanded = new StringBuilder().Insert(0, substr, repeat).ToString(); + stack.Push(expanded); + } + } + + var result = new StringBuilder(); + foreach (string part in stack) { + result.Insert(0, part); + } + return result.ToString(); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -436,6 +511,39 @@ class Solution { } ``` +```csharp +public class Solution { + public string DecodeString(string s) { + Stack stringStack = new Stack(); + Stack countStack = new Stack(); + string cur = ""; + int k = 0; + + foreach (char c in s) { + if (char.IsDigit(c)) { + k = k * 10 + (c - '0'); + } else if (c == '[') { + stringStack.Push(cur); + countStack.Push(k); + cur = ""; + k = 0; + } else if (c == ']') { + string temp = cur; + cur = stringStack.Pop(); + int count = countStack.Pop(); + for (int i = 0; i < count; i++) { + cur += temp; + } + } else { + cur += c; + } + } + + return cur; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/decode-ways.md b/articles/decode-ways.md index bfda19321..c735d1d3f 100644 --- a/articles/decode-ways.md +++ b/articles/decode-ways.md @@ -163,6 +163,34 @@ class Solution { } ``` +```swift +class Solution { + func numDecodings(_ s: String) -> Int { + let chars = Array(s) + + func dfs(_ i: Int) -> Int { + if i == chars.count { + return 1 + } + if chars[i] == "0" { + return 0 + } + + var res = dfs(i + 1) + if i < chars.count - 1 { + if chars[i] == "1" || (chars[i] == "2" && chars[i + 1] < "7") { + res += dfs(i + 2) + } + } + + return res + } + + return dfs(0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -375,6 +403,35 @@ class Solution { } ``` +```swift +class Solution { + func numDecodings(_ s: String) -> Int { + let chars = Array(s) + var dp = [Int: Int]() + dp[chars.count] = 1 + + func dfs(_ i: Int) -> Int { + if let cached = dp[i] { + return cached + } + if chars[i] == "0" { + return 0 + } + + var res = dfs(i + 1) + if i + 1 < chars.count, + chars[i] == "1" || (chars[i] == "2" && "0123456".contains(chars[i + 1])) { + res += dfs(i + 2) + } + dp[i] = res + return res + } + + return dfs(0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -533,6 +590,30 @@ class Solution { } ``` +```swift +class Solution { + func numDecodings(_ s: String) -> Int { + let chars = Array(s) + var dp = [Int: Int]() + dp[chars.count] = 1 + + for i in stride(from: chars.count - 1, through: 0, by: -1) { + if chars[i] == "0" { + dp[i] = 0 + } else { + dp[i] = dp[i + 1] ?? 0 + } + + if i + 1 < chars.count, + chars[i] == "1" || (chars[i] == "2" && "0123456".contains(chars[i + 1])) { + dp[i]! += dp[i + 2] ?? 0 + } + } + return dp[0] ?? 0 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -711,6 +792,30 @@ class Solution { } ``` +```swift +class Solution { + func numDecodings(_ s: String) -> Int { + let chars = Array(s) + var dp = 0, dp1 = 1, dp2 = 0 + + for i in stride(from: chars.count - 1, through: 0, by: -1) { + if chars[i] == "0" { + dp = 0 + } else { + dp = dp1 + } + + if i + 1 < chars.count, + chars[i] == "1" || (chars[i] == "2" && "0123456".contains(chars[i + 1])) { + dp += dp2 + } + (dp, dp1, dp2) = (0, dp, dp1) + } + return dp1 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/delete-leaves-with-a-given-value.md b/articles/delete-leaves-with-a-given-value.md index ccfb4637b..add3a0494 100644 --- a/articles/delete-leaves-with-a-given-value.md +++ b/articles/delete-leaves-with-a-given-value.md @@ -122,6 +122,36 @@ class Solution { } ``` +```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 TreeNode RemoveLeafNodes(TreeNode root, int target) { + if (root == null) return null; + + root.left = RemoveLeafNodes(root.left, target); + root.right = RemoveLeafNodes(root.right, target); + + if (root.left == null && root.right == null && root.val == target) { + return null; + } + + return root; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -343,6 +373,62 @@ class Solution { } ``` +```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 TreeNode RemoveLeafNodes(TreeNode root, int target) { + if (root == null) return null; + + Stack stack = new Stack(); + HashSet visited = new HashSet(); + Dictionary parents = new Dictionary(); + + stack.Push(root); + parents[root] = null; + + while (stack.Count > 0) { + TreeNode node = stack.Pop(); + + if (node.left == null && node.right == null) { + if (node.val == target) { + TreeNode parent = parents[node]; + if (parent == null) { + return null; + } + if (parent.left == node) parent.left = null; + if (parent.right == node) parent.right = null; + } + } else if (!visited.Contains(node)) { + visited.Add(node); + stack.Push(node); + if (node.left != null) { + stack.Push(node.left); + parents[node.left] = node; + } + if (node.right != null) { + stack.Push(node.right); + parents[node.right] = node; + } + } + } + + return root; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -569,6 +655,62 @@ class Solution { } ``` +```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 TreeNode RemoveLeafNodes(TreeNode root, int target) { + if (root == null) return null; + + Stack stack = new Stack(); + TreeNode cur = root; + TreeNode visited = null; + + while (stack.Count > 0 || cur != null) { + while (cur != null) { + stack.Push(cur); + cur = cur.left; + } + + cur = stack.Peek(); + if (cur.right != null && cur.right != visited) { + cur = cur.right; + continue; + } + + stack.Pop(); + if (cur.left == null && cur.right == null && cur.val == target) { + if (stack.Count == 0) return null; + + TreeNode parent = stack.Peek(); + if (parent.left == cur) { + parent.left = null; + } else if (parent.right == cur) { + parent.right = null; + } + } else { + visited = cur; + } + + cur = null; + } + + return root; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/delete-node-in-a-bst.md b/articles/delete-node-in-a-bst.md index 4b086145a..0a9617193 100644 --- a/articles/delete-node-in-a-bst.md +++ b/articles/delete-node-in-a-bst.md @@ -153,6 +153,45 @@ class Solution { } ``` +```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 TreeNode DeleteNode(TreeNode root, int key) { + if (root == null) return null; + + if (key > root.val) { + root.right = DeleteNode(root.right, key); + } else if (key < root.val) { + root.left = DeleteNode(root.left, key); + } else { + if (root.left == null) return root.right; + if (root.right == null) return root.left; + + TreeNode cur = root.right; + while (cur.left != null) { + cur = cur.left; + } + root.val = cur.val; + root.right = DeleteNode(root.right, root.val); + } + + return root; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -327,6 +366,46 @@ class Solution { } ``` +```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 TreeNode DeleteNode(TreeNode root, int key) { + if (root == null) return null; + + if (key > root.val) { + root.right = DeleteNode(root.right, key); + } else if (key < root.val) { + root.left = DeleteNode(root.left, key); + } else { + if (root.left == null) return root.right; + if (root.right == null) return root.left; + + TreeNode cur = root.right; + while (cur.left != null) { + cur = cur.left; + } + cur.left = root.left; + TreeNode res = root.right; + return res; + } + + return root; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -622,6 +701,85 @@ class Solution { } ``` +```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 TreeNode DeleteNode(TreeNode root, int key) { + if (root == null) return null; + + TreeNode parent = null; + TreeNode cur = root; + + // Find the node to delete + while (cur != null && cur.val != key) { + parent = cur; + if (key > cur.val) { + cur = cur.right; + } else { + cur = cur.left; + } + } + + if (cur == null) return root; + + // Node with one or no child + if (cur.left == null || cur.right == null) { + TreeNode child = cur.left != null ? cur.left : cur.right; + + if (parent == null) { + return child; + } + + if (parent.left == cur) { + parent.left = child; + } else { + parent.right = child; + } + } else { + // Node with two children + TreeNode par = null; + TreeNode delNode = cur; + cur = cur.right; + while (cur.left != null) { + par = cur; + cur = cur.left; + } + + if (par != null) { + par.left = cur.right; + cur.right = delNode.right; + } + + cur.left = delNode.left; + + if (parent == null) { + return cur; + } + + if (parent.left == delNode) { + parent.left = cur; + } else { + parent.right = cur; + } + } + + return root; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/depth-of-binary-tree.md b/articles/depth-of-binary-tree.md index efd76b64d..88a35751d 100644 --- a/articles/depth-of-binary-tree.md +++ b/articles/depth-of-binary-tree.md @@ -171,6 +171,30 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func maxDepth(_ root: TreeNode?) -> Int { + guard let root = root else { return 0 } + return 1 + max(maxDepth(root.left), maxDepth(root.right)) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -440,6 +464,41 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func maxDepth(_ root: TreeNode?) -> Int { + var stack: [(TreeNode?, Int)] = [(root, 1)] + var res = 0 + + while !stack.isEmpty { + let (node, depth) = stack.removeLast() + + if let node = node { + res = max(res, depth) + stack.append((node.left, depth + 1)) + stack.append((node.right, depth + 1)) + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -723,6 +782,47 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func maxDepth(_ root: TreeNode?) -> Int { + var queue = Deque() + if let root = root { + queue.append(root) + } + + var level = 0 + while !queue.isEmpty { + for _ in 0..] + private var tweetMap: [Int: [(Int, Int)]] + + init() { + self.time = 0 + self.followMap = [:] + self.tweetMap = [:] + } + + func postTweet(_ userId: Int, _ tweetId: Int) { + if tweetMap[userId] == nil { + tweetMap[userId] = [] + } + tweetMap[userId]!.append((time, tweetId)) + time += 1 + } + + func getNewsFeed(_ userId: Int) -> [Int] { + var feed = tweetMap[userId] ?? [] + if let followees = followMap[userId] { + for followeeId in followees { + if let tweets = tweetMap[followeeId] { + feed.append(contentsOf: tweets) + } + } + } + feed.sort { $0.0 > $1.0 } + return feed.prefix(10).map { $0.1 } + } + + func follow(_ followerId: Int, _ followeeId: Int) { + if followerId != followeeId { + followMap[followerId, default: Set()].insert(followeeId) + } + } + + func unfollow(_ followerId: Int, _ followeeId: Int) { + followMap[followerId]?.remove(followeeId) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -769,6 +814,84 @@ class Twitter { } ``` +```swift +class Twitter { + private var count: Int + private var tweetMap: [Int: [(Int, Int)]] // userId -> list of (count, tweetId) + private var followMap: [Int: Set] // userId -> set of followeeId + + init() { + self.count = 0 + self.tweetMap = [:] + self.followMap = [:] + } + + func postTweet(_ userId: Int, _ tweetId: Int) { + tweetMap[userId, default: []].append((count, tweetId)) + count -= 1 + } + + func getNewsFeed(_ userId: Int) -> [Int] { + var res = [Int]() + var minHeap = Heap() + + followMap[userId, default: Set()].insert(userId) + if let followees = followMap[userId] { + for followee in followees { + if let tweets = tweetMap[followee], !tweets.isEmpty { + let index = tweets.count - 1 + let (cnt, tweetId) = tweets[index] + minHeap.insert( + Item( + count: cnt, tweetId: tweetId, + followeeId: followee, index: index - 1 + ) + ) + } + } + } + + while !minHeap.isEmpty && res.count < 10 { + let entry = minHeap.popMin()! + res.append(entry.tweetId) + if entry.index >= 0, let tweets = tweetMap[entry.followeeId] { + let (cnt, tweetId) = tweets[entry.index] + minHeap.insert( + Item( + count: cnt, tweetId: tweetId, + followeeId: entry.followeeId, index: entry.index - 1 + ) + ) + } + } + return res + } + + func follow(_ followerId: Int, _ followeeId: Int) { + followMap[followerId, default: Set()].insert(followeeId) + } + + func unfollow(_ followerId: Int, _ followeeId: Int) { + followMap[followerId]?.remove(followeeId) + } +} + +struct Item: Comparable { + let count: Int + let tweetId: Int + let followeeId: Int + let index: Int + + static func < (lhs: Item, rhs: Item) -> Bool { + return lhs.count < rhs.count + } + + static func == (lhs: Item, rhs: Item) -> Bool { + return lhs.count == rhs.count + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1425,6 +1548,112 @@ class Twitter { } ``` +```swift +struct Item: Comparable { + let count: Int + let tweetId: Int + let followeeId: Int + let index: Int + + static func < (lhs: Item, rhs: Item) -> Bool { + return lhs.count < rhs.count + } + + static func == (lhs: Item, rhs: Item) -> Bool { + return lhs.count == rhs.count && + lhs.tweetId == rhs.tweetId && + lhs.followeeId == rhs.followeeId && + lhs.index == rhs.index + } +} + +class Twitter { + private var count: Int + private var tweetMap: [Int: [(Int, Int)]] // userId -> list of (count, tweetId) + private var followMap: [Int: Set] // userId -> set of followeeId + + init() { + self.count = 0 + self.tweetMap = [:] + self.followMap = [:] + } + + func postTweet(_ userId: Int, _ tweetId: Int) { + tweetMap[userId, default: []].append((count, tweetId)) + if tweetMap[userId]!.count > 10 { + tweetMap[userId]!.removeFirst() + } + count -= 1 + } + + func getNewsFeed(_ userId: Int) -> [Int] { + var res = [Int]() + var minHeap = Heap() + followMap[userId, default: Set()].insert(userId) + + if followMap[userId]!.count >= 10 { + var maxHeap = Heap() + for followeeId in followMap[userId]! { + if let tweets = tweetMap[followeeId], !tweets.isEmpty { + let index = tweets.count - 1 + let (cnt, tweetId) = tweets[index] + maxHeap.insert( + Item( + count: cnt, tweetId: tweetId, + followeeId: followeeId, index: index - 1 + ) + ) + if maxHeap.count > 10 { + maxHeap.removeMax() + } + } + } + while !maxHeap.isEmpty { + let item = maxHeap.popMax()! + minHeap.insert(item) + } + } else { + for followeeId in followMap[userId]! { + if let tweets = tweetMap[followeeId], !tweets.isEmpty { + let index = tweets.count - 1 + let (cnt, tweetId) = tweets[index] + minHeap.insert( + Item( + count: cnt, tweetId: tweetId, + followeeId: followeeId, index: index - 1 + ) + ) + } + } + } + + while !minHeap.isEmpty && res.count < 10 { + let item = minHeap.popMin()! + res.append(item.tweetId) + if item.index >= 0, let tweets = tweetMap[item.followeeId] { + let (cnt, tweetId) = tweets[item.index] + minHeap.insert( + Item( + count: cnt, tweetId: tweetId, + followeeId: item.followeeId, index: item.index - 1 + ) + ) + } + } + + return res + } + + func follow(_ followerId: Int, _ followeeId: Int) { + followMap[followerId, default: Set()].insert(followeeId) + } + + func unfollow(_ followerId: Int, _ followeeId: Int) { + followMap[followerId]?.remove(followeeId) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/design-word-search-data-structure.md b/articles/design-word-search-data-structure.md index 501e42785..033096234 100644 --- a/articles/design-word-search-data-structure.md +++ b/articles/design-word-search-data-structure.md @@ -222,6 +222,42 @@ class WordDictionary { } ``` +```swift +class WordDictionary { + private var store: [String] + + init() { + self.store = [] + } + + func addWord(_ word: String) { + store.append(word) + } + + func search(_ word: String) -> Bool { + for w in store { + if w.count != word.count { + continue + } + var i = 0 + let wArray = Array(w) + let wordArray = Array(word) + while i < wArray.count { + if wArray[i] == wordArray[i] || wordArray[i] == "." { + i += 1 + } else { + break + } + } + if i == wArray.count { + return true + } + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -627,6 +663,64 @@ class WordDictionary { } ``` +```swift +class TrieNode { + var children: [Character: TrieNode] + var word: Bool + + init() { + self.children = [:] + self.word = false + } +} + +class WordDictionary { + private let root: TrieNode + + init() { + self.root = TrieNode() + } + + func addWord(_ word: String) { + var cur = root + for c in word { + if cur.children[c] == nil { + cur.children[c] = TrieNode() + } + cur = cur.children[c]! + } + cur.word = true + } + + func search(_ word: String) -> Bool { + func dfs(_ j: Int, _ root: TrieNode) -> Bool { + var cur = root + let wordArray = Array(word) + + for i in j.. 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/duplicate-integer.md b/articles/duplicate-integer.md index c7b5e21f2..882486892 100644 --- a/articles/duplicate-integer.md +++ b/articles/duplicate-integer.md @@ -105,11 +105,26 @@ class Solution { } ``` +```swift +class Solution { + func hasDuplicate(_ nums: [Int]) -> Bool { + for i in 0.. Bool { + var nums = nums.sorted() + for i in 1.. Bool { + var seen = Set() + for num in nums { + if seen.contains(num) { + return true + } + seen.insert(num) + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -406,6 +450,14 @@ class Solution { } ``` +```swift +class Solution { + func hasDuplicate(_ nums: [Int]) -> Bool { + return Set(nums).count < nums.count + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/eating-bananas.md b/articles/eating-bananas.md index bf00f6c04..4acd82fb0 100644 --- a/articles/eating-bananas.md +++ b/articles/eating-bananas.md @@ -137,6 +137,27 @@ class Solution { } ``` +```swift +class Solution { + func minEatingSpeed(_ piles: [Int], _ h: Int) -> Int { + var speed = 1 + + while true { + var totalTime = 0 + for pile in piles { + totalTime += Int(ceil(Double(pile) / Double(speed))) + } + + if totalTime <= h { + return speed + } + speed += 1 + } + return speed + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -338,6 +359,32 @@ class Solution { } ``` +```swift +class Solution { + func minEatingSpeed(_ piles: [Int], _ h: Int) -> Int { + var l = 1, r = piles.max()! + var res = r + + while l <= r { + let k = (l + r) / 2 + + var totalTime = 0 + for p in piles { + totalTime += Int(ceil(Double(p) / Double(k))) + } + + if totalTime <= h { + res = k + r = k - 1 + } else { + l = k + 1 + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/edit-distance.md b/articles/edit-distance.md index a116df5c7..7c4b6bfeb 100644 --- a/articles/edit-distance.md +++ b/articles/edit-distance.md @@ -169,6 +169,27 @@ class Solution { } ``` +```swift +class Solution { + func minDistance(_ word1: String, _ word2: String) -> Int { + let m = word1.count, n = word2.count + let word1Array = Array(word1), word2Array = Array(word2) + + func dfs(_ i: Int, _ j: Int) -> Int { + if i == m { return n - j } + if j == n { return m - i } + if word1Array[i] == word2Array[j] { + return dfs(i + 1, j + 1) + } + let res = min(dfs(i + 1, j), dfs(i, j + 1)) + return min(res, dfs(i + 1, j + 1)) + 1 + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -403,6 +424,32 @@ class Solution { } ``` +```swift +class Solution { + func minDistance(_ word1: String, _ word2: String) -> Int { + let m = word1.count, n = word2.count + let word1Array = Array(word1), word2Array = Array(word2) + var dp = [[Int?]](repeating: [Int?](repeating: nil, count: n + 1), count: m + 1) + + func dfs(_ i: Int, _ j: Int) -> Int { + if i == m { return n - j } + if j == n { return m - i } + if let val = dp[i][j] { return val } + + if word1Array[i] == word2Array[j] { + dp[i][j] = dfs(i + 1, j + 1) + } else { + let res = min(dfs(i + 1, j), dfs(i, j + 1), dfs(i + 1, j + 1)) + 1 + dp[i][j] = res + } + return dp[i][j]! + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -624,6 +671,34 @@ class Solution { } ``` +```swift +class Solution { + func minDistance(_ word1: String, _ word2: String) -> Int { + let m = word1.count, n = word2.count + let word1Array = Array(word1), word2Array = Array(word2) + var dp = [[Int]](repeating: [Int](repeating: Int.max, count: n + 1), count: m + 1) + + for j in 0...n { + dp[m][j] = n - j + } + for i in 0...m { + dp[i][n] = m - i + } + + for i in stride(from: m - 1, through: 0, by: -1) { + for j in stride(from: n - 1, through: 0, by: -1) { + if word1Array[i] == word2Array[j] { + dp[i][j] = dp[i + 1][j + 1] + } else { + dp[i][j] = 1 + min(dp[i + 1][j], dp[i][j + 1], dp[i + 1][j + 1]) + } + } + } + return dp[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -890,6 +965,41 @@ class Solution { } ``` +```swift +class Solution { + func minDistance(_ word1: String, _ word2: String) -> Int { + var m = word1.count, n = word2.count + var word1Array = Array(word1), word2Array = Array(word2) + + if m < n { + swap(&m, &n) + swap(&word1Array, &word2Array) + } + + var dp = [Int](repeating: 0, count: n + 1) + var nextDp = [Int](repeating: 0, count: n + 1) + + for j in 0...n { + dp[j] = n - j + } + + for i in stride(from: m - 1, through: 0, by: -1) { + nextDp[n] = m - i + for j in stride(from: n - 1, through: 0, by: -1) { + if word1Array[i] == word2Array[j] { + nextDp[j] = dp[j + 1] + } else { + nextDp[j] = 1 + min(dp[j], nextDp[j + 1], dp[j + 1]) + } + } + dp = nextDp + } + + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1134,6 +1244,37 @@ class Solution { } ``` +```swift +class Solution { + func minDistance(_ word1: String, _ word2: String) -> Int { + var m = word1.count, n = word2.count + var word1Array = Array(word1), word2Array = Array(word2) + + if m < n { + swap(&m, &n) + swap(&word1Array, &word2Array) + } + + var dp = (0...n).map { n - $0 } + + for i in stride(from: m - 1, through: 0, by: -1) { + var nextDp = dp[n] + dp[n] = m - i + for j in stride(from: n - 1, through: 0, by: -1) { + let temp = dp[j] + if word1Array[i] == word2Array[j] { + dp[j] = nextDp + } else { + dp[j] = 1 + min(dp[j], dp[j + 1], nextDp) + } + nextDp = temp + } + } + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/evaluate-division.md b/articles/evaluate-division.md index 647a8002b..9be40ad06 100644 --- a/articles/evaluate-division.md +++ b/articles/evaluate-division.md @@ -199,6 +199,56 @@ class Solution { } ``` +```csharp +public class Solution { + public double[] CalcEquation(List> equations, double[] values, List> queries) { + var adj = new Dictionary>(); + + for (int i = 0; i < equations.Count; i++) { + string a = equations[i][0]; + string b = equations[i][1]; + double val = values[i]; + + if (!adj.ContainsKey(a)) adj[a] = new List<(string, double)>(); + if (!adj.ContainsKey(b)) adj[b] = new List<(string, double)>(); + + adj[a].Add((b, val)); + adj[b].Add((a, 1.0 / val)); + } + + double Bfs(string src, string target) { + if (!adj.ContainsKey(src) || !adj.ContainsKey(target)) return -1.0; + var queue = new Queue<(string, double)>(); + var visited = new HashSet(); + + queue.Enqueue((src, 1.0)); + visited.Add(src); + + while (queue.Count > 0) { + var (node, weight) = queue.Dequeue(); + if (node == target) return weight; + + foreach (var (nei, w) in adj[node]) { + if (!visited.Contains(nei)) { + visited.Add(nei); + queue.Enqueue((nei, weight * w)); + } + } + } + + return -1.0; + } + + double[] res = new double[queries.Count]; + for (int i = 0; i < queries.Count; i++) { + res[i] = Bfs(queries[i][0], queries[i][1]); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -391,6 +441,51 @@ class Solution { } ``` +```csharp +public class Solution { + public double[] CalcEquation(List> equations, double[] values, List> queries) { + var adj = new Dictionary>(); + + for (int i = 0; i < equations.Count; i++) { + string a = equations[i][0], b = equations[i][1]; + double val = values[i]; + + if (!adj.ContainsKey(a)) adj[a] = new List<(string, double)>(); + if (!adj.ContainsKey(b)) adj[b] = new List<(string, double)>(); + + adj[a].Add((b, val)); + adj[b].Add((a, 1.0 / val)); + } + + double Dfs(string src, string target, HashSet visited) { + if (!adj.ContainsKey(src) || !adj.ContainsKey(target)) return -1.0; + if (src == target) return 1.0; + + visited.Add(src); + + foreach (var (nei, weight) in adj[src]) { + if (!visited.Contains(nei)) { + double result = Dfs(nei, target, visited); + if (result != -1.0) { + return weight * result; + } + } + } + + return -1.0; + } + + double[] res = new double[queries.Count]; + for (int i = 0; i < queries.Count; i++) { + var visited = new HashSet(); + res[i] = Dfs(queries[i][0], queries[i][1], visited); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -666,6 +761,69 @@ class Solution { } ``` +```csharp +public class UnionFind { + private Dictionary parent = new Dictionary(); + private Dictionary weight = new Dictionary(); + + public void Add(string x) { + if (!parent.ContainsKey(x)) { + parent[x] = x; + weight[x] = 1.0; + } + } + + public string Find(string x) { + if (parent[x] != x) { + string origParent = parent[x]; + parent[x] = Find(origParent); + weight[x] *= weight[origParent]; + } + return parent[x]; + } + + public void Union(string x, string y, double value) { + Add(x); + Add(y); + string rootX = Find(x); + string rootY = Find(y); + + if (rootX != rootY) { + parent[rootX] = rootY; + weight[rootX] = value * weight[y] / weight[x]; + } + } + + public double GetRatio(string x, string y) { + if (!parent.ContainsKey(x) || !parent.ContainsKey(y) || Find(x) != Find(y)) { + return -1.0; + } + return weight[x] / weight[y]; + } +} + +public class Solution { + public double[] CalcEquation(List> equations, double[] values, List> queries) { + var uf = new UnionFind(); + + for (int i = 0; i < equations.Count; i++) { + string a = equations[i][0]; + string b = equations[i][1]; + uf.Union(a, b, values[i]); + } + + double[] res = new double[queries.Count]; + for (int i = 0; i < queries.Count; i++) { + string a = queries[i][0]; + string b = queries[i][1]; + res[i] = uf.GetRatio(a, b); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -826,6 +984,49 @@ class Solution { } ``` +```csharp +public class Solution { + public double[] CalcEquation(List> equations, double[] values, List> queries) { + var graph = new Dictionary>(); + + for (int i = 0; i < equations.Count; i++) { + string a = equations[i][0]; + string b = equations[i][1]; + double val = values[i]; + + if (!graph.ContainsKey(a)) graph[a] = new Dictionary(); + if (!graph.ContainsKey(b)) graph[b] = new Dictionary(); + + graph[a][b] = val; + graph[b][a] = 1.0 / val; + } + + foreach (var k in graph.Keys.ToList()) { + foreach (var i in graph[k].Keys.ToList()) { + foreach (var j in graph[k].Keys.ToList()) { + if (!graph[i].ContainsKey(j)) { + graph[i][j] = graph[i][k] * graph[k][j]; + } + } + } + } + + double[] result = new double[queries.Count]; + for (int i = 0; i < queries.Count; i++) { + string a = queries[i][0]; + string b = queries[i][1]; + if (graph.ContainsKey(a) && graph[a].ContainsKey(b)) { + result[i] = graph[a][b]; + } else { + result[i] = -1.0; + } + } + + return result; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/evaluate-reverse-polish-notation.md b/articles/evaluate-reverse-polish-notation.md index 9c3520b02..3ad96eff8 100644 --- a/articles/evaluate-reverse-polish-notation.md +++ b/articles/evaluate-reverse-polish-notation.md @@ -216,6 +216,39 @@ class Solution { } ``` +```swift +class Solution { + func evalRPN(_ tokens: [String]) -> Int { + var tokens = tokens + + while tokens.count > 1 { + for i in 0.. Int { + var head: DoublyLinkedList? = DoublyLinkedList(val: tokens[0]) + var curr = head + + for i in 1.. Int { + var tokens = tokens + + func dfs() -> Int { + let token = tokens.removeLast() + if let num = Int(token) { + return num + } + + let right = dfs() + let left = dfs() + + switch token { + case "+": return left + right + case "-": return left - right + case "*": return left * right + case "/": return left / right + default: return 0 + } + } + + return dfs() + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1042,6 +1161,34 @@ class Solution { } ``` +```swift +class Solution { + func evalRPN(_ tokens: [String]) -> Int { + var stack = [Int]() + + for c in tokens { + switch c { + case "+": + stack.append(stack.removeLast() + stack.removeLast()) + case "-": + let a = stack.removeLast() + let b = stack.removeLast() + stack.append(b - a) + case "*": + stack.append(stack.removeLast() * stack.removeLast()) + case "/": + let a = stack.removeLast() + let b = stack.removeLast() + stack.append(b / a) + default: + stack.append(Int(c)!) + } + } + return stack[0] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/extra-characters-in-a-string.md b/articles/extra-characters-in-a-string.md index b41af1f45..6b2052693 100644 --- a/articles/extra-characters-in-a-string.md +++ b/articles/extra-characters-in-a-string.md @@ -104,6 +104,30 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinExtraChar(string s, string[] dictionary) { + HashSet words = new HashSet(dictionary); + return Dfs(0, s, words); + } + + private int Dfs(int i, string s, HashSet words) { + if (i == s.Length) { + return 0; + } + + int res = 1 + Dfs(i + 1, s, words); + for (int j = i; j < s.Length; j++) { + if (words.Contains(s.Substring(i, j - i + 1))) { + res = Math.Min(res, Dfs(j + 1, s, words)); + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -220,6 +244,34 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinExtraChar(string s, string[] dictionary) { + HashSet words = new HashSet(dictionary); + int n = s.Length; + int[] dp = new int[n + 1]; + Array.Fill(dp, -1); + dp[n] = 0; + + return Dfs(0, s, words, dp); + } + + private int Dfs(int i, string s, HashSet words, int[] dp) { + if (dp[i] != -1) return dp[i]; + + int res = 1 + Dfs(i + 1, s, words, dp); + for (int j = i; j < s.Length; j++) { + if (words.Contains(s.Substring(i, j - i + 1))) { + res = Math.Min(res, Dfs(j + 1, s, words, dp)); + } + } + + dp[i] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -316,6 +368,27 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinExtraChar(string s, string[] dictionary) { + HashSet words = new HashSet(dictionary); + int n = s.Length; + int[] dp = new int[n + 1]; + + for (int i = n - 1; i >= 0; i--) { + dp[i] = 1 + dp[i + 1]; + for (int j = i; j < n; j++) { + if (words.Contains(s.Substring(i, j - i + 1))) { + dp[i] = Math.Min(dp[i], dp[j + 1]); + } + } + } + + return dp[0]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -467,6 +540,43 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinExtraChar(string s, string[] dictionary) { + Dictionary dp = new Dictionary(); + dp[s.Length] = 0; + return Dfs(0, s, dictionary, dp); + } + + private int Dfs(int i, string s, string[] dictionary, Dictionary dp) { + if (dp.ContainsKey(i)) { + return dp[i]; + } + + int res = 1 + Dfs(i + 1, s, dictionary, dp); + + foreach (string word in dictionary) { + if (i + word.Length > s.Length) continue; + + bool flag = true; + for (int j = 0; j < word.Length; j++) { + if (s[i + j] != word[j]) { + flag = false; + break; + } + } + + if (flag) { + res = Math.Min(res, Dfs(i + word.Length, s, dictionary, dp)); + } + } + + dp[i] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -563,6 +673,26 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinExtraChar(string s, string[] dictionary) { + int n = s.Length; + int[] dp = new int[n + 1]; + + for (int i = n - 1; i >= 0; i--) { + dp[i] = 1 + dp[i + 1]; + foreach (string word in dictionary) { + if (i + word.Length <= n && s.Substring(i, word.Length) == word) { + dp[i] = Math.Min(dp[i], dp[i + word.Length]); + } + } + } + + return dp[0]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -819,6 +949,63 @@ class Solution { } ``` +```csharp +public class TrieNode { + public TrieNode[] Children = new TrieNode[26]; + public bool IsWord = false; +} + +public class Trie { + public TrieNode Root = new TrieNode(); + + public void AddWord(string word) { + TrieNode curr = Root; + foreach (char c in word) { + int idx = c - 'a'; + if (curr.Children[idx] == null) { + curr.Children[idx] = new TrieNode(); + } + curr = curr.Children[idx]; + } + curr.IsWord = true; + } +} + +public class Solution { + public int MinExtraChar(string s, string[] dictionary) { + Trie trie = new Trie(); + foreach (string word in dictionary) { + trie.AddWord(word); + } + + int[] dp = new int[s.Length + 1]; + Array.Fill(dp, -1); + + return Dfs(0, s, trie, dp); + } + + private int Dfs(int i, string s, Trie trie, int[] dp) { + if (i == s.Length) return 0; + if (dp[i] != -1) return dp[i]; + + int res = 1 + Dfs(i + 1, s, trie, dp); + TrieNode curr = trie.Root; + + for (int j = i; j < s.Length; j++) { + int idx = s[j] - 'a'; + if (curr.Children[idx] == null) break; + curr = curr.Children[idx]; + if (curr.IsWord) { + res = Math.Min(res, Dfs(j + 1, s, trie, dp)); + } + } + + dp[i] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1052,6 +1239,57 @@ class Solution { } ``` +```csharp +public class TrieNode { + public TrieNode[] Children = new TrieNode[26]; + public bool IsWord = false; +} + +public class Trie { + public TrieNode Root = new TrieNode(); + + public void AddWord(string word) { + TrieNode curr = Root; + foreach (char c in word) { + int idx = c - 'a'; + if (curr.Children[idx] == null) { + curr.Children[idx] = new TrieNode(); + } + curr = curr.Children[idx]; + } + curr.IsWord = true; + } +} + +public class Solution { + public int MinExtraChar(string s, string[] dictionary) { + Trie trie = new Trie(); + foreach (string word in dictionary) { + trie.AddWord(word); + } + + int n = s.Length; + int[] dp = new int[n + 1]; + + for (int i = n - 1; i >= 0; i--) { + dp[i] = 1 + dp[i + 1]; + TrieNode curr = trie.Root; + + for (int j = i; j < n; j++) { + int idx = s[j] - 'a'; + if (curr.Children[idx] == null) break; + curr = curr.Children[idx]; + if (curr.IsWord) { + dp[i] = Math.Min(dp[i], dp[j + 1]); + } + } + } + + return dp[0]; + } +} +``` + ::tabs-end ### Time & Space Complexity 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/find-duplicate-integer.md b/articles/find-duplicate-integer.md index 46542d9b6..ef3317436 100644 --- a/articles/find-duplicate-integer.md +++ b/articles/find-duplicate-integer.md @@ -99,6 +99,20 @@ class Solution { } ``` +```swift +class Solution { + func findDuplicate(_ nums: [Int]) -> Int { + var nums = nums.sorted() + for i in 0.. Int { + var seen = Set() + for num in nums { + if seen.contains(num) { + return num + } + seen.insert(num) + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -333,6 +362,21 @@ class Solution { } ``` +```swift +class Solution { + func findDuplicate(_ nums: [Int]) -> Int { + var seen = [Int](repeating: 0, count: nums.count) + for num in nums { + if seen[num - 1] == 1 { + return num + } + seen[num - 1] = 1 + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -457,6 +501,22 @@ class Solution { } ``` +```swift +class Solution { + func findDuplicate(_ nums: [Int]) -> Int { + var nums = nums + for num in nums { + let idx = abs(num) - 1 + if nums[idx] < 0 { + return abs(num) + } + nums[idx] *= -1 + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -656,6 +716,27 @@ class Solution { } ``` +```swift +class Solution { + func findDuplicate(_ nums: [Int]) -> Int { + let n = nums.count + var low = 1, high = n - 1 + + while low < high { + let mid = low + (high - low) / 2 + let lessOrEqual = nums.filter { $0 <= mid }.count + + if lessOrEqual <= mid { + low = mid + 1 + } else { + high = mid + } + } + return low + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -866,6 +947,37 @@ class Solution { } ``` +```swift +class Solution { + func findDuplicate(_ nums: [Int]) -> Int { + let n = nums.count + var res = 0 + + for b in 0..<32 { + var x = 0, y = 0 + let mask = 1 << b + + for num in nums { + if num & mask != 0 { + x += 1 + } + } + + for num in 1.. y { + res |= mask + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1052,6 +1164,31 @@ class Solution { } ``` +```swift +class Solution { + func findDuplicate(_ nums: [Int]) -> Int { + var slow = 0, fast = 0 + + while true { + slow = nums[slow] + fast = nums[nums[fast]] + if slow == fast { + break + } + } + + var slow2 = 0 + while true { + slow = nums[slow] + slow2 = nums[slow2] + if slow == slow2 { + return slow + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/find-in-mountain-array.md b/articles/find-in-mountain-array.md index f687ba271..c917a7507 100644 --- a/articles/find-in-mountain-array.md +++ b/articles/find-in-mountain-array.md @@ -78,18 +78,18 @@ public: /** * // This is the MountainArray's API interface. * // You should not implement it, or speculate about its implementation - * function MountainArray() { + * class MountainArray { * @param {number} index * @return {number} - * this.get = function(index) { + * get(index) { * ... - * }; + * } * * @return {number} - * this.length = function() { + * length() { * ... - * }; - * }; + * } + * } */ class Solution { @@ -112,6 +112,31 @@ class Solution { } ``` +```csharp +/** + * // This is MountainArray's API interface. + * // You should not implement it, or speculate about its implementation + * class MountainArray { + * public int Get(int index) {} + * public int Length() {} + * } + */ + +class Solution { + public int FindInMountainArray(int target, MountainArray mountainArr) { + int n = mountainArr.Length(); + + for (int i = 0; i < n; i++) { + if (mountainArr.Get(i) == target) { + return i; + } + } + + return -1; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -316,18 +341,18 @@ public: /** * // This is the MountainArray's API interface. * // You should not implement it, or speculate about its implementation - * function MountainArray() { + * class MountainArray { * @param {number} index * @return {number} - * this.get = function(index) { + * get(index) { * ... - * }; + * } * * @return {number} - * this.length = function() { + * length() { * ... - * }; - * }; + * } + * } */ class Solution { @@ -391,6 +416,72 @@ class Solution { } ``` +```csharp +/** + * // This is MountainArray's API interface. + * // You should not implement it, or speculate about its implementation + * class MountainArray { + * public int Get(int index) {} + * public int Length() {} + * } + */ + +class Solution { + public int FindInMountainArray(int target, MountainArray mountainArr) { + int length = mountainArr.Length(); + + // Find Peak + int l = 1, r = length - 2, peak = 0; + while (l <= r) { + int m = (l + r) / 2; + int left = mountainArr.Get(m - 1); + int mid = mountainArr.Get(m); + int right = mountainArr.Get(m + 1); + if (left < mid && mid < right) { + l = m + 1; + } else if (left > mid && mid > right) { + r = m - 1; + } else { + peak = m; + break; + } + } + + // Search left portion + l = 0; + r = peak - 1; + while (l <= r) { + int m = (l + r) / 2; + int val = mountainArr.Get(m); + if (val < target) { + l = m + 1; + } else if (val > target) { + r = m - 1; + } else { + return m; + } + } + + // Search right portion + l = peak; + r = length - 1; + while (l <= r) { + int m = (l + r) / 2; + int val = mountainArr.Get(m); + if (val > target) { + l = m + 1; + } else if (val < target) { + r = m - 1; + } else { + return m; + } + } + + return -1; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -600,18 +691,18 @@ public: /** * // This is the MountainArray's API interface. * // You should not implement it, or speculate about its implementation - * function MountainArray() { + * class MountainArray { * @param {number} index * @return {number} - * this.get = function(index) { + * get(index) { * ... - * }; + * } * * @return {number} - * this.length = function() { + * length() { * ... - * }; - * }; + * } + * } */ class Solution { @@ -676,6 +767,73 @@ class Solution { } ``` +```csharp +/** + * // This is MountainArray's API interface. + * // You should not implement it, or speculate about its implementation + * class MountainArray { + * public int Get(int index) {} + * public int Length() {} + * } + */ + +class Solution { + private Dictionary cache = new Dictionary(); + + private int Get(int index, MountainArray mountainArr) { + if (!cache.ContainsKey(index)) { + cache[index] = mountainArr.Get(index); + } + return cache[index]; + } + + private int BinarySearch(int l, int r, bool ascending, MountainArray mountainArr, int target) { + while (l <= r) { + int m = (l + r) >> 1; + int val = Get(m, mountainArr); + if (val == target) { + return m; + } + if ((ascending && val < target) || (!ascending && val > target)) { + l = m + 1; + } else { + r = m - 1; + } + } + return -1; + } + + public int FindInMountainArray(int target, MountainArray mountainArr) { + int length = mountainArr.Length(); + + // Find Peak + int l = 1, r = length - 2, peak = 0; + while (l <= r) { + int m = (l + r) >> 1; + int left = Get(m - 1, mountainArr); + int mid = Get(m, mountainArr); + int right = Get(m + 1, mountainArr); + + if (left < mid && mid < right) { + l = m + 1; + } else if (left > mid && mid > right) { + r = m - 1; + } else { + peak = m; + break; + } + } + + // Search left portion + int res = BinarySearch(0, peak, true, mountainArr, target); + if (res != -1) return res; + + // Search right portion + return BinarySearch(peak, length - 1, false, mountainArr, target); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/find-median-in-a-data-stream.md b/articles/find-median-in-a-data-stream.md index ab246b370..ad27aa749 100644 --- a/articles/find-median-in-a-data-stream.md +++ b/articles/find-median-in-a-data-stream.md @@ -162,6 +162,30 @@ class MedianFinder() { } ``` +```swift +class MedianFinder { + private var data: [Int] + + init() { + self.data = [] + } + + func addNum(_ num: Int) { + data.append(num) + } + + func findMedian() -> Double { + data.sort() + let n = data.count + if n % 2 == 1 { + return Double(data[n / 2]) + } else { + return (Double(data[n / 2]) + Double(data[n / 2 - 1])) / 2.0 + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -447,6 +471,47 @@ class MedianFinder() { } ``` +```swift +class MedianFinder { + // two heaps, large, small, minheap, maxheap + // heaps should be equal size + private var small: Heap + private var large: Heap + + init() { + self.small = Heap() + self.large = Heap() + } + + func addNum(_ num: Int) { + if let top = large.min, num > top { + large.insert(num) + } else { + small.insert(num) + } + if small.count > large.count + 1 { + if let val = small.popMax() { + large.insert(val) + } + } + if large.count > small.count + 1 { + if let val = large.popMin() { + small.insert(val) + } + } + } + + func findMedian() -> Double { + if small.count > large.count { + return Double(small.max!) + } else if large.count > small.count { + return Double(large.min!) + } + return (Double(small.max!) + Double(large.min!)) / 2.0 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/find-minimum-in-rotated-sorted-array.md b/articles/find-minimum-in-rotated-sorted-array.md index 3c4c59be9..9443959d2 100644 --- a/articles/find-minimum-in-rotated-sorted-array.md +++ b/articles/find-minimum-in-rotated-sorted-array.md @@ -65,6 +65,14 @@ class Solution { } ``` +```swift +class Solution { + func findMin(_ nums: [Int]) -> Int { + return nums.min()! + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -261,6 +269,32 @@ class Solution { } ``` +```swift +class Solution { + func findMin(_ nums: [Int]) -> Int { + var res = nums[0] + var l = 0, r = nums.count - 1 + + while l <= r { + if nums[l] < nums[r] { + res = min(res, nums[l]) + break + } + + let m = (l + r) / 2 + res = min(res, nums[m]) + + if nums[m] >= nums[l] { + l = m + 1 + } else { + r = m - 1 + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -396,6 +430,23 @@ class Solution { } ``` +```swift +class Solution { + func findMin(_ nums: [Int]) -> Int { + var l = 0, r = nums.count - 1 + while l < r { + let m = l + (r - l) / 2 + if nums[m] < nums[r] { + r = m + } else { + l = m + 1 + } + } + return nums[l] + } +} +``` + ::tabs-end ### Time & Space Complexity 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/find-target-in-rotated-sorted-array.md b/articles/find-target-in-rotated-sorted-array.md index 2e6dd37e5..b406838bb 100644 --- a/articles/find-target-in-rotated-sorted-array.md +++ b/articles/find-target-in-rotated-sorted-array.md @@ -93,6 +93,19 @@ class Solution { } ``` +```swift +class Solution { + func search(_ nums: [Int], _ target: Int) -> Int { + for i in 0.. Int { + var l = 0, r = nums.count - 1 + + while l < r { + let m = (l + r) / 2 + if nums[m] > nums[r] { + l = m + 1 + } else { + r = m + } + } + + let pivot = l + + func binarySearch(_ left: Int, _ right: Int) -> Int { + var l = left, r = right + while l <= r { + let mid = (l + r) / 2 + if nums[mid] == target { + return mid + } else if nums[mid] < target { + l = mid + 1 + } else { + r = mid - 1 + } + } + return -1 + } + + let result = binarySearch(0, pivot - 1) + if result != -1 { + return result + } + + return binarySearch(pivot, nums.count - 1) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -681,6 +735,46 @@ class Solution { } ``` +```swift +class Solution { + func search(_ nums: [Int], _ target: Int) -> Int { + var l = 0, r = nums.count - 1 + + while l < r { + let m = (l + r) / 2 + if nums[m] > nums[r] { + l = m + 1 + } else { + r = m + } + } + + let pivot = l + l = 0 + r = nums.count - 1 + + if target >= nums[pivot] && target <= nums[r] { + l = pivot + } else { + r = pivot - 1 + } + + while l <= r { + let m = (l + r) / 2 + if nums[m] == target { + return m + } else if nums[m] < target { + l = m + 1 + } else { + r = m - 1 + } + } + + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -908,6 +1002,36 @@ class Solution { } ``` +```swift +class Solution { + func search(_ nums: [Int], _ target: Int) -> Int { + var l = 0, r = nums.count - 1 + + while l <= r { + let mid = (l + r) / 2 + if target == nums[mid] { + return mid + } + + if nums[l] <= nums[mid] { + if target > nums[mid] || target < nums[l] { + l = mid + 1 + } else { + r = mid - 1 + } + } else { + if target < nums[mid] || target > nums[r] { + r = mid - 1 + } else { + l = mid + 1 + } + } + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/find-the-town-judge.md b/articles/find-the-town-judge.md index 393448cd8..a1343bd35 100644 --- a/articles/find-the-town-judge.md +++ b/articles/find-the-town-judge.md @@ -89,6 +89,30 @@ class Solution { } ``` +```csharp +public class Solution { + public int FindJudge(int n, int[][] trust) { + int[] incoming = new int[n + 1]; + int[] outgoing = new int[n + 1]; + + foreach (int[] t in trust) { + int a = t[0]; + int b = t[1]; + outgoing[a]++; + incoming[b]++; + } + + for (int i = 1; i <= n; i++) { + if (outgoing[i] == 0 && incoming[i] == n - 1) { + return i; + } + } + + return -1; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -189,6 +213,28 @@ class Solution { } ``` +```csharp +public class Solution { + public int FindJudge(int n, int[][] trust) { + int[] delta = new int[n + 1]; + + foreach (int[] t in trust) { + int a = t[0]; + int b = t[1]; + delta[a]--; + delta[b]++; + } + + for (int i = 1; i <= n; i++) { + if (delta[i] == n - 1) { + return i; + } + } + return -1; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/first-missing-positive.md b/articles/first-missing-positive.md index f0bef0643..09f5f9678 100644 --- a/articles/first-missing-positive.md +++ b/articles/first-missing-positive.md @@ -80,6 +80,31 @@ class Solution { } ``` +```csharp +public class Solution { + public int FirstMissingPositive(int[] nums) { + int missing = 1; + + while (true) { + bool found = false; + + foreach (int num in nums) { + if (num == missing) { + found = true; + break; + } + } + + if (!found) { + return missing; + } + + missing++; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -183,6 +208,29 @@ class Solution { } ``` +```csharp +public class Solution { + public int FirstMissingPositive(int[] nums) { + int n = nums.Length; + bool[] seen = new bool[n]; + + foreach (int num in nums) { + if (num > 0 && num <= n) { + seen[num - 1] = true; + } + } + + for (int num = 1; num <= n; num++) { + if (!seen[num - 1]) { + return num; + } + } + + return n + 1; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -257,6 +305,23 @@ class Solution { } ``` +```csharp +public class Solution { + public int FirstMissingPositive(int[] nums) { + Array.Sort(nums); + int missing = 1; + + foreach (int num in nums) { + if (num > 0 && num == missing) { + missing++; + } + } + + return missing; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -396,6 +461,39 @@ class Solution { } ``` +```csharp +public class Solution { + public int FirstMissingPositive(int[] nums) { + int n = nums.Length; + + for (int i = 0; i < n; i++) { + if (nums[i] < 0) { + nums[i] = 0; + } + } + + for (int i = 0; i < n; i++) { + int val = Math.Abs(nums[i]); + if (val >= 1 && val <= n) { + if (nums[val - 1] > 0) { + nums[val - 1] *= -1; + } else if (nums[val - 1] == 0) { + nums[val - 1] = -(n + 1); + } + } + } + + for (int i = 0; i < n; i++) { + if (nums[i] >= 0) { + return i + 1; + } + } + + return n + 1; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -528,6 +626,39 @@ class Solution { } ``` +```csharp +public class Solution { + public int FirstMissingPositive(int[] nums) { + int n = nums.Length; + int i = 0; + + while (i < n) { + if (nums[i] <= 0 || nums[i] > n) { + i++; + continue; + } + + int index = nums[i] - 1; + if (nums[i] != nums[index]) { + int temp = nums[i]; + nums[i] = nums[index]; + nums[index] = temp; + } else { + i++; + } + } + + for (i = 0; i < n; i++) { + if (nums[i] != i + 1) { + return i + 1; + } + } + + return n + 1; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/foreign-dictionary.md b/articles/foreign-dictionary.md index f1353b74a..1bb32e486 100644 --- a/articles/foreign-dictionary.md +++ b/articles/foreign-dictionary.md @@ -405,6 +405,65 @@ class Solution { } ``` +```swift +class Solution { + func foreignDictionary(_ words: [String]) -> String { + var adj = [Character: Set]() + for word in words { + for char in word { + if adj[char] == nil { + adj[char] = Set() + } + } + } + + for i in 0.. w2.count && String(w1.prefix(minLen)) == String(w2.prefix(minLen)) { + return "" + } + for j in 0.. Bool { + if let flag = visited[char] { + return flag + } + visited[char] = true + for neigh in adj[char]! { + if dfs(neigh) { + return true + } + } + visited[char] = false + res.append(char) + return false + } + + for char in adj.keys { + if dfs(char) { + return "" + } + } + + res.reverse() + return String(res) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -823,6 +882,69 @@ class Solution { } ``` +```swift +class Solution { + func foreignDictionary(_ words: [String]) -> String { + var adj = [Character: Set]() + for word in words { + for char in word { + adj[char] = Set() + } + } + + var indegree = [Character: Int]() + for key in adj.keys { + indegree[key] = 0 + } + + for i in 0.. w2.count && String(w1.prefix(minLen)) == String(w2.prefix(minLen)) { + return "" + } + let w1Arr = Array(w1) + let w2Arr = Array(w2) + for j in 0..() + for (c, deg) in indegree { + if deg == 0 { + q.append(c) + } + } + + var res = [Character]() + while !q.isEmpty { + let char = q.removeFirst() + res.append(char) + for neighbor in adj[char]! { + indegree[neighbor]! -= 1 + if indegree[neighbor]! == 0 { + q.append(neighbor) + } + } + } + + if res.count != indegree.count { + return "" + } + + return String(res) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/gas-station.md b/articles/gas-station.md index cedbf31c2..9e779b1d8 100644 --- a/articles/gas-station.md +++ b/articles/gas-station.md @@ -11,6 +11,7 @@ class Solution: tank = gas[i] - cost[i] if tank < 0: continue + j = (i + 1) % n while j != i: tank += gas[j] @@ -19,6 +20,7 @@ class Solution: break j += 1 j %= n + if j == i: return i return -1 @@ -32,12 +34,14 @@ public class Solution { for (int i = 0; i < n; i++) { int tank = gas[i] - cost[i]; if (tank < 0) continue; + int j = (i + 1) % n; while (j != i) { tank += gas[j] - cost[j]; if (tank < 0) break; j = (j + 1) % n; } + if (j == i) return i; } return -1; @@ -54,12 +58,14 @@ public: for (int i = 0; i < n; i++) { int tank = gas[i] - cost[i]; if (tank < 0) continue; + int j = (i + 1) % n; while (j != i) { tank += gas[j] - cost[j]; if (tank < 0) break; j = (j + 1) % n; } + if (j == i) return i; } return -1; @@ -80,12 +86,14 @@ class Solution { for (let i = 0; i < n; i++) { let tank = gas[i] - cost[i]; if (tank < 0) continue; + let j = (i + 1) % n; while (j !== i) { tank += gas[j] - cost[j]; if (tank < 0) break; j = (j + 1) % n; } + if (j === i) return i; } return -1; @@ -101,14 +109,17 @@ public class Solution { for (int i = 0; i < n; i++) { int tank = gas[i] - cost[i]; if (tank < 0) continue; + int j = (i + 1) % n; while (j != i) { tank += gas[j] - cost[j]; if (tank < 0) break; j = (j + 1) % n; } + if (j == i) return i; } + return -1; } } @@ -117,11 +128,13 @@ public class Solution { ```go func canCompleteCircuit(gas []int, cost []int) int { n := len(gas) + for i := 0; i < n; i++ { tank := gas[i] - cost[i] if tank < 0 { continue } + j := (i + 1) % n for j != i { tank += gas[j] @@ -131,10 +144,12 @@ func canCompleteCircuit(gas []int, cost []int) int { } j = (j + 1) % n } + if j == i { return i } } + return -1 } ``` @@ -166,6 +181,38 @@ class Solution { } ``` +```swift +class Solution { + func canCompleteCircuit(_ gas: [Int], _ cost: [Int]) -> Int { + let n = gas.count + + for i in 0.. Int { + let n = gas.count + var start = n - 1 + var end = 0 + var tank = gas[start] - cost[start] + + while start > end { + if tank < 0 { + start -= 1 + tank += gas[start] - cost[start] + } else { + tank += gas[end] - cost[end] + end += 1 + } + } + + return tank >= 0 ? start : -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -510,6 +580,29 @@ class Solution { } ``` +```swift +class Solution { + func canCompleteCircuit(_ gas: [Int], _ cost: [Int]) -> Int { + if gas.reduce(0, +) < cost.reduce(0, +) { + return -1 + } + + var total = 0 + var res = 0 + for i in 0.. [String] { + var res = [String]() + + func isValid(_ s: String) -> Bool { + var open = 0 + for c in s { + open += (c == "(") ? 1 : -1 + if open < 0 { + return false + } + } + return open == 0 + } + + func dfs(_ s: String) { + if s.count == n * 2 { + if isValid(s) { + res.append(s) + } + return + } + dfs(s + "(") + dfs(s + ")") + } + + dfs("") + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -442,6 +475,37 @@ class Solution { } ``` +```swift +class Solution { + func generateParenthesis(_ n: Int) -> [String] { + var stack = [Character]() + var res = [String]() + + func backtrack(_ openN: Int, _ closedN: Int) { + if openN == n && closedN == n { + res.append(String(stack)) + return + } + + if openN < n { + stack.append("(") + backtrack(openN + 1, closedN) + stack.removeLast() + } + + if closedN < openN { + stack.append(")") + backtrack(openN, closedN + 1) + stack.removeLast() + } + } + + backtrack(0, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -606,6 +670,27 @@ class Solution { } ``` +```swift +class Solution { + func generateParenthesis(_ n: Int) -> [String] { + var res = [[String]](repeating: [], count: n + 1) + res[0] = [""] + + for k in 0...n { + for i in 0..[] adj = new List[n]; + for (int i = 0; i < n; i++) { + adj[i] = new List(); + } + + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + if (GCD(nums[i], nums[j]) > 1) { + adj[i].Add(j); + adj[j].Add(i); + } + } + } + + void DFS(int node) { + visited[node] = true; + foreach (int neighbor in adj[node]) { + if (!visited[neighbor]) { + DFS(neighbor); + } + } + } + + DFS(0); + foreach (bool v in visited) { + if (!v) return false; + } + + return true; + } + + private int GCD(int a, int b) { + while (b != 0) { + int temp = b; + b = a % b; + a = temp; + } + return a; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -189,7 +236,7 @@ class Solution: uf = UnionFind(len(nums)) factor_index = {} # f -> index of value with factor f - for i, num in enumerate(nums): + for i, n in enumerate(nums): f = 2 while f * f <= n: if n % f == 0: @@ -206,7 +253,7 @@ class Solution: else: factor_index[n] = i - return uf.isConnected() + return uf.isConnected() ``` ```java @@ -452,6 +499,87 @@ class Solution { } ``` +```csharp +public class Solution { + public class UnionFind { + public int Count; + private int[] Parent; + private int[] Size; + + public UnionFind(int n) { + Count = n; + Parent = new int[n]; + Size = new int[n]; + for (int i = 0; i < n; i++) { + Parent[i] = i; + Size[i] = 1; + } + } + + public int Find(int x) { + if (Parent[x] != x) { + Parent[x] = Find(Parent[x]); + } + return Parent[x]; + } + + public bool Union(int x, int y) { + int px = Find(x); + int py = Find(y); + if (px == py) return false; + Count--; + if (Size[px] < Size[py]) { + int temp = px; + px = py; + py = temp; + } + Size[px] += Size[py]; + Parent[py] = px; + return true; + } + + public bool IsConnected() { + return Count == 1; + } + } + + public bool CanTraverseAllPairs(int[] nums) { + int n = nums.Length; + if (n == 1) return true; + if (Array.Exists(nums, x => x == 1)) return false; + + UnionFind uf = new UnionFind(n); + Dictionary factorIndex = new Dictionary(); + + for (int i = 0; i < n; i++) { + int num = nums[i]; + int original = num; + for (int f = 2; f * f <= num; f++) { + if (num % f == 0) { + if (factorIndex.ContainsKey(f)) { + uf.Union(i, factorIndex[f]); + } else { + factorIndex[f] = i; + } + while (num % f == 0) { + num /= f; + } + } + } + if (num > 1) { + if (factorIndex.ContainsKey(num)) { + uf.Union(i, factorIndex[num]); + } else { + factorIndex[num] = i; + } + } + } + + return uf.IsConnected(); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -790,6 +918,86 @@ class Solution { } ``` +```csharp +public class UnionFind { + public int[] Parent; + public int[] Size; + + public UnionFind(int n) { + Parent = new int[n]; + Size = new int[n]; + for (int i = 0; i < n; i++) { + Parent[i] = i; + Size[i] = 1; + } + } + + public int Find(int x) { + if (Parent[x] != x) { + Parent[x] = Find(Parent[x]); + } + return Parent[x]; + } + + public bool Union(int x, int y) { + int px = Find(x); + int py = Find(y); + if (px == py) return false; + if (Size[px] < Size[py]) { + int temp = px; + px = py; + py = temp; + } + Parent[py] = px; + Size[px] += Size[py]; + return true; + } +} + +public class Solution { + public bool CanTraverseAllPairs(int[] nums) { + int n = nums.Length; + if (n == 1) return true; + if (Array.Exists(nums, x => x == 1)) return false; + + int maxVal = nums.Max(); + int[] sieve = new int[maxVal + 1]; + for (int i = 2; i * i <= maxVal; i++) { + if (sieve[i] == 0) { + for (int j = i * i; j <= maxVal; j += i) { + if (sieve[j] == 0) sieve[j] = i; + } + } + } + + UnionFind uf = new UnionFind(n + maxVal + 1); + + for (int i = 0; i < n; i++) { + int num = nums[i]; + if (sieve[num] == 0) { + uf.Union(i, n + num); + continue; + } + + while (num > 1) { + int prime = sieve[num] != 0 ? sieve[num] : num; + uf.Union(i, n + prime); + while (num % prime == 0) { + num /= prime; + } + } + } + + int root = uf.Find(0); + for (int i = 1; i < n; i++) { + if (uf.Find(i) != root) return false; + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1029,6 +1237,70 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CanTraverseAllPairs(int[] nums) { + int N = nums.Length; + if (N == 1) return true; + if (Array.Exists(nums, num => num == 1)) return false; + + int MAX = nums.Max(); + int[] sieve = new int[MAX + 1]; + for (int p = 2; p * p <= MAX; p++) { + if (sieve[p] == 0) { + for (int mult = p * p; mult <= MAX; mult += p) { + if (sieve[mult] == 0) { + sieve[mult] = p; + } + } + } + } + + Dictionary> adj = new Dictionary>(); + for (int i = 0; i < N; i++) { + int num = nums[i]; + if (sieve[num] == 0) { + AddEdge(adj, i, N + num); + continue; + } + while (num > 1) { + int prime = sieve[num] != 0 ? sieve[num] : num; + AddEdge(adj, i, N + prime); + while (num % prime == 0) { + num /= prime; + } + } + } + + HashSet visited = new HashSet(); + DFS(0, adj, visited); + + for (int i = 0; i < N; i++) { + if (!visited.Contains(i)) return false; + } + + return true; + } + + private void AddEdge(Dictionary> adj, int u, int v) { + if (!adj.ContainsKey(u)) adj[u] = new List(); + if (!adj.ContainsKey(v)) adj[v] = new List(); + adj[u].Add(v); + adj[v].Add(u); + } + + private void DFS(int node, Dictionary> adj, HashSet visited) { + visited.Add(node); + if (!adj.ContainsKey(node)) return; + foreach (int nei in adj[node]) { + if (!visited.Contains(nei)) { + DFS(nei, adj, visited); + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1295,6 +1567,74 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CanTraverseAllPairs(int[] nums) { + int N = nums.Length; + if (N == 1) return true; + if (nums.Contains(1)) return false; + + int MAX = nums.Max(); + int[] sieve = new int[MAX + 1]; + for (int p = 2; p * p <= MAX; p++) { + if (sieve[p] == 0) { + for (int composite = p * p; composite <= MAX; composite += p) { + if (sieve[composite] == 0) { + sieve[composite] = p; + } + } + } + } + + Dictionary> adj = new Dictionary>(); + for (int i = 0; i < N; i++) { + int num = nums[i]; + if (sieve[num] == 0) { + AddEdge(adj, i, N + num); + continue; + } + + while (num > 1) { + int prime = sieve[num] != 0 ? sieve[num] : num; + AddEdge(adj, i, N + prime); + while (num % prime == 0) { + num /= prime; + } + } + } + + HashSet visited = new HashSet(); + Queue queue = new Queue(); + queue.Enqueue(0); + visited.Add(0); + + while (queue.Count > 0) { + int node = queue.Dequeue(); + if (!adj.ContainsKey(node)) continue; + foreach (int nei in adj[node]) { + if (!visited.Contains(nei)) { + visited.Add(nei); + queue.Enqueue(nei); + } + } + } + + for (int i = 0; i < N; i++) { + if (!visited.Contains(i)) return false; + } + + return true; + } + + private void AddEdge(Dictionary> adj, int u, int v) { + if (!adj.ContainsKey(u)) adj[u] = new List(); + if (!adj.ContainsKey(v)) adj[v] = new List(); + adj[u].Add(v); + adj[v].Add(u); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/guess-number-higher-or-lower.md b/articles/guess-number-higher-or-lower.md index b6053e2e8..4946e4968 100644 --- a/articles/guess-number-higher-or-lower.md +++ b/articles/guess-number-higher-or-lower.md @@ -65,7 +65,7 @@ public: * @return -1 if num is higher than the picked number * 1 if num is lower than the picked number * otherwise return 0 - * var guess = function(num) {} + * function guess(num) {} */ class Solution { @@ -82,6 +82,26 @@ class Solution { } ``` +```csharp +/** + * Forward declaration of guess API. + * @param num your guess + * @return -1 if num is higher than the picked number + * 1 if num is lower than the picked number + * otherwise return 0 + * int guess(int num); + */ + +public class Solution : GuessGame { + public int GuessNumber(int n) { + for (int num = 1; num <= n; num++) { + if (guess(num) == 0) return num; + } + return n; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -181,7 +201,7 @@ public: * @return -1 if num is higher than the picked number * 1 if num is lower than the picked number * otherwise return 0 - * var guess = function(num) {} + * function guess(num) {} */ class Solution { @@ -206,6 +226,26 @@ class Solution { } ``` +```csharp +/** + * Forward declaration of guess API. + * @param num your guess + * @return -1 if num is higher than the picked number + * 1 if num is lower than the picked number + * otherwise return 0 + * int guess(int num); + */ + +public class Solution : GuessGame { + public int GuessNumber(int n) { + for (int num = 1; num <= n; num++) { + if (guess(num) == 0) return num; + } + return n; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -316,7 +356,7 @@ public: * @return -1 if num is higher than the picked number * 1 if num is lower than the picked number * otherwise return 0 - * var guess = function(num) {} + * function guess(num) {} */ class Solution { @@ -344,6 +384,41 @@ class Solution { } ``` +```csharp +/** + * Forward declaration of guess API. + * @param num your guess + * @return -1 if num is higher than the picked number + * 1 if num is lower than the picked number + * otherwise return 0 + * int guess(int num); + */ + +public class Solution : GuessGame { + public int GuessNumber(int n) { + int l = 1, r = n; + while (true) { + int m1 = l + (r - l) / 3; + int m2 = r - (r - l) / 3; + + if (guess(m1) == 0) return m1; + if (guess(m2) == 0) return m2; + + if (guess(m1) + guess(m2) == 0) { + l = m1 + 1; + r = m2 - 1; + } + else if (guess(m1) == -1) { + r = m1 - 1; + } + else { + l = m2 + 1; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/hand-of-straights.md b/articles/hand-of-straights.md index 728447cc2..773278b86 100644 --- a/articles/hand-of-straights.md +++ b/articles/hand-of-straights.md @@ -7,6 +7,7 @@ class Solution: def isNStraightHand(self, hand, groupSize): if len(hand) % groupSize: return False + count = Counter(hand) hand.sort() for num in hand: @@ -22,10 +23,12 @@ class Solution: public class Solution { public boolean isNStraightHand(int[] hand, int groupSize) { if (hand.length % groupSize != 0) return false; + Map count = new HashMap<>(); for (int num : hand) { count.put(num, count.getOrDefault(num, 0) + 1); } + Arrays.sort(hand); for (int num : hand) { if (count.get(num) > 0) { @@ -45,8 +48,10 @@ class Solution { public: bool isNStraightHand(vector& hand, int groupSize) { if (hand.size() % groupSize != 0) return false; + unordered_map count; for (int num : hand) count[num]++; + sort(hand.begin(), hand.end()); for (int num : hand) { if (count[num] > 0) { @@ -72,10 +77,12 @@ class Solution { if (hand.length % groupSize !== 0) { return false; } + const count = {}; for (const num of hand) { count[num] = (count[num] || 0) + 1; } + hand.sort((a, b) => a - b); for (const num of hand) { if (count[num] > 0) { @@ -94,10 +101,12 @@ class Solution { public class Solution { public bool IsNStraightHand(int[] hand, int groupSize) { if (hand.Length % groupSize != 0) return false; + var count = new Dictionary(); foreach (var num in hand) { count[num] = count.GetValueOrDefault(num, 0) + 1; } + Array.Sort(hand); foreach (var num in hand) { if (count[num] > 0) { @@ -164,6 +173,36 @@ class Solution { } ``` +```swift +class Solution { + func isNStraightHand(_ hand: [Int], _ groupSize: Int) -> Bool { + if hand.count % groupSize != 0 { + return false + } + + var count = [Int: Int]() + for num in hand { + count[num, default: 0] += 1 + } + + let sortedHand = hand.sorted() + for num in sortedHand { + if let freq = count[num], freq > 0 { + for i in num..<(num + groupSize) { + if let f = count[i], f > 0 { + count[i] = f - 1 + } else { + return false + } + } + } + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -410,6 +449,40 @@ class Solution { } ``` +```swift +class Solution { + func isNStraightHand(_ hand: [Int], _ groupSize: Int) -> Bool { + if hand.count % groupSize != 0 { + return false + } + + var count = [Int: Int]() + for n in hand { + count[n, default: 0] += 1 + } + + var minH = Heap(Array(count.keys)) + + while !minH.isEmpty { + guard let first = minH.min else { return false } + + for i in first..<(first + groupSize) { + guard let freq = count[i] else { return false } + count[i] = freq - 1 + if count[i] == 0 { + if i != minH.min { + return false + } + minH.removeMin() + } + } + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -655,6 +728,40 @@ class Solution { } ``` +```swift +class Solution { + func isNStraightHand(_ hand: [Int], _ groupSize: Int) -> Bool { + if hand.count % groupSize != 0 { + return false + } + + var count = [Int: Int]() + for num in hand { + count[num, default: 0] += 1 + } + + var queue = Deque() + var lastNum = -1 + var openGroups = 0 + + for (num, numCount) in count.sorted(by: { $0.key < $1.key }) { + if (openGroups > 0 && num > lastNum + 1) || openGroups > numCount { + return false + } + + queue.append(numCount - openGroups) + lastNum = num + openGroups = numCount + + if queue.count == groupSize { + openGroups -= queue.removeFirst() + } + } + return openGroups == 0 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -673,6 +780,7 @@ class Solution: def isNStraightHand(self, hand: List[int], groupSize: int) -> bool: if len(hand) % groupSize != 0: return False + count = Counter(hand) for num in hand: start = num @@ -692,6 +800,7 @@ class Solution: public class Solution { public boolean isNStraightHand(int[] hand, int groupSize) { if (hand.length % groupSize != 0) return false; + Map count = new HashMap<>(); for (int num : hand) { count.put(num, count.getOrDefault(num, 0) + 1); @@ -720,6 +829,7 @@ class Solution { public: bool isNStraightHand(vector& hand, int groupSize) { if (hand.size() % groupSize != 0) return false; + unordered_map count; for (int num : hand) count[num]++; @@ -750,6 +860,7 @@ class Solution { */ isNStraightHand(hand, groupSize) { if (hand.length % groupSize !== 0) return false; + const count = new Map(); hand.forEach(num => count.set(num, (count.get(num) || 0) + 1)); @@ -775,6 +886,7 @@ class Solution { public class Solution { public bool IsNStraightHand(int[] hand, int groupSize) { if (hand.Length % groupSize != 0) return false; + Dictionary count = new Dictionary(); foreach (int num in hand) { if (!count.ContainsKey(num)) count[num] = 0; @@ -867,6 +979,41 @@ class Solution { } ``` +```swift +class Solution { + func isNStraightHand(_ hand: [Int], _ groupSize: Int) -> Bool { + if hand.count % groupSize != 0 { + return false + } + + var count = [Int: Int]() + for num in hand { + count[num, default: 0] += 1 + } + + for num in hand { + var start = num + while (count[start - 1] ?? 0) > 0 { + start -= 1 + } + while start <= num { + while (count[start] ?? 0) > 0 { + for i in start..<(start + groupSize) { + if (count[i] ?? 0) == 0 { + return false + } + count[i]! -= 1 + } + } + start += 1 + } + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity 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/house-robber-ii.md b/articles/house-robber-ii.md index 9157646c6..0469d73df 100644 --- a/articles/house-robber-ii.md +++ b/articles/house-robber-ii.md @@ -131,6 +131,25 @@ class Solution { } ``` +```swift +class Solution { + func rob(_ nums: [Int]) -> Int { + if nums.count == 1 { + return nums[0] + } + + func dfs(_ i: Int, _ flag: Bool) -> Int { + if i >= nums.count || (flag && i == nums.count - 1) { + return 0 + } + return max(dfs(i + 1, flag), nums[i] + dfs(i + 2, flag || i == 0)) + } + + return max(dfs(0, true), dfs(1, false)) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -336,6 +355,35 @@ class Solution { } ``` +```swift +class Solution { + func rob(_ nums: [Int]) -> Int { + if nums.count == 1 { + return nums[0] + } + + var memo = Array(repeating: Array(repeating: -1, count: 2), count: nums.count) + + func dfs(_ i: Int, _ flag: Bool) -> Int { + if i >= nums.count || (flag && i == nums.count - 1) { + return 0 + } + if memo[i][flag ? 1 : 0] != -1 { + return memo[i][flag ? 1 : 0] + } + + memo[i][flag ? 1 : 0] = max( + dfs(i + 1, flag), nums[i] + dfs(i + 2, flag || i == 0) + ) + + return memo[i][flag ? 1 : 0] + } + + return max(dfs(0, true), dfs(1, false)) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -553,6 +601,36 @@ class Solution { } ``` +```swift +class Solution { + func rob(_ nums: [Int]) -> Int { + if nums.count == 1 { + return nums[0] + } + return max(helper(Array(nums[1...])), helper(Array(nums[..<(nums.count - 1)]))) + } + + func helper(_ nums: [Int]) -> Int { + if nums.isEmpty { + return 0 + } + if nums.count == 1 { + return nums[0] + } + + var dp = [Int](repeating: 0, count: nums.count) + dp[0] = nums[0] + dp[1] = max(nums[0], nums[1]) + + for i in 2.. Int { + if nums.isEmpty { + return 0 + } + if nums.count == 1 { + return nums[0] + } + + let candidate1 = nums[0] + let candidate2 = helper(Array(nums[1.. Int { + var rob1 = 0 + var rob2 = 0 + + for num in nums { + let newRob = max(rob1 + num, rob2) + rob1 = rob2 + rob2 = newRob + } + + return rob2 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/house-robber-iii.md b/articles/house-robber-iii.md index 08d521c95..a09238c6b 100644 --- a/articles/house-robber-iii.md +++ b/articles/house-robber-iii.md @@ -128,6 +128,38 @@ class Solution { } ``` +```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 int Rob(TreeNode root) { + if (root == null) return 0; + + int res = root.val; + if (root.left != null) { + res += Rob(root.left.left) + Rob(root.left.right); + } + if (root.right != null) { + res += Rob(root.right.left) + Rob(root.right.right); + } + + res = Math.Max(res, Rob(root.left) + Rob(root.right)); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -299,6 +331,46 @@ class Solution { } ``` +```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 cache = new(); + + public int Rob(TreeNode root) { + return Dfs(root); + } + + private int Dfs(TreeNode root) { + if (root == null) return 0; + if (cache.ContainsKey(root)) return cache[root]; + + int res = root.val; + if (root.left != null) { + res += Dfs(root.left.left) + Dfs(root.left.right); + } + if (root.right != null) { + res += Dfs(root.right.left) + Dfs(root.right.right); + } + + res = Math.Max(res, Dfs(root.left) + Dfs(root.right)); + cache[root] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -449,6 +521,40 @@ class Solution { } ``` +```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 int Rob(TreeNode root) { + var result = Dfs(root); + return Math.Max(result.withRoot, result.withoutRoot); + } + + private (int withRoot, int withoutRoot) Dfs(TreeNode root) { + if (root == null) return (0, 0); + + var left = Dfs(root.left); + var right = Dfs(root.right); + + int withRoot = root.val + left.withoutRoot + right.withoutRoot; + int withoutRoot = Math.Max(left.withRoot, left.withoutRoot) + Math.Max(right.withRoot, right.withoutRoot); + + return (withRoot, withoutRoot); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/house-robber.md b/articles/house-robber.md index 6122135cb..22be9ba02 100644 --- a/articles/house-robber.md +++ b/articles/house-robber.md @@ -118,6 +118,21 @@ class Solution { } ``` +```swift +class Solution { + func rob(_ nums: [Int]) -> Int { + func dfs(_ i: Int) -> Int { + if i >= nums.count { + return 0 + } + return max(dfs(i + 1), nums[i] + dfs(i + 2)) + } + + return dfs(0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -291,6 +306,27 @@ class Solution { } ``` +```swift +class Solution { + func rob(_ nums: [Int]) -> Int { + var memo = Array(repeating: -1, count: nums.count) + + func dfs(_ i: Int) -> Int { + if i >= nums.count { + return 0 + } + if memo[i] != -1 { + return memo[i] + } + memo[i] = max(dfs(i + 1), nums[i] + dfs(i + 2)) + return memo[i] + } + + return dfs(0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -455,6 +491,29 @@ class Solution { } ``` +```swift +class Solution { + func rob(_ nums: [Int]) -> Int { + if nums.isEmpty { + return 0 + } + if nums.count == 1 { + return nums[0] + } + + var dp = Array(repeating: 0, count: nums.count) + dp[0] = nums[0] + dp[1] = max(nums[0], nums[1]) + + for i in 2.. Int { + var rob1 = 0, rob2 = 0 + + for num in nums { + let temp = max(num + rob1, rob2) + rob1 = rob2 + rob2 = temp + } + + return rob2 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/implement-prefix-tree.md b/articles/implement-prefix-tree.md index 493258c7b..3e4a303f2 100644 --- a/articles/implement-prefix-tree.md +++ b/articles/implement-prefix-tree.md @@ -363,6 +363,62 @@ class PrefixTree { } ``` +```swift +class TrieNode { + var children: [TrieNode?] + var endOfWord: Bool + + init() { + self.children = Array(repeating: nil, count: 26) + self.endOfWord = false + } +} + +class PrefixTree { + private let root: TrieNode + + init() { + self.root = TrieNode() + } + + func insert(_ word: String) { + var cur = root + for c in word { + let i = Int(c.asciiValue! - Character("a").asciiValue!) + if cur.children[i] == nil { + cur.children[i] = TrieNode() + } + cur = cur.children[i]! + } + cur.endOfWord = true + } + + func search(_ word: String) -> Bool { + var cur = root + for c in word { + let i = Int(c.asciiValue! - Character("a").asciiValue!) + if cur.children[i] == nil { + return false + } + cur = cur.children[i]! + } + return cur.endOfWord + } + + func startsWith(_ prefix: String) -> Bool { + var cur = root + for c in prefix { + let i = Int(c.asciiValue! - Character("a").asciiValue!) + if cur.children[i] == nil { + return false + } + cur = cur.children[i]! + } + return true + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -708,6 +764,59 @@ class PrefixTree { } ``` +```swift +class TrieNode { + var children: [Character: TrieNode] + var endOfWord: Bool + + init() { + self.children = [:] + self.endOfWord = false + } +} + +class PrefixTree { + private let root: TrieNode + + init() { + self.root = TrieNode() + } + + func insert(_ word: String) { + var cur = root + for c in word { + if cur.children[c] == nil { + cur.children[c] = TrieNode() + } + cur = cur.children[c]! + } + cur.endOfWord = true + } + + func search(_ word: String) -> Bool { + var cur = root + for c in word { + if cur.children[c] == nil { + return false + } + cur = cur.children[c]! + } + return cur.endOfWord + } + + func startsWith(_ prefix: String) -> Bool { + var cur = root + for c in prefix { + if cur.children[c] == nil { + return false + } + cur = cur.children[c]! + } + return true + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/insert-into-a-binary-search-tree.md b/articles/insert-into-a-binary-search-tree.md index d8597610b..fe0604c3a 100644 --- a/articles/insert-into-a-binary-search-tree.md +++ b/articles/insert-into-a-binary-search-tree.md @@ -118,6 +118,37 @@ class Solution { } ``` +```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 TreeNode InsertIntoBST(TreeNode root, int val) { + if (root == null) { + return new TreeNode(val); + } + + if (val > root.val) { + root.right = InsertIntoBST(root.right, val); + } else { + root.left = InsertIntoBST(root.left, val); + } + + return root; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -282,6 +313,46 @@ class Solution { } ``` +```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 TreeNode InsertIntoBST(TreeNode root, int val) { + if (root == null) { + return new TreeNode(val); + } + + TreeNode cur = root; + while (true) { + if (val > cur.val) { + if (cur.right == null) { + cur.right = new TreeNode(val); + return root; + } + cur = cur.right; + } else { + if (cur.left == null) { + cur.left = new TreeNode(val); + return root; + } + cur = cur.left; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/insert-new-interval.md b/articles/insert-new-interval.md index e35159e6e..13f29a037 100644 --- a/articles/insert-new-interval.md +++ b/articles/insert-new-interval.md @@ -216,12 +216,45 @@ class Solution { } ``` +```swift +class Solution { + func insert(_ intervals: [[Int]], _ newInterval: [Int]) -> [[Int]] { + var intervals = intervals + var newInterval = newInterval + var res: [[Int]] = [] + var i = 0 + let n = intervals.count + + while i < n && intervals[i][1] < newInterval[0] { + res.append(intervals[i]) + i += 1 + } + + while i < n && newInterval[1] >= intervals[i][0] { + newInterval[0] = min(newInterval[0], intervals[i][0]) + newInterval[1] = max(newInterval[1], intervals[i][1]) + i += 1 + } + res.append(newInterval) + + while i < n { + res.append(intervals[i]) + i += 1 + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output list. --- @@ -510,12 +543,49 @@ class Solution { } ``` +```swift +class Solution { + func insert(_ intervals: [[Int]], _ newInterval: [Int]) -> [[Int]] { + if intervals.isEmpty { + return [newInterval] + } + + var intervals = intervals + let target = newInterval[0] + var left = 0, right = intervals.count - 1 + + while left <= right { + let mid = (left + right) / 2 + if intervals[mid][0] < target { + left = mid + 1 + } else { + right = mid - 1 + } + } + + intervals.insert(newInterval, at: left) + + var res: [[Int]] = [] + for interval in intervals { + if res.isEmpty || res.last![1] < interval[0] { + res.append(interval) + } else { + res[res.count - 1][1] = max(res.last![1], interval[1]) + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output list. --- @@ -703,9 +773,36 @@ class Solution { } ``` +```swift +class Solution { + func insert(_ intervals: [[Int]], _ newInterval: [Int]) -> [[Int]] { + var res = [[Int]]() + var newInterval = newInterval + + for i in 0.. intervals[i][1] { + res.append(intervals[i]) + } else { + newInterval[0] = min(newInterval[0], intervals[i][0]) + newInterval[1] = max(newInterval[1], intervals[i][1]) + } + } + + res.append(newInterval) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ \ No newline at end of file +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output list. \ No newline at end of file diff --git a/articles/integer-break.md b/articles/integer-break.md index eadd8856d..2330d8828 100644 --- a/articles/integer-break.md +++ b/articles/integer-break.md @@ -79,6 +79,28 @@ class Solution { } ``` +```csharp +public class Solution { + private int n; + + public int IntegerBreak(int n) { + this.n = n; + + int Dfs(int num) { + if (num == 1) return 1; + int res = num == n ? 0 : num; + for (int i = 1; i < num; i++) { + int val = Dfs(i) * Dfs(num - i); + res = Math.Max(res, val); + } + return res; + } + + return Dfs(n); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -173,6 +195,26 @@ class Solution { } ``` +```csharp +public class Solution { + public int IntegerBreak(int n) { + int Dfs(int num, int i) { + if (Math.Min(num, i) == 0) { + return 1; + } + + if (i > num) { + return Dfs(num, num); + } + + return Math.Max(i * Dfs(num - i, i), Dfs(num, i - 1)); + } + + return Dfs(n, n - 1); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -289,6 +331,31 @@ class Solution { } ``` +```csharp +public class Solution { + public int IntegerBreak(int n) { + Dictionary dp = new Dictionary(); + dp[1] = 1; + + int Dfs(int num) { + if (dp.ContainsKey(num)) { + return dp[num]; + } + + dp[num] = (num == n) ? 0 : num; + for (int i = 1; i < num; i++) { + int val = Dfs(i) * Dfs(num - i); + dp[num] = Math.Max(dp[num], val); + } + + return dp[num]; + } + + return Dfs(n); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -409,6 +476,30 @@ class Solution { } ``` +```csharp +public class Solution { + public int IntegerBreak(int n) { + Dictionary<(int, int), int> dp = new Dictionary<(int, int), int>(); + + int Dfs(int num, int i) { + if (Math.Min(num, i) == 0) return 1; + + if (dp.ContainsKey((num, i))) return dp[(num, i)]; + + if (i > num) { + dp[(num, i)] = Dfs(num, num); + return dp[(num, i)]; + } + + dp[(num, i)] = Math.Max(i * Dfs(num - i, i), Dfs(num, i - 1)); + return dp[(num, i)]; + } + + return Dfs(n, n - 1); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -495,6 +586,24 @@ class Solution { } ``` +```csharp +public class Solution { + public int IntegerBreak(int n) { + int[] dp = new int[n + 1]; + dp[1] = 1; + + for (int num = 2; num <= n; num++) { + dp[num] = num == n ? 0 : num; + for (int i = 1; i < num; i++) { + dp[num] = Math.Max(dp[num], dp[i] * dp[num - i]); + } + } + + return dp[n]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -571,6 +680,24 @@ class Solution { } ``` +```csharp +public class Solution { + public int IntegerBreak(int n) { + if (n <= 3) { + return n - 1; + } + + int res = 1; + while (n > 4) { + res *= 3; + n -= 3; + } + + return res * n; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -653,6 +780,24 @@ class Solution { } ``` +```csharp +public class Solution { + public int IntegerBreak(int n) { + if (n <= 3) { + return n - 1; + } + + int res = (int)Math.Pow(3, n / 3); + + if (n % 3 == 1) { + return (res / 3) * 4; + } + + return res * Math.Max(1, n % 3); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/interleaving-string.md b/articles/interleaving-string.md index c5e0566de..3d124cd01 100644 --- a/articles/interleaving-string.md +++ b/articles/interleaving-string.md @@ -199,6 +199,39 @@ class Solution { } ``` +```swift +class Solution { + func isInterleave(_ s1: String, _ s2: String, _ s3: String) -> Bool { + let n1 = s1.count, n2 = s2.count, n3 = s3.count + if n1 + n2 != n3 { return false } + + let s1 = Array(s1), s2 = Array(s2), s3 = Array(s3) + + func dfs(_ i: Int, _ j: Int, _ k: Int) -> Bool { + if k == n3 { + return i == n1 && j == n2 + } + + if i < n1 && s1[i] == s3[k] { + if dfs(i + 1, j, k + 1) { + return true + } + } + + if j < n2 && s2[j] == s3[k] { + if dfs(i, j + 1, k + 1) { + return true + } + } + + return false + } + + return dfs(0, 0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -462,6 +495,40 @@ class Solution { } ``` +```swift +class Solution { + func isInterleave(_ s1: String, _ s2: String, _ s3: String) -> Bool { + let m = s1.count, n = s2.count, l = s3.count + if m + n != l { return false } + + let s1 = Array(s1), s2 = Array(s2), s3 = Array(s3) + var dp = Array(repeating: Array(repeating: nil as Bool?, count: n + 1), count: m + 1) + + func dfs(_ i: Int, _ j: Int, _ k: Int) -> Bool { + if k == l { + return i == m && j == n + } + if let cached = dp[i][j] { + return cached + } + + var res = false + if i < m && s1[i] == s3[k] { + res = dfs(i + 1, j, k + 1) + } + if !res && j < n && s2[j] == s3[k] { + res = dfs(i, j + 1, k + 1) + } + + dp[i][j] = res + return res + } + + return dfs(0, 0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -660,6 +727,31 @@ class Solution { } ``` +```swift +class Solution { + func isInterleave(_ s1: String, _ s2: String, _ s3: String) -> Bool { + let m = s1.count, n = s2.count, l = s3.count + if m + n != l { return false } + + let s1 = Array(s1), s2 = Array(s2), s3 = Array(s3) + var dp = Array(repeating: Array(repeating: false, count: n + 1), count: m + 1) + dp[m][n] = true + + for i in stride(from: m, through: 0, by: -1) { + for j in stride(from: n, through: 0, by: -1) { + if i < m && s1[i] == s3[i + j] && dp[i + 1][j] { + dp[i][j] = true + } + if j < n && s2[j] == s3[i + j] && dp[i][j + 1] { + dp[i][j] = true + } + } + } + return dp[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -904,6 +996,38 @@ class Solution { } ``` +```swift +class Solution { + func isInterleave(_ s1: String, _ s2: String, _ s3: String) -> Bool { + var s1 = Array(s1), s2 = Array(s2), s3 = Array(s3) + var m = s1.count, n = s2.count + if m + n != s3.count { return false } + if n < m { + swap(&s1, &s2) + swap(&m, &n) + } + + var dp = Array(repeating: false, count: n + 1) + dp[n] = true + + for i in stride(from: m, through: 0, by: -1) { + var nextDp = Array(repeating: false, count: n + 1) + nextDp[n] = true + for j in stride(from: n, through: 0, by: -1) { + if i < m && s1[i] == s3[i + j] && dp[j] { + nextDp[j] = true + } + if j < n && s2[j] == s3[i + j] && nextDp[j + 1] { + nextDp[j] = true + } + } + dp = nextDp + } + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1155,6 +1279,39 @@ class Solution { } ``` +```swift +class Solution { + func isInterleave(_ s1: String, _ s2: String, _ s3: String) -> Bool { + var s1 = Array(s1), s2 = Array(s2), s3 = Array(s3) + var m = s1.count, n = s2.count + if m + n != s3.count { return false } + if n < m { + swap(&s1, &s2) + swap(&m, &n) + } + + var dp = Array(repeating: false, count: n + 1) + dp[n] = true + + for i in stride(from: m, through: 0, by: -1) { + var nextDp = true + for j in stride(from: n - 1, through: 0, by: -1) { + var res = false + if i < m && s1[i] == s3[i + j] && dp[j] { + res = true + } + if j < n && s2[j] == s3[i + j] && nextDp { + res = true + } + dp[j] = res + nextDp = dp[j] + } + } + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/invert-a-binary-tree.md b/articles/invert-a-binary-tree.md index 2c7622067..33ee15f84 100644 --- a/articles/invert-a-binary-tree.md +++ b/articles/invert-a-binary-tree.md @@ -227,6 +227,44 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func invertTree(_ root: TreeNode?) -> TreeNode? { + guard let root = root else { return nil } + var queue = Deque() + queue.append(root) + + while !queue.isEmpty { + let node = queue.removeFirst() + (node.left, node.right) = (node.right, node.left) + + if let left = node.left { + queue.append(left) + } + if let right = node.right { + queue.append(right) + } + } + return root + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -253,10 +291,10 @@ class Solution: if not root: return None root.left, root.right = root.right, root.left - + self.invertTree(root.left) self.invertTree(root.right) - + return root ``` @@ -277,16 +315,18 @@ class Solution: * } */ -class Solution { +public class Solution { public TreeNode invertTree(TreeNode root) { if (root == null) return null; - - TreeNode node = new TreeNode(root.val); - node.right = invertTree(root.left); - node.left = invertTree(root.right); - - return node; + TreeNode temp = root.left; + root.left = root.right; + root.right = temp; + + invertTree(root.left); + invertTree(root.right); + + return root; } } ``` @@ -307,14 +347,13 @@ class Solution { class Solution { public: TreeNode* invertTree(TreeNode* root) { - if (root == nullptr) return nullptr; + if (!root) return nullptr; - TreeNode* node = new TreeNode(root->val); - - node->right = invertTree(root->left); - node->left = invertTree(root->right); + swap(root->left, root->right); + invertTree(root->left); + invertTree(root->right); - return node; + return root; } }; ``` @@ -337,14 +376,13 @@ class Solution { * @return {TreeNode} */ invertTree(root) { - if (root === null) return null; - - const node = new TreeNode(root.val); + if (!root) return null; - node.right = this.invertTree(root.left); - node.left = this.invertTree(root.right); + [root.left, root.right] = [root.right, root.left]; + this.invertTree(root.left); + this.invertTree(root.right); - return node; + return root; } } ``` @@ -368,12 +406,95 @@ public class Solution { public TreeNode InvertTree(TreeNode root) { if (root == null) return null; - TreeNode node = new TreeNode(root.val); - - node.right = InvertTree(root.left); - node.left = InvertTree(root.right); + TreeNode temp = root.left; + root.left = root.right; + root.right = temp; + + InvertTree(root.left); + InvertTree(root.right); - return node; + return root; + } +} +``` + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func invertTree(root *TreeNode) *TreeNode { + if root == nil { + return nil + } + + root.Left, root.Right = root.Right, root.Left + invertTree(root.Left) + invertTree(root.Right) + + return root +} +``` + +```kotlin +/** + * Example: + * var ti = TreeNode(5) + * var v = ti.`val` + * Definition for a binary tree node. + * class TreeNode(var `val`: Int) { + * var left: TreeNode? = null + * var right: TreeNode? = null + * } + */ + +class Solution { + fun invertTree(root: TreeNode?): TreeNode? { + if (root == null) return null + + val temp = root.left + root.left = root.right + root.right = temp + + invertTree(root.left) + invertTree(root.right) + + return root + } +} +``` + +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func invertTree(_ root: TreeNode?) -> TreeNode? { + guard let root = root else { return nil } + + (root.left, root.right) = (root.right, root.left) + + invertTree(root.left) + invertTree(root.right) + + return root } } ``` @@ -383,7 +504,7 @@ public class Solution { ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(n)$ +* Space complexity: $O(n)$ for recursion stack. --- @@ -592,6 +713,43 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func invertTree(_ root: TreeNode?) -> TreeNode? { + guard let root = root else { return nil } + var stack: [TreeNode] = [root] + + while !stack.isEmpty { + let node = stack.removeLast() + (node.left, node.right) = (node.right, node.left) + + if let left = node.left { + stack.append(left) + } + if let right = node.right { + stack.append(right) + } + } + return root + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/ipo.md b/articles/ipo.md index e71ba4c34..87670000f 100644 --- a/articles/ipo.md +++ b/articles/ipo.md @@ -85,8 +85,8 @@ class Solution { * @return {number} */ findMaximizedCapital(k, w, profits, capital) { - const minCapital = new MinPriorityQueue({ compare: (a, b) => a[0] - b[0] }); // Min heap - const maxProfit = new MaxPriorityQueue({ compare: (a, b) => b - a }); // Max heap + const minCapital = new PriorityQueue((a, b) => a[0] - b[0]); // Min heap + const maxProfit = new PriorityQueue((a, b) => b - a); // Max heap for (let i = 0; i < capital.length; i++) { minCapital.enqueue([capital[i], profits[i]]); @@ -107,6 +107,39 @@ class Solution { } ``` +```csharp +public class Solution { + public int FindMaximizedCapital(int k, int w, int[] profits, int[] capital) { + var minCapital = new List<(int c, int p)>(); + for (int i = 0; i < capital.Length; i++) { + minCapital.Add((capital[i], profits[i])); + } + + // Min-heap by capital + minCapital.Sort((a, b) => a.c.CompareTo(b.c)); + + // Max-heap by profit + var maxProfit = new PriorityQueue(Comparer.Create((a, b) => b.CompareTo(a))); + int iPtr = 0; + + for (int i = 0; i < k; i++) { + while (iPtr < minCapital.Count && minCapital[iPtr].c <= w) { + maxProfit.Enqueue(minCapital[iPtr].p, minCapital[iPtr].p); + iPtr++; + } + + if (maxProfit.Count == 0) { + break; + } + + w += maxProfit.Dequeue(); + } + + return w; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -215,12 +248,12 @@ class Solution { * @return {number} */ findMaximizedCapital(k, w, profits, capital) { - const minCapital = new MinPriorityQueue({ - compare: (a, b) => capital[a] - capital[b], - }); - const maxProfit = new MaxPriorityQueue({ - compare: (a, b) => profits[b] - profits[a], - }); + const minCapital = new PriorityQueue( + (a, b) => capital[a] - capital[b], + ); + const maxProfit = new PriorityQueue( + (a, b) => profits[b] - profits[a], + ); for (let i = 0; i < capital.length; i++) { minCapital.enqueue(i); @@ -241,6 +274,34 @@ class Solution { } ``` +```csharp +public class Solution { + public int FindMaximizedCapital(int k, int w, int[] profits, int[] capital) { + var minCapital = new PriorityQueue(); // index with capital as priority + var maxProfit = new PriorityQueue(Comparer.Create((a, b) => b.CompareTo(a))); // max heap by profit + + for (int i = 0; i < capital.Length; i++) { + minCapital.Enqueue(i, capital[i]); + } + + for (int i = 0; i < k; i++) { + while (minCapital.Count > 0 && capital[minCapital.Peek()] <= w) { + int idx = minCapital.Dequeue(); + maxProfit.Enqueue(profits[idx], profits[idx]); + } + + if (maxProfit.Count == 0) { + break; + } + + w += maxProfit.Dequeue(); + } + + return w; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -358,7 +419,7 @@ class Solution { if (maxProfit.isEmpty()) { break; } - w += maxProfit.dequeue().element; + w += maxProfit.dequeue(); } return w; @@ -366,6 +427,38 @@ class Solution { } ``` +```csharp +public class Solution { + public int FindMaximizedCapital(int k, int w, int[] profits, int[] capital) { + int n = profits.Length; + int[] indices = new int[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + + Array.Sort(indices, (a, b) => capital[a].CompareTo(capital[b])); + + var maxProfit = new PriorityQueue(Comparer.Create((a, b) => b.CompareTo(a))); + int idx = 0; + + for (int i = 0; i < k; i++) { + while (idx < n && capital[indices[idx]] <= w) { + maxProfit.Enqueue(profits[indices[idx]], profits[indices[idx]]); + idx++; + } + + if (maxProfit.Count == 0) { + break; + } + + w += maxProfit.Dequeue(); + } + + return w; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/is-anagram.md b/articles/is-anagram.md index ae3a44534..eb996634a 100644 --- a/articles/is-anagram.md +++ b/articles/is-anagram.md @@ -112,6 +112,14 @@ class Solution { } ``` +```swift +class Solution { + func isAnagram(_ s: String, _ t: String) -> Bool { + return s.count == t.count && s.sorted() == t.sorted() + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -123,7 +131,7 @@ class Solution { --- -## 2. Hash Table +## 2. Hash Map ::tabs-start @@ -266,6 +274,29 @@ class Solution { } ``` +```swift +class Solution { + func isAnagram(_ s: String, _ t: String) -> Bool { + if s.count != t.count { + return false + } + + var countS = [Character: Int]() + var countT = [Character: Int]() + + let sArray = Array(s) + let tArray = Array(t) + + for i in 0.. Bool { + if s.count != t.count { + return false + } + + var count = [Int](repeating: 0, count: 26) + let sArray = Array(s) + let tArray = Array(t) + + for i in 0.. Where $n$ is the length of string $s$ and $m$ is the length of string $t$. +> Where $n$ is the length of string $s$ and $m$ is the length of string $t$. \ No newline at end of file diff --git a/articles/is-palindrome.md b/articles/is-palindrome.md index e7675ceb9..9aea0c833 100644 --- a/articles/is-palindrome.md +++ b/articles/is-palindrome.md @@ -123,6 +123,22 @@ class Solution { } ``` +```swift +class Solution { + func isPalindrome(_ s: String) -> Bool { + var newStr = "" + + for c in s { + if c.isLetter || c.isNumber { + newStr.append(c.lowercased()) + } + } + + return newStr == String(newStr.reversed()) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -327,6 +343,34 @@ class Solution { } ``` +```swift +class Solution { + func isPalindrome(_ s: String) -> Bool { + let chars = Array(s) + var l = 0, r = chars.count - 1 + + while l < r { + while l < r && !isAlphaNum(chars[l]) { + l += 1 + } + while r > l && !isAlphaNum(chars[r]) { + r -= 1 + } + if chars[l].lowercased() != chars[r].lowercased() { + return false + } + l += 1 + r -= 1 + } + return true + } + + private func isAlphaNum(_ c: Character) -> Bool { + return c.isLetter || c.isNumber + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/island-perimeter.md b/articles/island-perimeter.md index c4bb78ca5..bb87939fe 100644 --- a/articles/island-perimeter.md +++ b/articles/island-perimeter.md @@ -138,6 +138,42 @@ class Solution { } ``` +```csharp +public class Solution { + private int rows, cols; + private HashSet<(int, int)> visit; + + public int IslandPerimeter(int[][] grid) { + rows = grid.Length; + cols = grid[0].Length; + visit = new HashSet<(int, int)>(); + + int Dfs(int i, int j) { + if (i < 0 || j < 0 || i >= rows || j >= cols || grid[i][j] == 0) { + return 1; + } + if (visit.Contains((i, j))) { + return 0; + } + + visit.Add((i, j)); + int perim = Dfs(i, j + 1) + Dfs(i + 1, j) + Dfs(i, j - 1) + Dfs(i - 1, j); + return perim; + } + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (grid[i][j] == 1) { + return Dfs(i, j); + } + } + } + + return 0; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -309,6 +345,56 @@ class Solution { } ``` +```csharp +public class Solution { + public int IslandPerimeter(int[][] grid) { + int rows = grid.Length; + int cols = grid[0].Length; + var visited = new HashSet<(int, int)>(); + int[][] directions = new int[][] { + new int[] { 0, 1 }, + new int[] { 1, 0 }, + new int[] { 0, -1 }, + new int[] { -1, 0 } + }; + + int Bfs(int r, int c) { + var queue = new Queue<(int, int)>(); + queue.Enqueue((r, c)); + visited.Add((r, c)); + int perimeter = 0; + + while (queue.Count > 0) { + var (x, y) = queue.Dequeue(); + foreach (var dir in directions) { + int nx = x + dir[0]; + int ny = y + dir[1]; + + if (nx < 0 || ny < 0 || nx >= rows || ny >= cols || grid[nx][ny] == 0) { + perimeter++; + } else if (!visited.Contains((nx, ny))) { + visited.Add((nx, ny)); + queue.Enqueue((nx, ny)); + } + } + } + + return perimeter; + } + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (grid[i][j] == 1) { + return Bfs(i, j); + } + } + } + + return 0; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -401,6 +487,29 @@ class Solution { } ``` +```csharp +public class Solution { + public int IslandPerimeter(int[][] grid) { + int m = grid.Length; + int n = grid[0].Length; + int res = 0; + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 1) { + if (i + 1 >= m || grid[i + 1][j] == 0) res++; + if (j + 1 >= n || grid[i][j + 1] == 0) res++; + if (i - 1 < 0 || grid[i - 1][j] == 0) res++; + if (j - 1 < 0 || grid[i][j - 1] == 0) res++; + } + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -506,6 +615,32 @@ class Solution { } ``` +```csharp +public class Solution { + public int IslandPerimeter(int[][] grid) { + int m = grid.Length; + int n = grid[0].Length; + int res = 0; + + for (int r = 0; r < m; r++) { + for (int c = 0; c < n; c++) { + if (grid[r][c] == 1) { + res += 4; + if (r > 0 && grid[r - 1][c] == 1) { + res -= 2; + } + if (c > 0 && grid[r][c - 1] == 1) { + res -= 2; + } + } + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/islands-and-treasure.md b/articles/islands-and-treasure.md index ff99ef107..86e92192f 100644 --- a/articles/islands-and-treasure.md +++ b/articles/islands-and-treasure.md @@ -302,6 +302,43 @@ class Solution { } ``` +```swift +class Solution { + func islandsAndTreasure(_ grid: inout [[Int]]) { + let ROWS = grid.count + let COLS = grid[0].count + let INF = 2147483647 + let directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] + var visit = Array(repeating: Array(repeating: false, count: COLS), count: ROWS) + + func dfs(_ r: Int, _ c: Int) -> Int { + if r < 0 || c < 0 || r >= ROWS || c >= COLS || grid[r][c] == -1 || visit[r][c] { + return INF + } + if grid[r][c] == 0 { + return 0 + } + + visit[r][c] = true + var res = INF + for (dx, dy) in directions { + res = min(res, 1 + dfs(r + dx, c + dy)) + } + visit[r][c] = false + return res + } + + for r in 0.. Int { + var q = Deque<(Int, Int)>() + q.append((r, c)) + var visit = Array(repeating: Array(repeating: false, count: COLS), count: ROWS) + visit[r][c] = true + var steps = 0 + while !q.isEmpty { + let levelCount = q.count + for _ in 0..= 0 && nr < ROWS && nc >= 0 && nc < COLS && + !visit[nr][nc] && grid[nr][nc] != -1) { + visit[nr][nc] = true + q.append((nr, nc)) + } + } + } + steps += 1 + } + return INF + } + + for r in 0..() + var q = Deque() + + func addCell(_ r: Int, _ c: Int) { + if r < 0 || c < 0 || r >= ROWS || c >= COLS { return } + let item = Item(r: r, c: c) + if visit.contains(item) || grid[r][c] == -1 { return } + visit.insert(item) + q.append(item) + } + + for r in 0.. Int { + func dfs(_ i: Int) -> Int { + if i == nums.count - 1 { + return 0 + } + if nums[i] == 0 { + return 1000000 + } + + let end = min(nums.count - 1, i + nums[i]) + var res = 1000000 + for j in i + 1..<(end + 1) { + res = min(res, 1 + dfs(j)) + } + + return res + } + + return dfs(0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -382,6 +411,37 @@ class Solution { } ``` +```swift +class Solution { + var memo: [Int: Int] = [:] + + func jump(_ nums: [Int]) -> Int { + return dfs(nums, 0) + } + + private func dfs(_ nums: [Int], _ i: Int) -> Int { + if let cachedResult = memo[i] { + return cachedResult + } + if i == nums.count - 1 { + return 0 + } + if nums[i] == 0 { + return 1000000 + } + + var res = 1000000 + let end = min(nums.count, i + nums[i] + 1) + for j in i + 1.. Int { + let n = nums.count + var dp = Array(repeating: 1000000, count: n) + dp[n - 1] = 0 + + for i in stride(from: n - 2, through: 0, by: -1) { + let end = min(n, i + nums[i] + 1) + for j in i + 1.. Int { + var res = 0 + var l = 0 + var r = 0 + + while r < nums.count - 1 { + var farthest = 0 + for i in l...r { + farthest = max(farthest, i + nums[i]) + } + l = r + 1 + r = farthest + res += 1 + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/jump-game.md b/articles/jump-game.md index 850539bca..c5048055e 100644 --- a/articles/jump-game.md +++ b/articles/jump-game.md @@ -157,6 +157,29 @@ class Solution { } ``` +```swift +class Solution { + func canJump(_ nums: [Int]) -> Bool { + + func dfs(_ i: Int) -> Bool { + if i == nums.count - 1 { + return true + } + + let end = min(nums.count - 1, i + nums[i]) + for j in i + 1..<(end + 1) { + if dfs(j) { + return true + } + } + return false + } + + return dfs(0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -397,6 +420,39 @@ class Solution { } ``` +```swift +class Solution { + func canJump(_ nums: [Int]) -> Bool { + var memo: [Int: Bool] = [:] + + func dfs(_ i: Int) -> Bool { + if let cachedResult = memo[i] { + return cachedResult + } + if i == nums.count - 1 { + return true + } + if nums[i] == 0 { + return false + } + + let end = min(nums.count, i + nums[i] + 1) + for j in i + 1.. Bool { + let n = nums.count + var dp = [Bool](repeating: false, count: n) + dp[n - 1] = true + + for i in (0.. Bool { + var goal = nums.count - 1 + + for i in stride(from: nums.count - 2, through: 0, by: -1) { + if i + nums[i] >= goal { + goal = i + } + } + + return goal == 0 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/k-closest-points-to-origin.md b/articles/k-closest-points-to-origin.md index 823a5a33f..7882e7c18 100644 --- a/articles/k-closest-points-to-origin.md +++ b/articles/k-closest-points-to-origin.md @@ -75,6 +75,16 @@ class Solution { } ``` +```swift +class Solution { + func kClosest(_ points: [[Int]], _ k: Int) -> [[Int]] { + return points.sorted { ($0[0] * $0[0] + $0[1] * $0[1]) < ($1[0] * $1[0] + $1[1] * $1[1]) } + .prefix(k) + .map { $0 } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -84,7 +94,7 @@ class Solution { --- -## 2. Min Heap +## 2. Min-Heap ::tabs-start @@ -242,6 +252,39 @@ class Solution { } ``` +```swift +struct Item: Comparable { + let dist: Int + let x: Int + let y: Int + + static func < (lhs: Item, rhs: Item) -> Bool { + return lhs.dist < rhs.dist + } +} + +class Solution { + func kClosest(_ points: [[Int]], _ k: Int) -> [[Int]] { + var minHeap = Heap() + + for point in points { + let x = point[0], y = point[1] + let dist = x * x + y * y + minHeap.insert(Item(dist: dist, x: x, y: y)) + } + + var res = [[Int]]() + for _ in 0.. Bool { + return lhs.dist > rhs.dist + } +} + +class Solution { + func kClosest(_ points: [[Int]], _ k: Int) -> [[Int]] { + var maxHeap = Heap() + + for point in points { + let x = point[0], y = point[1] + let dist = x * x + y * y + maxHeap.insert(Item(dist: dist, x: x, y: y)) + if maxHeap.count > k { + _ = maxHeap.popMin() + } + } + + var res = [[Int]]() + while !maxHeap.isEmpty { + if let item = maxHeap.popMin() { + res.append([item.x, item.y]) + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -721,6 +800,46 @@ class Solution { } ``` +```swift +class Solution { + func kClosest(_ points: [[Int]], _ k: Int) -> [[Int]] { + var points = points + + func euclidean(_ point: [Int]) -> Int { + return point[0] * point[0] + point[1] * point[1] + } + + func partition(_ l: Int, _ r: Int) -> Int { + let pivotIdx = r + let pivotDist = euclidean(points[pivotIdx]) + var i = l + for j in l.. 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/kth-largest-element-in-an-array.md b/articles/kth-largest-element-in-an-array.md index ba0f51363..28fa1c69b 100644 --- a/articles/kth-largest-element-in-an-array.md +++ b/articles/kth-largest-element-in-an-array.md @@ -67,6 +67,15 @@ class Solution { } ``` +```swift +class Solution { + func findKthLargest(_ nums: [Int], _ k: Int) -> Int { + let sortedNums = nums.sorted() + return sortedNums[sortedNums.count - k] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -184,6 +193,23 @@ class Solution { } ``` +```swift +class Solution { + func findKthLargest(_ nums: [Int], _ k: Int) -> Int { + var minHeap = Heap() + + for num in nums { + minHeap.insert(num) + if minHeap.count > k { + _ = minHeap.removeMin() + } + } + + return minHeap.popMin()! + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -417,6 +443,38 @@ class Solution { } ``` +```swift +class Solution { + func findKthLargest(_ nums: [Int], _ k: Int) -> Int { + var nums = nums + let k = nums.count - k + + func quickSelect(_ l: Int, _ r: Int) -> Int { + let pivot = nums[r] + var p = l + + for i in l.. k { + return quickSelect(l, p - 1) + } else if p < k { + return quickSelect(p + 1, r) + } else { + return nums[p] + } + } + + return quickSelect(0, nums.count - 1) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -822,6 +880,70 @@ class Solution { } ``` +```swift +class Solution { + func partition(_ nums: inout [Int], _ left: Int, _ right: Int) -> Int { + let mid = (left + right) >> 1 + nums.swapAt(mid, left + 1) + + if nums[left] < nums[right] { + nums.swapAt(left, right) + } + if nums[left + 1] < nums[right] { + nums.swapAt(left + 1, right) + } + if nums[left] < nums[left + 1] { + nums.swapAt(left, left + 1) + } + + let pivot = nums[left + 1] + var i = left + 1 + var j = right + + while true { + repeat { i += 1 } while nums[i] > pivot + repeat { j -= 1 } while nums[j] < pivot + + if i > j { + break + } + nums.swapAt(i, j) + } + + nums.swapAt(left + 1, j) + return j + } + + func quickSelect(_ nums: inout [Int], _ k: Int) -> Int { + var left = 0 + var right = nums.count - 1 + + while true { + if right <= left + 1 { + if right == left + 1 && nums[right] > nums[left] { + nums.swapAt(left, right) + } + return nums[k] + } + + let j = partition(&nums, left, right) + + if j >= k { + right = j - 1 + } + if j <= k { + left = j + 1 + } + } + } + + func findKthLargest(_ nums: [Int], _ k: Int) -> Int { + var nums = nums + return quickSelect(&nums, k - 1) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/kth-largest-integer-in-a-stream.md b/articles/kth-largest-integer-in-a-stream.md index 7913b93ca..42a4f617a 100644 --- a/articles/kth-largest-integer-in-a-stream.md +++ b/articles/kth-largest-integer-in-a-stream.md @@ -124,12 +124,32 @@ class KthLargest(k: Int, nums: IntArray) { } ``` +```swift +class KthLargest { + private var k: Int + private var arr: [Int] + + init(_ k: Int, _ nums: [Int]) { + self.k = k + self.arr = nums + } + + func add(_ val: Int) -> Int { + arr.append(val) + arr.sort() + return arr[arr.count - k] + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(m * n\log n)$ -* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. +* Space complexity: + * $O(m)$ extra space. + * $O(1)$ or $O(n)$ space depending on the sorting algorithm. > Where $m$ is the number of calls made to $add()$ and $n$ is the current size of the array. @@ -324,6 +344,32 @@ class KthLargest(k: Int, nums: IntArray) { } ``` +```swift +class KthLargest { + private var minHeap: Heap + private let k: Int + + init(_ k: Int, _ nums: [Int]) { + self.k = k + self.minHeap = Heap() + for num in nums { + minHeap.insert(num) + if minHeap.count > k { + minHeap.popMin() + } + } + } + + func add(_ val: Int) -> Int { + minHeap.insert(val) + if minHeap.count > k { + minHeap.popMin() + } + return minHeap.min! + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/kth-smallest-integer-in-bst.md b/articles/kth-smallest-integer-in-bst.md index 1014ba6d4..ec5dfe795 100644 --- a/articles/kth-smallest-integer-in-bst.md +++ b/articles/kth-smallest-integer-in-bst.md @@ -225,6 +225,40 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int { + var arr = [Int]() + + func dfs(_ node: TreeNode?) { + guard let node = node else { return } + arr.append(node.val) + dfs(node.left) + dfs(node.right) + } + + dfs(root) + arr.sort() + return arr[k - 1] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -456,6 +490,39 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int { + var arr = [Int]() + + func dfs(_ node: TreeNode?) { + guard let node = node else { return } + dfs(node.left) + arr.append(node.val) + dfs(node.right) + } + + dfs(root) + return arr[k - 1] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -721,6 +788,45 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int { + var cnt = k + var res = root!.val + + func dfs(_ node: TreeNode?) { + guard let node = node else { return } + + dfs(node.left) + cnt -= 1 + if cnt == 0 { + res = node.val + return + } + dfs(node.right) + } + + dfs(root) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -983,6 +1089,45 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int { + var stack = [TreeNode]() + var curr = root + var k = k + + while !stack.isEmpty || curr != nil { + while curr != nil { + stack.append(curr!) + curr = curr?.left + } + curr = stack.removeLast() + k -= 1 + if k == 0 { + return curr!.val + } + curr = curr?.right + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1298,6 +1443,58 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int { + var curr = root + var k = k + + while curr != nil { + if curr?.left == nil { + k -= 1 + if k == 0 { + return curr!.val + } + curr = curr?.right + } else { + var pred = curr?.left + while pred?.right != nil && pred?.right !== curr { + pred = pred?.right + } + + if pred?.right == nil { + pred?.right = curr + curr = curr?.left + } else { + pred?.right = nil + k -= 1 + if k == 0 { + return curr!.val + } + curr = curr?.right + } + } + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/largest-rectangle-in-histogram.md b/articles/largest-rectangle-in-histogram.md index 54d44de5b..75df88ffe 100644 --- a/articles/largest-rectangle-in-histogram.md +++ b/articles/largest-rectangle-in-histogram.md @@ -203,6 +203,35 @@ class Solution { } ``` +```swift +class Solution { + func largestRectangleArea(_ heights: [Int]) -> Int { + let n = heights.count + var maxArea = 0 + + for i in 0..= height { + rightMost += 1 + } + + var leftMost = i + while leftMost >= 0 && heights[leftMost] >= height { + leftMost -= 1 + } + + rightMost -= 1 + leftMost += 1 + maxArea = max(maxArea, height * (rightMost - leftMost + 1)) + } + + return maxArea + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -767,6 +796,86 @@ class Solution { } ``` +```swift +class MinIdxSegmentTree { + private var n: Int + private var INF = Int(1e9) + private var A: [Int] + private var tree: [Int] + + init(_ N: Int, _ A: [Int]) { + self.n = N + self.A = A + while (self.n & (self.n - 1)) != 0 { + self.A.append(self.INF) + self.n += 1 + } + self.tree = [Int](repeating: 0, count: 2 * self.n) + build() + } + + private func build() { + for i in 0..> 1 + while j >= 1 { + let a = tree[j << 1] + let b = tree[(j << 1) + 1] + tree[j] = (A[a] <= A[b]) ? a : b + j >>= 1 + } + } + + func query(_ ql: Int, _ qh: Int) -> Int { + return _query(1, 0, n - 1, ql, qh) + } + + private func _query(_ node: Int, _ l: Int, _ h: Int, _ ql: Int, _ qh: Int) -> Int { + if ql > h || qh < l { + return INF + } + if l >= ql && h <= qh { + return tree[node] + } + let a = _query(node << 1, l, (l + h) >> 1, ql, qh) + let b = _query((node << 1) + 1, ((l + h) >> 1) + 1, h, ql, qh) + if a == INF { return b } + if b == INF { return a } + return (A[a] <= A[b]) ? a : b + } +} + +class Solution { + func getMaxArea(_ heights: [Int], _ l: Int, _ r: Int, _ st: MinIdxSegmentTree) -> Int { + if l > r { return 0 } + if l == r { return heights[l] } + + let minIdx = st.query(l, r) + return max( + max(getMaxArea(heights, l, minIdx - 1, st), + getMaxArea(heights, minIdx + 1, r, st)), + (r - l + 1) * heights[minIdx] + ) + } + + func largestRectangleArea(_ heights: [Int]) -> Int { + let n = heights.count + let st = MinIdxSegmentTree(n, heights) + return getMaxArea(heights, 0, n - 1, st) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1075,6 +1184,46 @@ class Solution { } ``` +```swift +class Solution { + func largestRectangleArea(_ heights: [Int]) -> Int { + let n = heights.count + var stack = [Int]() + + var leftMost = [Int](repeating: -1, count: n) + for i in 0..= heights[i] { + stack.removeLast() + } + if !stack.isEmpty { + leftMost[i] = stack.last! + } + stack.append(i) + } + + stack.removeAll() + var rightMost = [Int](repeating: n, count: n) + for i in stride(from: n - 1, through: 0, by: -1) { + while !stack.isEmpty && heights[stack.last!] >= heights[i] { + stack.removeLast() + } + if !stack.isEmpty { + rightMost[i] = stack.last! + } + stack.append(i) + } + + var maxArea = 0 + for i in 0.. Int { + var maxArea = 0 + var stack = [(Int, Int)]() // Pair: (index, height) + + for (i, h) in heights.enumerated() { + var start = i + while !stack.isEmpty && stack.last!.1 > h { + let (index, height) = stack.removeLast() + maxArea = max(maxArea, height * (i - index)) + start = index + } + stack.append((start, h)) + } + + for (i, h) in stack { + maxArea = max(maxArea, h * (heights.count - i)) + } + + return maxArea + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1292,7 +1466,7 @@ class Solution { --- -## 5. Stack (One Pass) +## 5. Stack (Optimal) ::tabs-start @@ -1453,6 +1627,26 @@ class Solution { } ``` +```swift +class Solution { + func largestRectangleArea(_ heights: [Int]) -> Int { + let n = heights.count + var maxArea = 0 + var stack = [Int]() + + for i in 0...n { + while !stack.isEmpty && (i == n || heights[stack.last!] >= heights[i]) { + let height = heights[stack.removeLast()] + let width = stack.isEmpty ? i : i - stack.last! - 1 + maxArea = max(maxArea, height * width) + } + stack.append(i) + } + return maxArea + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/last-stone-weight.md b/articles/last-stone-weight.md index da1ec745e..69ab3403a 100644 --- a/articles/last-stone-weight.md +++ b/articles/last-stone-weight.md @@ -127,6 +127,24 @@ class Solution { } ``` +```swift +class Solution { + func lastStoneWeight(_ stones: [Int]) -> Int { + var stones = stones + + while stones.count > 1 { + stones.sort() + let cur = stones.removeLast() - stones.removeLast() + if cur > 0 { + stones.append(cur) + } + } + + return stones.isEmpty ? 0 : stones[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -368,6 +386,40 @@ class Solution { } ``` +```swift +class Solution { + func lastStoneWeight(_ stones: [Int]) -> Int { + var stones = stones.sorted() + var n = stones.count + + while n > 1 { + let cur = stones.removeLast() - stones.removeLast() + n -= 2 + if cur > 0 { + var l = 0, r = n + while l < r { + let mid = (l + r) / 2 + if stones[mid] < cur { + l = mid + 1 + } else { + r = mid + } + } + let pos = l + stones.append(0) + n += 1 + for i in stride(from: n - 1, to: pos, by: -1) { + stones[i] = stones[i - 1] + } + stones[pos] = cur + } + } + + return n > 0 ? stones[0] : 0 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -543,6 +595,22 @@ class Solution { } ``` +```swift +class Solution { + func lastStoneWeight(_ stones: [Int]) -> Int { + var heap = Heap(stones) + while heap.count > 1 { + let first = heap.popMax()! + let second = heap.popMax()! + if first > second { + heap.insert(first - second) + } + } + return heap.isEmpty ? 0 : heap.popMax()! + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -843,6 +911,46 @@ class Solution { } ``` +```swift +class Solution { + func lastStoneWeight(_ stones: [Int]) -> Int { + guard let maxStone = stones.max() else { return 0 } + + var bucket = [Int](repeating: 0, count: maxStone + 1) + for stone in stones { + bucket[stone] += 1 + } + + var first = maxStone + var second = maxStone + + while first > 0 { + if bucket[first] % 2 == 0 { + first -= 1 + continue + } + + var j = min(first - 1, second) + while j > 0 && bucket[j] == 0 { + j -= 1 + } + + if j == 0 { + return first + } + + second = j + bucket[first] -= 1 + bucket[second] -= 1 + bucket[first - second] += 1 + first = max(first - second, second) + } + + return first + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/level-order-traversal-of-binary-tree.md b/articles/level-order-traversal-of-binary-tree.md index 3bb08fe9a..28df7fc5f 100644 --- a/articles/level-order-traversal-of-binary-tree.md +++ b/articles/level-order-traversal-of-binary-tree.md @@ -19,11 +19,11 @@ class Solution: return None if len(res) == depth: res.append([]) - + res[depth].append(node.val) dfs(node.left, depth + 1) dfs(node.right, depth + 1) - + dfs(root, 0) return res ``` @@ -251,6 +251,44 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func levelOrder(_ root: TreeNode?) -> [[Int]] { + var res = [[Int]]() + + func dfs(_ node: TreeNode?, _ depth: Int) { + guard let node = node else { return } + + if res.count == depth { + res.append([]) + } + + res[depth].append(node.val) + dfs(node.left, depth + 1) + dfs(node.right, depth + 1) + } + + dfs(root, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -549,6 +587,48 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func levelOrder(_ root: TreeNode?) -> [[Int]] { + var res = [[Int]]() + var q = Deque() + q.append(root) + + while !q.isEmpty { + let qLen = q.count + var level = [Int]() + + for _ in 0.. Bool { + var seen = Set() + var cur = head + + while cur != nil { + let nodeId = ObjectIdentifier(cur!) + if seen.contains(nodeId) { + return true + } + seen.insert(nodeId) + cur = cur?.next + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -387,6 +418,36 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init(_ val: Int) { + * self.val = val + * self.next = nil + * } + * } + */ + +class Solution { + func hasCycle(_ head: ListNode?) -> Bool { + var slow = head + var fast = head + + while fast != nil && fast?.next != nil { + slow = slow?.next + fast = fast?.next?.next + if slow === fast { + return true + } + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/longest-common-prefix.md b/articles/longest-common-prefix.md index e5941f9a6..936377d1c 100644 --- a/articles/longest-common-prefix.md +++ b/articles/longest-common-prefix.md @@ -78,6 +78,27 @@ class Solution { } ``` +```csharp +public class Solution { + public string LongestCommonPrefix(string[] strs) { + string prefix = strs[0]; + + for (int i = 1; i < strs.Length; i++) { + int j = 0; + while (j < Math.Min(prefix.Length, strs[i].Length)) { + if (prefix[j] != strs[i][j]) { + break; + } + j++; + } + prefix = prefix.Substring(0, j); + } + + return prefix; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -153,6 +174,21 @@ class Solution { } ``` +```csharp +public class Solution { + public string LongestCommonPrefix(string[] strs) { + for (int i = 0; i < strs[0].Length; i++) { + foreach (string s in strs) { + if (i == s.Length || s[i] != strs[0][i]) { + return s.Substring(0, i); + } + } + } + return strs[0]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -242,6 +278,30 @@ class Solution { } ``` +```csharp +public class Solution { + public string LongestCommonPrefix(string[] strs) { + if (strs.Length == 1) { + return strs[0]; + } + + Array.Sort(strs); + string first = strs[0]; + string last = strs[strs.Length - 1]; + + int i = 0; + while (i < Math.Min(first.Length, last.Length)) { + if (first[i] != last[i]) { + return first.Substring(0, i); + } + i++; + } + + return first; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -493,6 +553,64 @@ class Solution { } ``` +```csharp +public class TrieNode { + public Dictionary Children = new Dictionary(); +} + +public class Trie { + public TrieNode Root; + + public Trie() { + Root = new TrieNode(); + } + + public void Insert(string word) { + TrieNode node = Root; + foreach (char c in word) { + if (!node.Children.ContainsKey(c)) { + node.Children[c] = new TrieNode(); + } + node = node.Children[c]; + } + } + + public int Lcp(string word, int prefixLen) { + TrieNode node = Root; + for (int i = 0; i < Math.Min(word.Length, prefixLen); i++) { + if (!node.Children.ContainsKey(word[i])) { + return i; + } + node = node.Children[word[i]]; + } + return Math.Min(word.Length, prefixLen); + } +} + +public class Solution { + public string LongestCommonPrefix(string[] strs) { + if (strs.Length == 1) return strs[0]; + + int mini = 0; + for (int i = 1; i < strs.Length; i++) { + if (strs[i].Length < strs[mini].Length) { + mini = i; + } + } + + Trie trie = new Trie(); + trie.Insert(strs[mini]); + + int prefixLen = strs[mini].Length; + for (int i = 0; i < strs.Length; i++) { + prefixLen = trie.Lcp(strs[i], prefixLen); + } + + return strs[0].Substring(0, prefixLen); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -500,4 +618,4 @@ class Solution { * Time complexity: $O(n * m)$ * Space complexity: $O(n)$ -> Where $n$ is the length of the shortest string and $m$ is the number of strings. +> Where $n$ is the length of the shortest string and $m$ is the number of strings. \ No newline at end of file diff --git a/articles/longest-common-subsequence.md b/articles/longest-common-subsequence.md index f75a48573..95c23cd86 100644 --- a/articles/longest-common-subsequence.md +++ b/articles/longest-common-subsequence.md @@ -136,6 +136,27 @@ class Solution { } ``` +```swift +class Solution { + func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int { + let arr1 = Array(text1) + let arr2 = Array(text2) + + func dfs(_ i: Int, _ j: Int) -> Int { + if i == arr1.count || j == arr2.count { + return 0 + } + if arr1[i] == arr2[j] { + return 1 + dfs(i + 1, j + 1) + } + return max(dfs(i + 1, j), dfs(i, j + 1)) + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -363,6 +384,35 @@ class Solution { } ``` +```swift +class Solution { + func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int { + let arr1 = Array(text1) + let arr2 = Array(text2) + var memo = [String: Int]() + + func dfs(_ i: Int, _ j: Int) -> Int { + if i == arr1.count || j == arr2.count { + return 0 + } + let key = "\(i),\(j)" + if let val = memo[key] { + return val + } + + if arr1[i] == arr2[j] { + memo[key] = 1 + dfs(i + 1, j + 1) + } else { + memo[key] = max(dfs(i + 1, j), dfs(i, j + 1)) + } + return memo[key]! + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -534,6 +584,31 @@ class Solution { } ``` +```swift +class Solution { + func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int { + let m = text1.count + let n = text2.count + let arr1 = Array(text1) + let arr2 = Array(text2) + + var dp = Array(repeating: Array(repeating: 0, count: n + 1), count: m + 1) + + for i in stride(from: m - 1, through: 0, by: -1) { + for j in stride(from: n - 1, through: 0, by: -1) { + if arr1[i] == arr2[j] { + dp[i][j] = 1 + dp[i + 1][j + 1] + } else { + dp[i][j] = max(dp[i][j + 1], dp[i + 1][j]) + } + } + } + + return dp[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -749,6 +824,35 @@ class Solution { } ``` +```swift +class Solution { + func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int { + var t1 = Array(text1) + var t2 = Array(text2) + + if t1.count < t2.count { + swap(&t1, &t2) + } + + var prev = Array(repeating: 0, count: t2.count + 1) + var curr = Array(repeating: 0, count: t2.count + 1) + + for i in stride(from: t1.count - 1, through: 0, by: -1) { + for j in stride(from: t2.count - 1, through: 0, by: -1) { + if t1[i] == t2[j] { + curr[j] = 1 + prev[j + 1] + } else { + curr[j] = max(curr[j + 1], prev[j]) + } + } + swap(&prev, &curr) + } + + return prev[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -966,6 +1070,36 @@ class Solution { } ``` +```swift +class Solution { + func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int { + var t1 = Array(text1) + var t2 = Array(text2) + + if t1.count < t2.count { + swap(&t1, &t2) + } + + var dp = Array(repeating: 0, count: t2.count + 1) + + for i in stride(from: t1.count - 1, through: 0, by: -1) { + var prev = 0 + for j in stride(from: t2.count - 1, through: 0, by: -1) { + let temp = dp[j] + if t1[i] == t2[j] { + dp[j] = 1 + prev + } else { + dp[j] = max(dp[j], dp[j + 1]) + } + prev = temp + } + } + + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/longest-consecutive-sequence.md b/articles/longest-consecutive-sequence.md index 9f7193486..22cd5db3f 100644 --- a/articles/longest-consecutive-sequence.md +++ b/articles/longest-consecutive-sequence.md @@ -143,6 +143,29 @@ class Solution { } ``` +```swift +class Solution { + func longestConsecutive(_ nums: [Int]) -> Int { + var res = 0 + let store = Set(nums) + + for num in nums { + var streak = 0 + var curr = num + + while store.contains(curr) { + streak += 1 + curr += 1 + } + + res = max(res, streak) + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -343,12 +366,44 @@ class Solution { } ``` +```swift +class Solution { + func longestConsecutive(_ nums: [Int]) -> Int { + if nums.isEmpty { + return 0 + } + + var res = 0 + var nums = nums.sorted() + + var curr = nums[0] + var streak = 0 + var i = 0 + + while i < nums.count { + if curr != nums[i] { + curr = nums[i] + streak = 0 + } + while i < nums.count && nums[i] == curr { + i += 1 + } + streak += 1 + curr += 1 + res = max(res, streak) + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n \log n)$ -* Space complexity: $O(1)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. --- @@ -506,6 +561,27 @@ class Solution { } ``` +```swift +class Solution { + func longestConsecutive(_ nums: [Int]) -> Int { + let numSet = Set(nums) + var longest = 0 + + for num in numSet { + if !numSet.contains(num - 1) { + var length = 1 + while numSet.contains(num + length) { + length += 1 + } + longest = max(length, longest) + } + } + + return longest + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -662,6 +738,31 @@ class Solution { } ``` +```swift +class Solution { + func longestConsecutive(_ nums: [Int]) -> Int { + var mp = [Int: Int]() + var res = 0 + + for num in nums { + if mp[num] == nil { + let left = mp[num - 1] ?? 0 + let right = mp[num + 1] ?? 0 + let length = left + right + 1 + + mp[num] = length + mp[num - left] = length + mp[num + right] = length + + res = max(res, length) + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/longest-happy-string.md b/articles/longest-happy-string.md index e5f2e0573..3b669e0e4 100644 --- a/articles/longest-happy-string.md +++ b/articles/longest-happy-string.md @@ -166,6 +166,45 @@ class Solution { } ``` +```csharp +public class Solution { + public string LongestDiverseString(int a, int b, int c) { + int[] count = new int[] { a, b, c }; + List res = new List(); + + int GetMax(int repeated) { + int idx = -1; + int maxCnt = 0; + for (int i = 0; i < 3; i++) { + if (i == repeated || count[i] == 0) continue; + if (maxCnt < count[i]) { + maxCnt = count[i]; + idx = i; + } + } + return idx; + } + + int repeated = -1; + while (true) { + int maxChar = GetMax(repeated); + if (maxChar == -1) break; + + res.Add((char)(maxChar + 'a')); + count[maxChar]--; + + if (res.Count > 1 && res[res.Count - 1] == res[res.Count - 2]) { + repeated = maxChar; + } else { + repeated = -1; + } + } + + return new string(res.ToArray()); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -283,18 +322,18 @@ class Solution { */ longestDiverseString(a, b, c) { const res = []; - const maxHeap = new MaxPriorityQueue({ priority: (x) => x[0] }); + const maxHeap = new MaxPriorityQueue(x => x[0]); if (a > 0) maxHeap.enqueue([a, 'a']); if (b > 0) maxHeap.enqueue([b, 'b']); if (c > 0) maxHeap.enqueue([c, 'c']); while (!maxHeap.isEmpty()) { - const [count, char] = maxHeap.dequeue().element; + const [count, char] = maxHeap.dequeue(); if (res.length > 1 && res[res.length - 1] === char && res[res.length - 2] === char) { if (maxHeap.isEmpty()) break; - const [count2, char2] = maxHeap.dequeue().element; + const [count2, char2] = maxHeap.dequeue(); res.push(char2); if (count2 - 1 > 0) maxHeap.enqueue([count2 - 1, char2]); maxHeap.enqueue([count, char]); @@ -309,6 +348,47 @@ class Solution { } ``` +```csharp +public class Solution { + public string LongestDiverseString(int a, int b, int c) { + string res = ""; + PriorityQueue<(int count, char ch), int> maxHeap = new PriorityQueue<(int, char), int>(); + + void AddToHeap(int count, char ch) { + if (count > 0) { + maxHeap.Enqueue((count, ch), -count); + } + } + + AddToHeap(a, 'a'); + AddToHeap(b, 'b'); + AddToHeap(c, 'c'); + + while (maxHeap.Count > 0) { + var (count1, ch1) = maxHeap.Dequeue(); + if (res.Length >= 2 && res[^1] == ch1 && res[^2] == ch1) { + if (maxHeap.Count == 0) break; + var (count2, ch2) = maxHeap.Dequeue(); + res += ch2; + count2--; + if (count2 > 0) { + maxHeap.Enqueue((count2, ch2), -count2); + } + maxHeap.Enqueue((count1, ch1), -count1); + } else { + res += ch1; + count1--; + if (count1 > 0) { + maxHeap.Enqueue((count1, ch1), -count1); + } + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -448,6 +528,35 @@ class Solution { } ``` +```csharp +public class Solution { + public string LongestDiverseString(int a, int b, int c) { + return string.Join("", Rec(a, b, c, 'a', 'b', 'c')); + } + + private List Rec(int max1, int max2, int max3, char char1, char char2, char char3) { + if (max1 < max2) return Rec(max2, max1, max3, char2, char1, char3); + if (max2 < max3) return Rec(max1, max3, max2, char1, char3, char2); + if (max2 == 0) { + int use = Math.Min(2, max1); + var res = new List(); + for (int i = 0; i < use; i++) res.Add(char1); + return res; + } + + int use1 = Math.Min(2, max1); + int use2 = (max1 - use1 >= max2) ? 1 : 0; + + var result = new List(); + for (int i = 0; i < use1; i++) result.Add(char1); + for (int i = 0; i < use2; i++) result.Add(char2); + + result.AddRange(Rec(max1 - use1, max2 - use2, max3, char1, char2, char3)); + return result; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/longest-increasing-path-in-matrix.md b/articles/longest-increasing-path-in-matrix.md index 950ac6e73..e529b1ded 100644 --- a/articles/longest-increasing-path-in-matrix.md +++ b/articles/longest-increasing-path-in-matrix.md @@ -230,6 +230,35 @@ class Solution { } ``` +```swift +class Solution { + func longestIncreasingPath(_ matrix: [[Int]]) -> Int { + let rows = matrix.count, cols = matrix[0].count + let directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] + + func dfs(_ r: Int, _ c: Int, _ prevVal: Int) -> Int { + if r < 0 || c < 0 || r >= rows || c >= cols || matrix[r][c] <= prevVal { + return 0 + } + + var res = 1 + for (dr, dc) in directions { + res = max(res, 1 + dfs(r + dr, c + dc, matrix[r][c])) + } + return res + } + + var lip = 0 + for r in 0.. Int { + let rows = matrix.count, cols = matrix[0].count + var dp = Array(repeating: Array(repeating: -1, count: cols), count: rows) + + func dfs(_ r: Int, _ c: Int, _ prevVal: Int) -> Int { + if r < 0 || r >= rows || c < 0 || c >= cols || matrix[r][c] <= prevVal { + return 0 + } + if dp[r][c] != -1 { + return dp[r][c] + } + + var res = 1 + res = max(res, 1 + dfs(r + 1, c, matrix[r][c])) + res = max(res, 1 + dfs(r - 1, c, matrix[r][c])) + res = max(res, 1 + dfs(r, c + 1, matrix[r][c])) + res = max(res, 1 + dfs(r, c - 1, matrix[r][c])) + + dp[r][c] = res + return res + } + + var maxPath = 0 + for r in 0.. Int { + let rows = matrix.count, cols = matrix[0].count + let directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] + var indegree = Array(repeating: Array(repeating: 0, count: cols), count: rows) + + for r in 0..= 0 && nr < rows && nc >= 0 && nc < cols && + matrix[nr][nc] < matrix[r][c]) { + indegree[r][c] += 1 + } + } + } + } + + var q = Deque<(Int, Int)>() + for r in 0..= 0 && nr < rows && nc >= 0 && nc < cols && + matrix[nr][nc] > matrix[r][c]) { + indegree[nr][nc] -= 1 + if indegree[nr][nc] == 0 { + q.append((nr, nc)) + } + } + } + } + LIS += 1 + } + return LIS + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/longest-increasing-subsequence.md b/articles/longest-increasing-subsequence.md index 1b24412eb..79391921a 100644 --- a/articles/longest-increasing-subsequence.md +++ b/articles/longest-increasing-subsequence.md @@ -170,6 +170,28 @@ class Solution { } ``` +```swift +class Solution { + func lengthOfLIS(_ nums: [Int]) -> Int { + func dfs(_ i: Int, _ j: Int) -> Int { + if i == nums.count { + return 0 + } + + var LIS = dfs(i + 1, j) // not include + + if j == -1 || nums[j] < nums[i] { + LIS = max(LIS, 1 + dfs(i + 1, i)) // include + } + + return LIS + } + + return dfs(0, -1) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -179,7 +201,7 @@ class Solution { --- -## 2. Dynamic Programming (Top-Down) +## 2. Dynamic Programming (Top-Down) - I ::tabs-start @@ -410,6 +432,508 @@ class Solution { } ``` +```swift +class Solution { + func lengthOfLIS(_ nums: [Int]) -> Int { + let n = nums.count + var memo = Array(repeating: Array(repeating: -1, count: n + 1), count: n) + + func dfs(_ i: Int, _ j: Int) -> Int { + if i == n { + return 0 + } + if memo[i][j + 1] != -1 { + return memo[i][j + 1] + } + + var LIS = dfs(i + 1, j) // not include + + if j == -1 || nums[j] < nums[i] { + LIS = max(LIS, 1 + dfs(i + 1, i)) // include + } + + memo[i][j + 1] = LIS + return LIS + } + + return dfs(0, -1) + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n ^ 2)$ + +--- + +## 3. Dynamic Programming (Top-Down) - II + +::tabs-start + +```python +class Solution: + def lengthOfLIS(self, nums: List[int]) -> int: + n = len(nums) + memo = [-1] * n + + def dfs(i): + if memo[i] != -1: + return memo[i] + + LIS = 1 + for j in range(i + 1, n): + if nums[i] < nums[j]: + LIS = max(LIS, 1 + dfs(j)) + + memo[i] = LIS + return LIS + + return max(dfs(i) for i in range(n)) +``` + +```java +public class Solution { + private int[] memo; + + public int lengthOfLIS(int[] nums) { + int n = nums.length; + memo = new int[n]; + Arrays.fill(memo, -1); + + int maxLIS = 1; + for (int i = 0; i < n; i++) { + maxLIS = Math.max(maxLIS, dfs(nums, i)); + } + return maxLIS; + } + + private int dfs(int[] nums, int i) { + if (memo[i] != -1) { + return memo[i]; + } + + int LIS = 1; + for (int j = i + 1; j < nums.length; j++) { + if (nums[i] < nums[j]) { + LIS = Math.max(LIS, 1 + dfs(nums, j)); + } + } + + memo[i] = LIS; + return LIS; + } +} +``` + +```cpp +class Solution { +private: + vector memo; + + int dfs(vector& nums, int i) { + if (memo[i] != -1) { + return memo[i]; + } + + int LIS = 1; + for (int j = i + 1; j < nums.size(); j++) { + if (nums[i] < nums[j]) { + LIS = max(LIS, 1 + dfs(nums, j)); + } + } + + return memo[i] = LIS; + } + +public: + int lengthOfLIS(vector& nums) { + int n = nums.size(); + memo.assign(n, -1); + + int maxLIS = 1; + for (int i = 0; i < n; i++) { + maxLIS = max(maxLIS, dfs(nums, i)); + } + return maxLIS; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + lengthOfLIS(nums) { + const n = nums.length; + const memo = new Array(n).fill(-1); + + const dfs = (i) => { + if (memo[i] !== -1) { + return memo[i]; + } + + let LIS = 1; + for (let j = i + 1; j < n; j++) { + if (nums[i] < nums[j]) { + LIS = Math.max(LIS, 1 + dfs(j)); + } + } + + memo[i] = LIS; + return LIS; + }; + + return Math.max(...nums.map((_, i) => dfs(i))); + } +} +``` + +```csharp +public class Solution { + private int[] memo; + + public int LengthOfLIS(int[] nums) { + int n = nums.Length; + memo = new int[n]; + Array.Fill(memo, -1); + + int maxLIS = 1; + for (int i = 0; i < n; i++) { + maxLIS = Math.Max(maxLIS, Dfs(nums, i)); + } + return maxLIS; + } + + private int Dfs(int[] nums, int i) { + if (memo[i] != -1) { + return memo[i]; + } + + int LIS = 1; + for (int j = i + 1; j < nums.Length; j++) { + if (nums[i] < nums[j]) { + LIS = Math.Max(LIS, 1 + Dfs(nums, j)); + } + } + + memo[i] = LIS; + return LIS; + } +} +``` + +```go +func lengthOfLIS(nums []int) int { + n := len(nums) + memo := make([]int, n) + for i := range memo { + memo[i] = -1 + } + + var dfs func(int) int + dfs = func(i int) int { + if memo[i] != -1 { + return memo[i] + } + + LIS := 1 + for j := i + 1; j < n; j++ { + if nums[i] < nums[j] { + LIS = max(LIS, 1+dfs(j)) + } + } + + memo[i] = LIS + return LIS + } + + maxLIS := 1 + for i := 0; i < n; i++ { + maxLIS = max(maxLIS, dfs(i)) + } + + return maxLIS +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` + +```kotlin +class Solution { + private lateinit var memo: IntArray + + fun lengthOfLIS(nums: IntArray): Int { + val n = nums.size + memo = IntArray(n) { -1 } + + var maxLIS = 1 + for (i in nums.indices) { + maxLIS = maxOf(maxLIS, dfs(nums, i)) + } + return maxLIS + } + + private fun dfs(nums: IntArray, i: Int): Int { + if (memo[i] != -1) { + return memo[i] + } + + var LIS = 1 + for (j in i + 1 until nums.size) { + if (nums[i] < nums[j]) { + LIS = maxOf(LIS, 1 + dfs(nums, j)) + } + } + + memo[i] = LIS + return LIS + } +} +``` + +```swift +class Solution { + func lengthOfLIS(_ nums: [Int]) -> Int { + let n = nums.count + var memo = Array(repeating: -1, count: n) + + func dfs(_ i: Int) -> Int { + if memo[i] != -1 { + return memo[i] + } + + var LIS = 1 + for j in (i + 1)..= 0; i--) { + for (int j = i - 1; j >= -1; j--) { + int LIS = dp[i + 1][j + 1]; // Not including nums[i] + + if (j == -1 || nums[j] < nums[i]) { + LIS = Math.max(LIS, 1 + dp[i + 1][i + 1]); // Including nums[i] + } + + dp[i][j + 1] = LIS; + } + } + + return dp[0][0]; + } +} +``` + +```cpp +class Solution { +public: + int lengthOfLIS(vector& nums) { + int n = nums.size(); + vector> dp(n + 1, vector(n + 1, 0)); + + for (int i = n - 1; i >= 0; --i) { + for (int j = i - 1; j >= -1; --j) { + int LIS = dp[i + 1][j + 1]; // Not including nums[i] + + if (j == -1 || nums[j] < nums[i]) { + LIS = max(LIS, 1 + dp[i + 1][i + 1]); // Including nums[i] + } + + dp[i][j + 1] = LIS; + } + } + + return dp[0][0]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + lengthOfLIS(nums) { + const n = nums.length; + const dp = Array.from({ length: n + 1 }, () => new Array(n + 1).fill(0)); + + for (let i = n - 1; i >= 0; i--) { + for (let j = i - 1; j >= -1; j--) { + let LIS = dp[i + 1][j + 1]; // Not including nums[i] + + if (j === -1 || nums[j] < nums[i]) { + LIS = Math.max(LIS, 1 + dp[i + 1][i + 1]); // Including nums[i] + } + + dp[i][j + 1] = LIS; + } + } + + return dp[0][0]; + } +} +``` + +```csharp +public class Solution { + public int LengthOfLIS(int[] nums) { + int n = nums.Length; + int[,] dp = new int[n + 1, n + 1]; + + for (int i = n - 1; i >= 0; i--) { + for (int j = i - 1; j >= -1; j--) { + int LIS = dp[i + 1, j + 1]; // Not including nums[i] + + if (j == -1 || nums[j] < nums[i]) { + LIS = Math.Max(LIS, 1 + dp[i + 1, i + 1]); // Including nums[i] + } + + dp[i, j + 1] = LIS; + } + } + + return dp[0, 0]; + } +} +``` + +```go +func lengthOfLIS(nums []int) int { + n := len(nums) + dp := make([][]int, n+1) + for i := range dp { + dp[i] = make([]int, n+1) + } + + for i := n - 1; i >= 0; i-- { + for j := i - 1; j >= -1; j-- { + LIS := dp[i+1][j+1] // Not including nums[i] + + if j == -1 || nums[j] < nums[i] { + LIS = max(LIS, 1+dp[i+1][i+1]) // Including nums[i] + } + + dp[i][j+1] = LIS + } + } + + return dp[0][0] +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` + +```kotlin +class Solution { + fun lengthOfLIS(nums: IntArray): Int { + val n = nums.size + val dp = Array(n + 1) { IntArray(n + 1) } + + for (i in n - 1 downTo 0) { + for (j in i - 1 downTo -1) { + var LIS = dp[i + 1][j + 1] // Not including nums[i] + + if (j == -1 || nums[j] < nums[i]) { + LIS = maxOf(LIS, 1 + dp[i + 1][i + 1]) // Including nums[i] + } + + dp[i][j + 1] = LIS + } + } + + return dp[0][0] + } +} +``` + +```swift +class Solution { + func lengthOfLIS(_ nums: [Int]) -> Int { + let n = nums.count + var dp = Array(repeating: Array(repeating: 0, count: n + 1), count: n + 1) + + for i in stride(from: n - 1, through: 0, by: -1) { + for j in stride(from: i - 1, through: -1, by: -1) { + var LIS = dp[i + 1][j + 1] // Not including nums[i] + + if j == -1 || nums[j] < nums[i] { + LIS = max(LIS, 1 + dp[i + 1][i + 1]) // Including nums[i] + } + + dp[i][j + 1] = LIS + } + } + + return dp[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -419,7 +943,7 @@ class Solution { --- -## 3. Dynamic Programming (Bottom-Up) +## 5. Dynamic Programming (Bottom-Up) - II ::tabs-start @@ -556,6 +1080,23 @@ class Solution { } ``` +```swift +class Solution { + func lengthOfLIS(_ nums: [Int]) -> Int { + var LIS = Array(repeating: 1, count: nums.count) + + for i in stride(from: nums.count - 1, through: 0, by: -1) { + for j in (i + 1)..> 1 + while j >= 1 { + tree[j] = max(tree[j << 1], tree[j << 1 | 1]) + j >>= 1 + } + } + + func query(_ l: Int, _ r: Int) -> Int { + if l > r { + return 0 + } + var res = Int.min + var l = l + n + var r = r + n + 1 + while l < r { + if l & 1 == 1 { + res = max(res, tree[l]) + l += 1 + } + if r & 1 == 1 { + r -= 1 + res = max(res, tree[r]) + } + l >>= 1 + r >>= 1 + } + return res + } +} + +class Solution { + func lengthOfLIS(_ nums: [Int]) -> Int { + func compress(_ arr: [Int]) -> [Int] { + let sortedArr = Array(Set(arr)).sorted() + return arr.map { sortedArr.firstIndex(of: $0)! } + } + + let nums = compress(nums) + let n = nums.count + let segTree = SegmentTree(n) + + var LIS = 0 + for num in nums { + let curLIS = segTree.query(0, num - 1) + 1 + segTree.update(num, curLIS) + LIS = max(LIS, curLIS) + } + return LIS + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1059,7 +1667,7 @@ class Solution { --- -## 5. Binary Search +## 7. Dynamic Programming + Binary Search ::tabs-start @@ -1237,6 +1845,39 @@ class Solution { } ``` +```swift +class Solution { + func lengthOfLIS(_ nums: [Int]) -> Int { + var dp = [nums[0]] + var LIS = 1 + + for i in 1.. Int { + var left = 0, right = dp.count - 1 + while left < right { + let mid = (left + right) / 2 + if dp[mid] < target { + left = mid + 1 + } else { + right = mid + } + } + return left + } +} +``` + ::tabs-end ### Time & Space Complexity 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 diff --git a/articles/longest-palindromic-substring.md b/articles/longest-palindromic-substring.md index 715d7c512..1d0f82c17 100644 --- a/articles/longest-palindromic-substring.md +++ b/articles/longest-palindromic-substring.md @@ -180,12 +180,38 @@ class Solution { } ``` +```swift +class Solution { + func longestPalindrome(_ s: String) -> String { + let chars = Array(s) + var res = "" + var resLen = 0 + + for i in 0..= r && resLen < (j - i + 1) { + res = String(chars[i...j]) + resLen = j - i + 1 + } + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n ^ 3)$ -* Space complexity: $O(1)$ +* Space complexity: $O(n)$ --- @@ -377,6 +403,31 @@ class Solution { } ``` +```swift +class Solution { + func longestPalindrome(_ s: String) -> String { + let chars = Array(s) + let n = chars.count + var resIdx = 0, resLen = 0 + var dp = Array(repeating: Array(repeating: false, count: n), count: n) + + for i in stride(from: n - 1, through: 0, by: -1) { + for j in i.. String { + let chars = Array(s) + var resIdx = 0 + var resLen = 0 + + for i in 0..= 0 && r < chars.count && chars[l] == chars[r] { + if (r - l + 1) > resLen { + resIdx = l + resLen = r - l + 1 + } + l -= 1 + r += 1 + } + + // Even length palindrome + l = i + r = i + 1 + while l >= 0 && r < chars.count && chars[l] == chars[r] { + if (r - l + 1) > resLen { + resIdx = l + resLen = r - l + 1 + } + l -= 1 + r += 1 + } + } + + return String(chars[resIdx.. String { + func manacher(_ s: String) -> [Int] { + let t = "#" + s.map { String($0) }.joined(separator: "#") + "#" + let tArray = Array(t) + let n = tArray.count + var p = [Int](repeating: 0, count: n) + var l = 0, r = 0 + + for i in 0..= 0 && + tArray[i + p[i] + 1] == tArray[i - p[i] - 1]) { + p[i] += 1 + } + if i + p[i] > r { + l = i - p[i] + r = i + p[i] + } + } + return p + } + + let p = manacher(s) + var resLen = 0, centerIndex = 0 + for (i, v) in p.enumerated() { + if v > resLen { + resLen = v + centerIndex = i + } + } + let resIdx = (centerIndex - resLen) / 2 + let start = s.index(s.startIndex, offsetBy: resIdx) + let end = s.index(start, offsetBy: resLen) + return String(s[start.. Int { + var res = 0 + let chars = Array(s) + + for i in 0.. Int { + var res = 0 + let charSet = Set(s) + let chars = Array(s) + + for c in charSet { + var count = 0, l = 0 + + for r in 0.. k { + if chars[l] == c { + count -= 1 + } + l += 1 + } + + res = max(res, r - l + 1) + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -563,6 +617,30 @@ class Solution { } ``` +```swift +class Solution { + func characterReplacement(_ s: String, _ k: Int) -> Int { + var count = [Character: Int]() + var res = 0 + var l = 0, maxf = 0 + let chars = Array(s) + + for r in 0.. k { + count[chars[l], default: 0] -= 1 + l += 1 + } + res = max(res, r - l + 1) + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity 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/longest-substring-without-duplicates.md b/articles/longest-substring-without-duplicates.md index a37747ed3..3d197dc21 100644 --- a/articles/longest-substring-without-duplicates.md +++ b/articles/longest-substring-without-duplicates.md @@ -137,6 +137,27 @@ class Solution { } ``` +```kotlin +class Solution { + func lengthOfLongestSubstring(_ s: String) -> Int { + var res = 0 + let chars = Array(s) + + for i in 0..() + for j in i.. Int { + var charSet = Set() + var l = 0, res = 0 + let chars = Array(s) + + for r in 0.. Int { + var mp = [Character: Int]() + var l = 0, res = 0 + let chars = Array(s) + + for r in 0.. TreeNode? { + guard let root = root, let p = p, let q = q else { + return nil + } + + if max(p.val, q.val) < root.val { + return lowestCommonAncestor(root.left, p, q) + } else if min(p.val, q.val) > root.val { + return lowestCommonAncestor(root.right, p, q) + } else { + return root + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -436,6 +468,41 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init(_ val: Int) { + * self.val = val + * self.left = nil + * self.right = nil + * } + * } + */ + +class Solution { + func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? { + var cur = root + + while let node = cur { + if let p = p, let q = q { + if p.val > node.val && q.val > node.val { + cur = node.right + } else if p.val < node.val && q.val < node.val { + cur = node.left + } else { + return node + } + } + } + return nil + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/lru-cache.md b/articles/lru-cache.md index d93c79886..2bd939f9c 100644 --- a/articles/lru-cache.md +++ b/articles/lru-cache.md @@ -279,6 +279,46 @@ class LRUCache(capacity: Int) { } ``` +```swift +class LRUCache { + private var cache: [(Int, Int)] + private let capacity: Int + + init(_ capacity: Int) { + self.cache = [] + self.capacity = capacity + } + + func get(_ key: Int) -> Int { + for i in 0.. Int { + if let node = cache[key] { + remove(node) + insert(node) + return node.val + } + return -1 + } + + func put(_ key: Int, _ value: Int) { + if let node = cache[key] { + remove(node) + } + let newNode = Node(key, value) + cache[key] = newNode + insert(newNode) + + if cache.count > cap { + if let lru = left.next { + remove(lru) + cache.removeValue(forKey: lru.key) + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1002,6 +1112,45 @@ class LRUCache(capacity: Int) { } ``` +```swift +class LRUCache { + private var capacity: Int + private var cache: [Int: Int] = [:] + private var keyOrder: [Int] = [] + + init(_ capacity: Int) { + self.capacity = capacity + } + + func get(_ key: Int) -> Int { + if let value = cache[key] { + if let index = keyOrder.firstIndex(of: key) { + keyOrder.remove(at: index) + } + keyOrder.append(key) + return value + } + return -1 + } + + func put(_ key: Int, _ value: Int) { + if cache[key] != nil { + if let index = keyOrder.firstIndex(of: key) { + keyOrder.remove(at: index) + } + } else if cache.count >= capacity { + if let lruKey = keyOrder.first { + cache.removeValue(forKey: lruKey) + keyOrder.removeFirst() + } + } + + cache[key] = value + keyOrder.append(key) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/majority-element-ii.md b/articles/majority-element-ii.md index 6ba0f2fd1..aca6e49c3 100644 --- a/articles/majority-element-ii.md +++ b/articles/majority-element-ii.md @@ -72,6 +72,24 @@ class Solution { } ``` +```csharp +public class Solution { + public List MajorityElement(int[] nums) { + HashSet res = new HashSet(); + int n = nums.Length; + + foreach (int num in nums) { + int count = nums.Count(x => x == num); + if (count > n / 3) { + res.Add(num); + } + } + + return res.ToList(); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -180,6 +198,30 @@ class Solution { } ``` +```csharp +public class Solution { + public List MajorityElement(int[] nums) { + Array.Sort(nums); + List res = new List(); + int n = nums.Length; + + int i = 0; + while (i < n) { + int j = i + 1; + while (j < n && nums[j] == nums[i]) { + j++; + } + if (j - i > n / 3) { + res.Add(nums[i]); + } + i = j; + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -271,6 +313,31 @@ class Solution { } ``` +```csharp +public class Solution { + public List MajorityElement(int[] nums) { + Dictionary count = new Dictionary(); + List res = new List(); + int n = nums.Length; + + foreach (int num in nums) { + if (!count.ContainsKey(num)) { + count[num] = 0; + } + count[num]++; + } + + foreach (var kvp in count) { + if (kvp.Value > n / 3) { + res.Add(kvp.Key); + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -444,6 +511,45 @@ class Solution { } ``` +```csharp +public class Solution { + public List MajorityElement(int[] nums) { + int n = nums.Length; + int num1 = -1, num2 = -1; + int cnt1 = 0, cnt2 = 0; + + foreach (int num in nums) { + if (num == num1) { + cnt1++; + } else if (num == num2) { + cnt2++; + } else if (cnt1 == 0) { + num1 = num; + cnt1 = 1; + } else if (cnt2 == 0) { + num2 = num; + cnt2 = 1; + } else { + cnt1--; + cnt2--; + } + } + + cnt1 = cnt2 = 0; + foreach (int num in nums) { + if (num == num1) cnt1++; + else if (num == num2) cnt2++; + } + + List res = new List(); + if (cnt1 > n / 3) res.Add(num1); + if (cnt2 > n / 3) res.Add(num2); + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -589,6 +695,49 @@ class Solution { } ``` +```csharp +public class Solution { + public List MajorityElement(int[] nums) { + Dictionary count = new Dictionary(); + + foreach (int num in nums) { + if (count.ContainsKey(num)) { + count[num]++; + } else { + count[num] = 1; + } + + if (count.Count <= 2) { + continue; + } + + Dictionary newCount = new Dictionary(); + foreach (var kvp in count) { + if (kvp.Value > 1) { + newCount[kvp.Key] = kvp.Value - 1; + } + } + count = newCount; + } + + List res = new List(); + foreach (int candidate in count.Keys) { + int freq = 0; + foreach (int num in nums) { + if (num == candidate) { + freq++; + } + } + if (freq > nums.Length / 3) { + res.Add(candidate); + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/majority-element.md b/articles/majority-element.md index 9ac32df2c..225347051 100644 --- a/articles/majority-element.md +++ b/articles/majority-element.md @@ -72,6 +72,26 @@ class Solution { } ``` +```csharp +public class Solution { + public int MajorityElement(int[] nums) { + int n = nums.Length; + foreach (int num in nums) { + int count = 0; + foreach (int i in nums) { + if (i == num) { + count++; + } + } + if (count > n / 2) { + return num; + } + } + return -1; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -158,6 +178,29 @@ class Solution { } ``` +```csharp +public class Solution { + public int MajorityElement(int[] nums) { + Dictionary count = new Dictionary(); + int res = 0, maxCount = 0; + + foreach (int num in nums) { + if (!count.ContainsKey(num)) { + count[num] = 0; + } + count[num]++; + + if (count[num] > maxCount) { + res = num; + maxCount = count[num]; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -210,6 +253,15 @@ class Solution { } ``` +```csharp +public class Solution { + public int MajorityElement(int[] nums) { + Array.Sort(nums); + return nums[nums.Length / 2]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -313,6 +365,30 @@ class Solution { } ``` +```csharp +public class Solution { + public int MajorityElement(int[] nums) { + int n = nums.Length; + int[] bit = new int[32]; + + foreach (int num in nums) { + for (int i = 0; i < 32; i++) { + bit[i] += (num >> i) & 1; + } + } + + int res = 0; + for (int i = 0; i < 32; i++) { + if (bit[i] > n / 2) { + res |= (1 << i); + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -393,6 +469,23 @@ class Solution { } ``` +```csharp +public class Solution { + public int MajorityElement(int[] nums) { + int res = 0, count = 0; + + foreach (int num in nums) { + if (count == 0) { + res = num; + } + count += (num == res) ? 1 : -1; + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -484,6 +577,25 @@ class Solution { } ``` +```csharp +public class Solution { + private static Random random = new Random(); + + public int MajorityElement(int[] nums) { + int n = nums.Length; + + while (true) { + int candidate = nums[random.Next(n)]; + int count = nums.Count(x => x == candidate); + + if (count > n / 2) { + return candidate; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity 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/matchsticks-to-square.md b/articles/matchsticks-to-square.md index c05819570..ae760c5ac 100644 --- a/articles/matchsticks-to-square.md +++ b/articles/matchsticks-to-square.md @@ -109,6 +109,39 @@ class Solution { } ``` +```csharp +public class Solution { + public bool Makesquare(int[] matchsticks) { + int total = 0; + foreach (int stick in matchsticks) { + total += stick; + } + if (total % 4 != 0) return false; + + int target = total / 4; + int[] sides = new int[4]; + + bool Dfs(int i) { + if (i == matchsticks.Length) { + return sides[0] == sides[1] && sides[1] == sides[2] && sides[2] == sides[3]; + } + + for (int side = 0; side < 4; side++) { + sides[side] += matchsticks[i]; + if (sides[side] <= target && Dfs(i + 1)) { + return true; + } + sides[side] -= matchsticks[i]; + } + + return false; + } + + return Dfs(0); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -266,6 +299,45 @@ class Solution { } ``` +```csharp +public class Solution { + public bool Makesquare(int[] matchsticks) { + int totalLength = 0; + foreach (int stick in matchsticks) { + totalLength += stick; + } + + if (totalLength % 4 != 0) { + return false; + } + + int length = totalLength / 4; + int[] sides = new int[4]; + Array.Sort(matchsticks, (a, b) => b.CompareTo(a)); // Sort in descending order + + bool Dfs(int i) { + if (i == matchsticks.Length) { + return true; + } + + for (int side = 0; side < 4; side++) { + if (sides[side] + matchsticks[i] <= length) { + sides[side] += matchsticks[i]; + if (Dfs(i + 1)) return true; + sides[side] -= matchsticks[i]; + } + + if (sides[side] == 0) break; + } + + return false; + } + + return Dfs(0); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -466,6 +538,46 @@ class Solution { } ``` +```csharp +public class Solution { + public bool Makesquare(int[] matchsticks) { + int totalLength = matchsticks.Sum(); + if (totalLength % 4 != 0) return false; + + int length = totalLength / 4; + if (matchsticks.Max() > length) return false; + + int n = matchsticks.Length; + int[] dp = Enumerable.Repeat(int.MinValue, 1 << n).ToArray(); + Array.Sort(matchsticks, (a, b) => b.CompareTo(a)); // Sort descending + + int Dfs(int mask) { + if (mask == 0) return 0; + if (dp[mask] != int.MinValue) return dp[mask]; + + for (int i = 0; i < n; i++) { + if ((mask & (1 << i)) != 0) { + int res = Dfs(mask ^ (1 << i)); + if (res >= 0 && res + matchsticks[i] <= length) { + dp[mask] = (res + matchsticks[i]) % length; + return dp[mask]; + } + if (mask == (1 << n) - 1) { + dp[mask] = -1; + return -1; + } + } + } + + dp[mask] = -1; + return -1; + } + + return Dfs((1 << n) - 1) != -1; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/max-area-of-island.md b/articles/max-area-of-island.md index 22f9f8b53..cb69ca56d 100644 --- a/articles/max-area-of-island.md +++ b/articles/max-area-of-island.md @@ -232,6 +232,34 @@ class Solution { } ``` +```swift +class Solution { + func maxAreaOfIsland(_ grid: [[Int]]) -> Int { + let ROWS = grid.count + let COLS = grid[0].count + var visit = Set<[Int]>() + var grid = grid + + func dfs(_ r: Int, _ c: Int) -> Int { + if (r < 0 || r == ROWS || c < 0 || c == COLS || + grid[r][c] == 0 || visit.contains([r, c])) { + return 0 + } + visit.insert([r, c]) + return 1 + dfs(r + 1, c) + dfs(r - 1, c) + dfs(r, c + 1) + dfs(r, c - 1) + } + + var area = 0 + for r in 0.. Int { + let directions = [[1, 0], [-1, 0], [0, 1], [0, -1]] + let ROWS = grid.count + let COLS = grid[0].count + var grid = grid + var area = 0 + + func bfs(_ r: Int, _ c: Int) -> Int { + var queue = Deque<(Int, Int)>() + grid[r][c] = 0 + queue.append((r, c)) + var res = 1 + + while !queue.isEmpty { + let (row, col) = queue.popFirst()! + for dir in directions { + let nr = row + dir[0] + let nc = col + dir[1] + if nr < 0 || nc < 0 || nr >= ROWS || nc >= COLS || grid[nr][nc] == 0 { + continue + } + queue.append((nr, nc)) + grid[nr][nc] = 0 + res += 1 + } + } + return res + } + + for r in 0.. Int { + if parent[node] != node { + parent[node] = find(parent[node]) + } + return parent[node] + } + + func union(_ u: Int, _ v: Int) -> Bool { + let pu = find(u) + let pv = find(v) + if pu == pv { + return false + } + if size[pu] >= size[pv] { + size[pu] += size[pv] + parent[pv] = pu + } else { + size[pv] += size[pu] + parent[pu] = pv + } + return true + } + + func getSize(_ node: Int) -> Int { + let par = find(node) + return size[par] + } +} + +class Solution { + func maxAreaOfIsland(_ grid: [[Int]]) -> Int { + var grid = grid + let ROWS = grid.count + let COLS = grid[0].count + let dsu = DSU(ROWS * COLS) + + func index(_ r: Int, _ c: Int) -> Int { + return r * COLS + c + } + + let directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] + var area = 0 + + for r in 0..= ROWS || nc >= COLS || grid[nr][nc] == 0 { + continue + } + dsu.union(index(r, c), index(nr, nc)) + } + area = max(area, dsu.getSize(index(r, c))) + } + } + } + + return area + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/max-water-container.md b/articles/max-water-container.md index dfd046f07..bb1ea6083 100644 --- a/articles/max-water-container.md +++ b/articles/max-water-container.md @@ -110,6 +110,20 @@ class Solution { } ``` +```swift +class Solution { + func maxArea(_ heights: [Int]) -> Int { + var res = 0 + for i in 0.. Int { + var l = 0, r = heights.count - 1 + var res = 0 + + while l < r { + let area = min(heights[l], heights[r]) * (r - l) + res = max(res, area) + if heights[l] <= heights[r] { + l += 1 + } else { + r -= 1 + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity 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/maximum-product-subarray.md b/articles/maximum-product-subarray.md index 5f5f0e299..f163b341f 100644 --- a/articles/maximum-product-subarray.md +++ b/articles/maximum-product-subarray.md @@ -137,6 +137,25 @@ class Solution { } ``` +```swift +class Solution { + func maxProduct(_ nums: [Int]) -> Int { + var res = nums[0] + + for i in 0.. Int { + var A = [[Int]]() + var cur = [Int]() + var res = Int.min + + for num in nums { + res = max(res, num) + if num == 0 { + if !cur.isEmpty { + A.append(cur) + } + cur = [] + } else { + cur.append(num) + } + } + + if !cur.isEmpty { + A.append(cur) + } + + for sub in A { + let negsCount = sub.filter { $0 < 0 }.count + var prod = 1 + var need = negsCount % 2 == 0 ? negsCount : negsCount - 1 + var negs = 0 + var j = 0 + + for i in 0.. need { + prod /= sub[j] + if sub[j] < 0 { + negs -= 1 + } + j += 1 + } + } + if j <= i { + res = max(res, prod) + } + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -642,6 +714,23 @@ class Solution { } ``` +```swift +class Solution { + func maxProduct(_ nums: [Int]) -> Int { + var res = nums[0] + var curMin = 1, curMax = 1 + + for num in nums { + let tmp = curMax * num + curMax = max(num * curMax, num * curMin, num) + curMin = min(tmp, num * curMin, num) + res = max(res, curMax) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -791,6 +880,23 @@ class Solution { } ``` +```swift +class Solution { + func maxProduct(_ nums: [Int]) -> Int { + let n = nums.count + var res = nums[0] + var prefix = 0, suffix = 0 + + for i in 0..(); + + for (int i = 0; i < n; i++) { + intervals.Add((startTime[i], endTime[i], profit[i])); + } + + intervals.Sort((a, b) => a.start.CompareTo(b.start)); + Dictionary cache = new(); + + int Dfs(int i) { + if (i == n) return 0; + if (cache.ContainsKey(i)) return cache[i]; + + // Option 1: don't include + int res = Dfs(i + 1); + + // Option 2: include current job + int j = i + 1; + while (j < n && intervals[j].start < intervals[i].end) { + j++; + } + + res = Math.Max(res, intervals[i].profit + Dfs(j)); + cache[i] = res; + return res; + } + + return Dfs(0); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -328,6 +364,48 @@ class Solution { } ``` +```csharp +public class Solution { + private int[][] intervals; + private int[] cache; + + public int JobScheduling(int[] startTime, int[] endTime, int[] profit) { + int n = startTime.Length; + intervals = new int[n][]; + cache = new int[n]; + Array.Fill(cache, -1); + + for (int i = 0; i < n; i++) { + intervals[i] = new int[] { startTime[i], endTime[i], profit[i] }; + } + + Array.Sort(intervals, (a, b) => a[0].CompareTo(b[0])); + return Dfs(0); + } + + private int Dfs(int i) { + if (i == intervals.Length) return 0; + if (cache[i] != -1) return cache[i]; + + int res = Dfs(i + 1); + + int left = i + 1, right = intervals.Length, j = intervals.Length; + while (left < right) { + int mid = left + (right - left) / 2; + if (intervals[mid][0] >= intervals[i][1]) { + j = mid; + right = mid; + } else { + left = mid + 1; + } + } + + cache[i] = Math.Max(res, intervals[i][2] + Dfs(j)); + return cache[i]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -517,6 +595,52 @@ class Solution { } ``` +```csharp +public class Solution { + private int[] startTime, endTime, profit, cache; + private int[] index; + private int n; + + public int JobScheduling(int[] startTime, int[] endTime, int[] profit) { + this.n = startTime.Length; + this.startTime = startTime; + this.endTime = endTime; + this.profit = profit; + this.index = new int[n]; + this.cache = new int[n]; + Array.Fill(cache, -1); + + for (int i = 0; i < n; i++) { + index[i] = i; + } + + Array.Sort(index, (a, b) => startTime[a].CompareTo(startTime[b])); + + return Dfs(0); + } + + private int Dfs(int i) { + if (i == n) return 0; + if (cache[i] != -1) return cache[i]; + + int res = Dfs(i + 1); + + int left = i + 1, right = n, j = n; + while (left < right) { + int mid = left + (right - left) / 2; + if (startTime[index[mid]] >= endTime[index[i]]) { + j = mid; + right = mid; + } else { + left = mid + 1; + } + } + + return cache[i] = Math.Max(res, profit[index[i]] + Dfs(j)); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -647,6 +771,37 @@ class Solution { } ``` +```csharp +public class Solution { + public int JobScheduling(int[] startTime, int[] endTime, int[] profit) { + int n = startTime.Length; + int[] index = new int[n]; + for (int i = 0; i < n; i++) index[i] = i; + + Array.Sort(index, (a, b) => startTime[a].CompareTo(startTime[b])); + + int[] dp = new int[n + 1]; + + for (int i = n - 1; i >= 0; i--) { + int left = i + 1, right = n, j = n; + while (left < right) { + int mid = left + (right - left) / 2; + if (startTime[index[mid]] >= endTime[index[i]]) { + j = mid; + right = mid; + } else { + left = mid + 1; + } + } + + dp[i] = Math.Max(dp[i + 1], profit[index[i]] + dp[j]); + } + + return dp[0]; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/maximum-subarray.md b/articles/maximum-subarray.md index afdcd634f..678ab39c8 100644 --- a/articles/maximum-subarray.md +++ b/articles/maximum-subarray.md @@ -119,6 +119,25 @@ class Solution { } ``` +```swift +class Solution { + func maxSubArray(_ nums: [Int]) -> Int { + let n = nums.count + var res = nums[0] + + for i in 0.. Int { + func dfs(_ i: Int, _ flag: Bool) -> Int { + if i == nums.count { + return flag ? 0 : Int.min + } + + if flag { + return max(0, nums[i] + dfs(i + 1, true)) + } + + return max(dfs(i + 1, false), nums[i] + dfs(i + 1, true)) + } + + return dfs(0, false) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -449,6 +488,33 @@ class Solution { } ``` +```swift +class Solution { + func maxSubArray(_ nums: [Int]) -> Int { + var memo = Array(repeating: [Int?](repeating: nil, count: 2), count: nums.count + 1) + + func dfs(_ i: Int, _ flag: Bool) -> Int { + if i == nums.count { + return flag ? 0 : Int.min + } + if let value = memo[i][flag ? 1 : 0] { + return value + } + + if flag { + memo[i][flag ? 1 : 0] = max(0, nums[i] + dfs(i + 1, true)) + } else { + memo[i][flag ? 1 : 0] = max(dfs(i + 1, false), nums[i] + dfs(i + 1, true)) + } + + return memo[i][flag ? 1 : 0]! + } + + return dfs(0, false) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -594,6 +660,24 @@ class Solution { } ``` +```swift +class Solution { + func maxSubArray(_ nums: [Int]) -> Int { + let n = nums.count + var dp = Array(repeating: [0, 0], count: n) + dp[n - 1][1] = nums[n - 1] + dp[n - 1][0] = nums[n - 1] + + for i in (0.. Int { + var dp = nums + + for i in 1.. Int { + var maxSub = nums[0] + var curSum = 0 + + for num in nums { + if curSum < 0 { + curSum = 0 + } + curSum += num + maxSub = max(maxSub, curSum) + } + + return maxSub + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1092,6 +1209,39 @@ class Solution { } ``` +```swift +class Solution { + func maxSubArray(_ nums: [Int]) -> Int { + + func dfs(_ l: Int, _ r: Int) -> Int { + if l > r { + return Int.min + } + + let m = (l + r) / 2 + var leftSum = 0 + var rightSum = 0 + var curSum = 0 + + for i in stride(from: m - 1, through: l, by: -1) { + curSum += nums[i] + leftSum = max(leftSum, curSum) + } + + curSum = 0 + for i in stride(from: m + 1, to: r + 1, by: 1) { + curSum += nums[i] + rightSum = max(rightSum, curSum) + } + + return max(dfs(l, m - 1), dfs(m + 1, r), leftSum + nums[m] + rightSum) + } + + return dfs(0, nums.count - 1) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/median-of-two-sorted-arrays.md b/articles/median-of-two-sorted-arrays.md index 6fb01b6af..3ac051111 100644 --- a/articles/median-of-two-sorted-arrays.md +++ b/articles/median-of-two-sorted-arrays.md @@ -127,6 +127,22 @@ class Solution { } ``` +```swift +class Solution { + func findMedianSortedArrays(_ nums1: [Int], _ nums2: [Int]) -> Double { + var merged = nums1 + nums2 + merged.sort() + + let totalLen = merged.count + if totalLen % 2 == 0 { + return (Double(merged[totalLen / 2 - 1]) + Double(merged[totalLen / 2])) / 2.0 + } else { + return Double(merged[totalLen / 2]) + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -391,6 +407,41 @@ class Solution { } ``` +```kotlin +class Solution { + func findMedianSortedArrays(_ nums1: [Int], _ nums2: [Int]) -> Double { + let len1 = nums1.count, len2 = nums2.count + var i = 0, j = 0 + var median1 = 0, median2 = 0 + + for _ in 0..<(len1 + len2) / 2 + 1 { + median2 = median1 + if i < len1 && j < len2 { + if nums1[i] > nums2[j] { + median1 = nums2[j] + j += 1 + } else { + median1 = nums1[i] + i += 1 + } + } else if i < len1 { + median1 = nums1[i] + i += 1 + } else { + median1 = nums2[j] + j += 1 + } + } + + if (len1 + len2) % 2 == 1 { + return Double(median1) + } else { + return (Double(median1) + Double(median2)) / 2.0 + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -653,12 +704,44 @@ class Solution { } ``` +```swift +class Solution { + func getKth(_ a: [Int], _ m: Int, _ b: [Int], _ n: Int, _ k: Int, _ aStart: Int = 0, _ bStart: Int = 0) -> Int { + if m > n { + return getKth(b, n, a, m, k, bStart, aStart) + } + if m == 0 { + return b[bStart + k - 1] + } + if k == 1 { + return min(a[aStart], b[bStart]) + } + + let i = min(m, k / 2) + let j = min(n, k / 2) + + if a[aStart + i - 1] > b[bStart + j - 1] { + return getKth(a, m, b, n - j, k - j, aStart, bStart + j) + } else { + return getKth(a, m - i, b, n, k - i, aStart + i, bStart) + } + } + + func findMedianSortedArrays(_ nums1: [Int], _ nums2: [Int]) -> Double { + let left = (nums1.count + nums2.count + 1) / 2 + let right = (nums1.count + nums2.count + 2) / 2 + return (Double(getKth(nums1, nums1.count, nums2, nums2.count, left)) + + Double(getKth(nums1, nums1.count, nums2, nums2.count, right))) / 2.0 + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(\log (m + n))$ -* Space complexity: $O(\log (m + n))$ +* Space complexity: $O(\log (m + n))$ for recursion stack. > Where $n$ is the length of $nums1$ and $m$ is the length of $nums2$. @@ -969,6 +1052,44 @@ class Solution { } ``` +```swift +class Solution { + func findMedianSortedArrays(_ nums1: [Int], _ nums2: [Int]) -> Double { + var A = nums1, B = nums2 + if A.count > B.count { + swap(&A, &B) + } + + let total = A.count + B.count + let half = total / 2 + var l = 0 + var r = A.count + + while true { + let i = (l + r) / 2 + let j = half - i + + let Aleft = i > 0 ? Double(A[i - 1]) : -Double.infinity + let Aright = i < A.count ? Double(A[i]) : Double.infinity + let Bleft = j > 0 ? Double(B[j - 1]) : -Double.infinity + let Bright = j < B.count ? Double(B[j]) : Double.infinity + + if Aleft <= Bright && Bleft <= Aright { + if total % 2 == 1 { + return min(Aright, Bright) + } else { + return (max(Aleft, Bleft) + min(Aright, Bright)) / 2.0 + } + } else if Aleft > Bright { + r = i - 1 + } else { + l = i + 1 + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/meeting-schedule-ii.md b/articles/meeting-schedule-ii.md index ce53b1e92..afd50a48e 100644 --- a/articles/meeting-schedule-ii.md +++ b/articles/meeting-schedule-ii.md @@ -193,6 +193,34 @@ class Solution { } ``` +```swift +/** + * Definition of Interval: + * class Interval { + * var start: Int + * var end: Int + * init(start: Int, end: Int) { + * self.start = start + * self.end = end + * } + * } + */ + +class Solution { + func minMeetingRooms(_ intervals: [Interval]) -> Int { + let sortedIntervals = intervals.sorted { $0.start < $1.start } + var minHeap = Heap() + for interval in sortedIntervals { + if !minHeap.isEmpty, let earliest = minHeap.min!, earliest <= interval.start { + minHeap.removeMin() + } + minHeap.insert(interval.end) + } + return minHeap.count + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -414,6 +442,37 @@ class Solution { } ``` +```swift +/** + * Definition of Interval: + * class Interval { + * var start: Int + * var end: Int + * init(start: Int, end: Int) { + * self.start = start + * self.end = end + * } + * } + */ + +class Solution { + func minMeetingRooms(_ intervals: [Interval]) -> Int { + var mp = [Int: Int]() + for interval in intervals { + mp[interval.start, default: 0] += 1 + mp[interval.end, default: 0] -= 1 + } + var prev = 0 + var res = 0 + for key in mp.keys.sorted() { + prev += mp[key]! + res = max(res, prev) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -689,6 +748,40 @@ class Solution { } ``` +```swift +/** + * Definition of Interval: + * class Interval { + * var start: Int + * var end: Int + * init(start: Int, end: Int) { + * self.start = start + * self.end = end + * } + * } + */ + +class Solution { + func minMeetingRooms(_ intervals: [Interval]) -> Int { + let starts = intervals.map { $0.start }.sorted() + let ends = intervals.map { $0.end }.sorted() + + var res = 0, count = 0, s = 0, e = 0 + while s < intervals.count { + if starts[s] < ends[e] { + count += 1 + s += 1 + } else { + count -= 1 + e += 1 + } + res = max(res, count) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -929,6 +1022,47 @@ class Solution { } ``` +```swift +/** + * Definition of Interval: + * class Interval { + * var start: Int + * var end: Int + * init(start: Int, end: Int) { + * self.start = start + * self.end = end + * } + * } + */ + +class Solution { + func minMeetingRooms(_ intervals: [Interval]) -> Int { + var times = [(Int, Int)]() + for interval in intervals { + times.append((interval.start, 1)) + times.append((interval.end, -1)) + } + + times.sort { + if $0.0 != $1.0 { + return $0.0 < $1.0 + } else { + return $0.1 < $1.1 + } + } + + var count = 0 + var res = 0 + for t in times { + count += t.1 + res = max(res, count) + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/meeting-schedule.md b/articles/meeting-schedule.md index 735df876a..226a6a70f 100644 --- a/articles/meeting-schedule.md +++ b/articles/meeting-schedule.md @@ -205,6 +205,36 @@ class Solution { } ``` +```swift +/** + * Definition of Interval: + * class Interval { + * var start: Int + * var end: Int + * init(start: Int, end: Int) { + * self.start = start + * self.end = end + * } + * } + */ + +class Solution { + func canAttendMeetings(_ intervals: [Interval]) -> Bool { + let n = intervals.count + for i in 0.. max(A.start, B.start) { + return false + } + } + } + return true + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -400,6 +430,32 @@ class Solution { } ``` +```swift +/** + * Definition of Interval: + * class Interval { + * var start: Int + * var end: Int + * init(start: Int, end: Int) { + * self.start = start + * self.end = end + * } + * } + */ + +class Solution { + func canAttendMeetings(_ intervals: [Interval]) -> Bool { + let sortedIntervals = intervals.sorted { $0.start < $1.start } + for i in 1.. sortedIntervals[i].start { + return false + } + } + return true + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/merge-intervals.md b/articles/merge-intervals.md index 56f8a6313..100d894b6 100644 --- a/articles/merge-intervals.md +++ b/articles/merge-intervals.md @@ -164,12 +164,36 @@ class Solution { } ``` +```swift +class Solution { + func merge(_ intervals: [[Int]]) -> [[Int]] { + let intervals = intervals.sorted { $0[0] < $1[0] } + var output: [[Int]] = [intervals[0]] + + for interval in intervals { + let start = interval[0] + let end = interval[1] + var lastEnd = output.last![1] + + if start <= lastEnd { + output[output.count - 1][1] = max(lastEnd, end) + } else { + output.append([start, end]) + } + } + return output + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n \log n)$ -* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. +* Space complexity: + * $O(1)$ or $O(n)$ space depending on the sorting algorithm. + * $O(n)$ for the output list. --- @@ -381,6 +405,38 @@ class Solution { } ``` +```swift +class Solution { + func merge(_ intervals: [[Int]]) -> [[Int]] { + var mp = [Int: Int]() + + for interval in intervals { + let start = interval[0] + let end = interval[1] + mp[start, default: 0] += 1 + mp[end, default: 0] -= 1 + } + + var res = [[Int]]() + var interval = [Int]() + var have = 0 + + for i in mp.keys.sorted() { + if interval.isEmpty { + interval.append(i) + } + have += mp[i, default: 0] + if have == 0 { + interval.append(i) + res.append(interval) + interval = [] + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -676,6 +732,44 @@ class Solution { } ``` +```swift +class Solution { + func merge(_ intervals: [[Int]]) -> [[Int]] { + let maxVal = intervals.map { $0[0] }.max() ?? 0 + var mp = [Int](repeating: 0, count: maxVal + 1) + for interval in intervals { + let start = interval[0] + let end = interval[1] + mp[start] = max(end + 1, mp[start]) + } + + var res = [[Int]]() + var have = -1 + var intervalStart = -1 + + for i in 0.. ListNode? { + var nodes: [Int] = [] + + for list in lists { + var lst = list + while lst != nil { + nodes.append(lst!.val) + lst = lst?.next + } + } + + nodes.sort() + + let dummy = ListNode(0) + var cur = dummy + for node in nodes { + cur.next = ListNode(node) + cur = cur.next! + } + + return dummy.next + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -510,6 +547,47 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func mergeKLists(_ lists: [ListNode?]) -> ListNode? { + var lists = lists + let dummy = ListNode(0) + var cur = dummy + + while true { + var minNodeIndex: Int? = nil + for i in 0.. ListNode? { + if lists.isEmpty { + return nil + } + + var lists = lists + for i in 1.. ListNode? { + let dummy = ListNode(0) + var tail = dummy + var l1 = l1, l2 = l2 + + while l1 != nil && l2 != nil { + if l1!.val < l2!.val { + tail.next = l1 + l1 = l1?.next + } else { + tail.next = l2 + l2 = l2?.next + } + tail = tail.next! + } + + if l1 != nil { + tail.next = l1 + } + if l2 != nil { + tail.next = l2 + } + + return dummy.next + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1157,6 +1288,60 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +struct NodeWrapper: Comparable { + let node: ListNode + + init(_ node: ListNode) { + self.node = node + } + + static func < (lhs: NodeWrapper, rhs: NodeWrapper) -> Bool { + return lhs.node.val < rhs.node.val + } + + static func == (lhs: NodeWrapper, rhs: NodeWrapper) -> Bool { + return lhs.node.val == rhs.node.val + } +} + +class Solution { + func mergeKLists(_ lists: [ListNode?]) -> ListNode? { + var heap = Heap() + + for list in lists { + if let node = list { + heap.insert(NodeWrapper(node)) + } + } + + let dummy = ListNode(0) + var tail = dummy + + while let wrapper = heap.popMin() { + tail.next = wrapper.node + tail = tail.next! + + if let next = wrapper.node.next { + heap.insert(NodeWrapper(next)) + } + } + + return dummy.next + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1190,14 +1375,17 @@ class Solution: return None if l == r: return lists[l] + mid = l + (r - l) // 2 left = self.divide(lists, l, mid) right = self.divide(lists, mid + 1, r) + return self.conquer(left, right) def conquer(self, l1, l2): dummy = ListNode(0) curr = dummy + while l1 and l2: if l1.val <= l2.val: curr.next = l1 @@ -1206,10 +1394,12 @@ class Solution: curr.next = l2 l2 = l2.next curr = curr.next + if l1: curr.next = l1 else: curr.next = l2 + return dummy.next ``` @@ -1240,9 +1430,11 @@ class Solution { if (l == r) { return lists[l]; } + int mid = l + (r - l) / 2; ListNode left = divide(lists, l, mid); ListNode right = divide(lists, mid + 1, r); + return conquer(left, right); } @@ -1302,15 +1494,18 @@ private: if (l == r) { return lists[l]; } + int mid = l + (r - l) / 2; ListNode* left = divide(lists, l, mid); ListNode* right = divide(lists, mid + 1, r); + return conquer(left, right); } ListNode* conquer(ListNode* l1, ListNode* l2) { ListNode dummy(0); ListNode* curr = &dummy; + while (l1 && l2) { if (l1->val <= l2->val) { curr->next = l1; @@ -1321,11 +1516,13 @@ private: } curr = curr->next; } + if (l1) { curr->next = l1; } else { curr->next = l2; } + return dummy.next; } }; @@ -1367,9 +1564,11 @@ class Solution { if (l === r) { return lists[l]; } + const mid = Math.floor(l + (r - l) / 2); const left = this.divide(lists, l, mid); const right = this.divide(lists, mid + 1, r); + return this.conquer(left, right); } @@ -1381,6 +1580,7 @@ class Solution { conquer(l1, l2) { const dummy = new ListNode(0); let curr = dummy; + while (l1 && l2) { if (l1.val <= l2.val) { curr.next = l1; @@ -1391,6 +1591,7 @@ class Solution { } curr = curr.next; } + curr.next = l1 ? l1 : l2; return dummy.next; } @@ -1425,9 +1626,11 @@ public class Solution { if (l == r) { return lists[l]; } + int mid = l + (r - l) / 2; ListNode left = Divide(lists, l, mid); ListNode right = Divide(lists, mid + 1, r); + return Conquer(left, right); } @@ -1479,15 +1682,18 @@ func divide(lists []*ListNode, left, right int) *ListNode { if left == right { return lists[left] } + mid := left + (right-left)/2 l1 := divide(lists, left, mid) l2 := divide(lists, mid+1, right) + return conquer(l1, l2) } func conquer(l1, l2 *ListNode) *ListNode { dummy := &ListNode{} curr := dummy + for l1 != nil && l2 != nil { if l1.Val <= l2.Val { curr.Next = l1 @@ -1498,11 +1704,13 @@ func conquer(l1, l2 *ListNode) *ListNode { } curr = curr.Next } + if l1 != nil { curr.Next = l1 } else { curr.Next = l2 } + return dummy.Next } ``` @@ -1526,9 +1734,11 @@ class Solution { private fun divide(lists: Array, left: Int, right: Int): ListNode? { if (left > right) return null if (left == right) return lists[left] + val mid = left + (right - left) / 2 val l1 = divide(lists, left, mid) val l2 = divide(lists, mid + 1, right) + return conquer(l1, l2) } @@ -1537,6 +1747,7 @@ class Solution { var curr = dummy var list1 = l1 var list2 = l2 + while (list1 != null && list2 != null) { if (list1.`val` <= list2.`val`) { curr.next = list1 @@ -1547,12 +1758,68 @@ class Solution { } curr = curr.next!! } + curr.next = list1 ?: list2 return dummy.next } } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func mergeKLists(_ lists: [ListNode?]) -> ListNode? { + if lists.isEmpty { + return nil + } + return divide(lists, 0, lists.count - 1) + } + + private func divide(_ lists: [ListNode?], _ l: Int, _ r: Int) -> ListNode? { + if l > r { + return nil + } + if l == r { + return lists[l] + } + + let mid = l + (r - l) / 2 + let left = divide(lists, l, mid) + let right = divide(lists, mid + 1, r) + return conquer(left, right) + } + + private func conquer(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? { + let dummy = ListNode(0) + var curr = dummy + var l1 = l1, l2 = l2 + + while let node1 = l1, let node2 = l2 { + if node1.val <= node2.val { + curr.next = node1 + l1 = node1.next + } else { + curr.next = node2 + l2 = node2.next + } + curr = curr.next! + } + + curr.next = l1 ?? l2 + return dummy.next + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1602,10 +1869,12 @@ class Solution: tail.next = l2 l2 = l2.next tail = tail.next + if l1: tail.next = l1 if l2: tail.next = l2 + return dummy.next ``` @@ -1653,12 +1922,14 @@ public class Solution { } tail = tail.next; } + if (l1 != null) { tail.next = l1; } if (l2 != null) { tail.next = l2; } + return dummy.next; } } @@ -1710,12 +1981,14 @@ private: } tail = tail->next; } + if (l1) { tail->next = l1; } if (l2) { tail->next = l2; } + return dummy.next; } }; @@ -1762,6 +2035,7 @@ class Solution { mergeList(l1, l2) { const dummy = new ListNode(0); let curr = dummy; + while (l1 && l2) { if (l1.val <= l2.val) { curr.next = l1; @@ -1772,6 +2046,7 @@ class Solution { } curr = curr.next; } + curr.next = l1 ? l1 : l2; return dummy.next; } @@ -1823,12 +2098,14 @@ public class Solution { } tail = tail.next; } + if (l1 != null) { tail.next = l1; } if (l2 != null) { tail.next = l2; } + return dummy.next; } } @@ -1876,11 +2153,13 @@ func mergeList(l1, l2 *ListNode) *ListNode { } tail = tail.Next } + if l1 != nil { tail.Next = l1 } else { tail.Next = l2 } + return dummy.Next } ``` @@ -1928,12 +2207,69 @@ class Solution { } tail = tail.next!! } + tail.next = list1 ?: list2 return dummy.next } } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func mergeKLists(_ lists: [ListNode?]) -> ListNode? { + if lists.isEmpty { + return nil + } + + var lists = lists + + while lists.count > 1 { + var mergedLists: [ListNode?] = [] + + for i in stride(from: 0, to: lists.count, by: 2) { + let l1 = lists[i] + let l2 = i + 1 < lists.count ? lists[i + 1] : nil + mergedLists.append(mergeList(l1, l2)) + } + + lists = mergedLists + } + + return lists[0] + } + + private func mergeList(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? { + let dummy = ListNode(0) + var tail = dummy + var l1 = l1, l2 = l2 + + while let node1 = l1, let node2 = l2 { + if node1.val < node2.val { + tail.next = node1 + l1 = node1.next + } else { + tail.next = node2 + l2 = node2.next + } + tail = tail.next! + } + + tail.next = l1 ?? l2 + return dummy.next + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/merge-sorted-array.md b/articles/merge-sorted-array.md index aab35dc73..a0e701ef0 100644 --- a/articles/merge-sorted-array.md +++ b/articles/merge-sorted-array.md @@ -53,6 +53,17 @@ class Solution { } ``` +```csharp +public class Solution { + public void Merge(int[] nums1, int m, int[] nums2, int n) { + for (int i = 0; i < n; i++) { + nums1[i + m] = nums2[i]; + } + Array.Sort(nums1); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -146,6 +157,25 @@ class Solution { } ``` +```csharp +public class Solution { + public void Merge(int[] nums1, int m, int[] nums2, int n) { + int[] nums1Copy = new int[m]; + Array.Copy(nums1, nums1Copy, m); + + int idx = 0, i = 0, j = 0; + + while (idx < m + n) { + if (j >= n || (i < m && nums1Copy[i] <= nums2[j])) { + nums1[idx++] = nums1Copy[i++]; + } else { + nums1[idx++] = nums2[j++]; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -270,6 +300,33 @@ class Solution { } ``` +```csharp +public class Solution { + public void Merge(int[] nums1, int m, int[] nums2, int n) { + int last = m + n - 1; + + // Merge in reverse order + while (m > 0 && n > 0) { + if (nums1[m - 1] > nums2[n - 1]) { + nums1[last] = nums1[m - 1]; + m--; + } else { + nums1[last] = nums2[n - 1]; + n--; + } + last--; + } + + // Fill nums1 with leftover nums2 elements + while (n > 0) { + nums1[last] = nums2[n - 1]; + n--; + last--; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -364,6 +421,23 @@ class Solution { } ``` +```csharp +public class Solution { + public void Merge(int[] nums1, int m, int[] nums2, int n) { + int last = m + n - 1; + int i = m - 1, j = n - 1; + + while (j >= 0) { + if (i >= 0 && nums1[i] > nums2[j]) { + nums1[last--] = nums1[i--]; + } else { + nums1[last--] = nums2[j--]; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/merge-strings-alternately.md b/articles/merge-strings-alternately.md index 04d95926d..d61a657cd 100644 --- a/articles/merge-strings-alternately.md +++ b/articles/merge-strings-alternately.md @@ -70,6 +70,27 @@ class Solution { } ``` +```csharp +public class Solution { + public string MergeAlternately(string word1, string word2) { + int i = 0, j = 0; + StringBuilder res = new StringBuilder(); + + while (i < word1.Length && j < word2.Length) { + res.Append(word1[i]); + res.Append(word2[j]); + i++; + j++; + } + + res.Append(word1.Substring(i)); + res.Append(word2.Substring(j)); + + return res.ToString(); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -152,6 +173,29 @@ class Solution { } ``` +```csharp +public class Solution { + public string MergeAlternately(string word1, string word2) { + int n = word1.Length, m = word2.Length; + int i = 0, j = 0; + StringBuilder res = new StringBuilder(); + + while (i < n || j < m) { + if (i < n) { + res.Append(word1[i]); + } + if (j < m) { + res.Append(word2[j]); + } + i++; + j++; + } + + return res.ToString(); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -240,6 +284,26 @@ class Solution { } ``` +```csharp +public class Solution { + public string MergeAlternately(string word1, string word2) { + int n = word1.Length, m = word2.Length; + StringBuilder res = new StringBuilder(); + + for (int i = 0; i < Math.Max(n, m); i++) { + if (i < n) { + res.Append(word1[i]); + } + if (i < m) { + res.Append(word2[i]); + } + } + + return res.ToString(); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/merge-triplets-to-form-target.md b/articles/merge-triplets-to-form-target.md index 4fe080b4c..268d8ae9d 100644 --- a/articles/merge-triplets-to-form-target.md +++ b/articles/merge-triplets-to-form-target.md @@ -138,6 +138,27 @@ class Solution { } ``` +```swift +class Solution { + func mergeTriplets(_ triplets: [[Int]], _ target: [Int]) -> Bool { + var good = Set() + + for t in triplets { + if t[0] > target[0] || t[1] > target[1] || t[2] > target[2] { + continue + } + for (i, v) in t.enumerated() { + if v == target[i] { + good.insert(i) + } + } + } + + return good.count == 3 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -268,6 +289,28 @@ class Solution { } ``` +```swift +class Solution { + func mergeTriplets(_ triplets: [[Int]], _ target: [Int]) -> Bool { + var x = false, y = false, z = false + + for t in triplets { + if t[0] <= target[0] && t[1] <= target[1] && t[2] <= target[2] { + if t[0] == target[0] { x = true } + if t[1] == target[1] { y = true } + if t[2] == target[2] { z = true } + } + + if x && y && z { + return true + } + } + + return false + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/merge-two-sorted-linked-lists.md b/articles/merge-two-sorted-linked-lists.md index bffc3e16f..b65407ade 100644 --- a/articles/merge-two-sorted-linked-lists.md +++ b/articles/merge-two-sorted-linked-lists.md @@ -203,6 +203,36 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func mergeTwoLists(_ list1: ListNode?, _ list2: ListNode?) -> ListNode? { + if list1 == nil { + return list2 + } + if list2 == nil { + return list1 + } + if list1!.val <= list2!.val { + list1!.next = mergeTwoLists(list1!.next, list2) + return list1 + } else { + list2!.next = mergeTwoLists(list1, list2!.next) + return list2 + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -473,6 +503,42 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func mergeTwoLists(_ list1: ListNode?, _ list2: ListNode?) -> ListNode? { + let dummy = ListNode(0) + var node = dummy + var l1 = list1 + var l2 = list2 + + while l1 != nil && l2 != nil { + if l1!.val < l2!.val { + node.next = l1 + l1 = l1?.next + } else { + node.next = l2 + l2 = l2?.next + } + node = node.next! + } + + node.next = l1 ?? l2 + + return dummy.next + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/min-cost-climbing-stairs.md b/articles/min-cost-climbing-stairs.md index 3c7139726..9433d007b 100644 --- a/articles/min-cost-climbing-stairs.md +++ b/articles/min-cost-climbing-stairs.md @@ -118,6 +118,21 @@ class Solution { } ``` +```swift +class Solution { + func minCostClimbingStairs(_ cost: [Int]) -> Int { + func dfs(_ i: Int) -> Int { + if i >= cost.count { + return 0 + } + return cost[i] + min(dfs(i + 1), dfs(i + 2)) + } + + return min(dfs(0), dfs(1)) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -291,6 +306,27 @@ class Solution { } ``` +```swift +class Solution { + func minCostClimbingStairs(_ cost: [Int]) -> Int { + var memo = Array(repeating: -1, count: cost.count) + + func dfs(_ i: Int) -> Int { + if i >= cost.count { + return 0 + } + if memo[i] != -1 { + return memo[i] + } + memo[i] = cost[i] + min(dfs(i + 1), dfs(i + 2)) + return memo[i] + } + + return min(dfs(0), dfs(1)) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -423,6 +459,22 @@ class Solution { } ``` +```swift +class Solution { + func minCostClimbingStairs(_ cost: [Int]) -> Int { + let n = cost.count + var dp = Array(repeating: 0, count: n + 1) + + for i in 2...n { + dp[i] = min(dp[i - 1] + cost[i - 1], + dp[i - 2] + cost[i - 2]) + } + + return dp[n] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -523,6 +575,17 @@ class Solution { } ``` +```swift +class Solution { + func minCostClimbingStairs(_ cost: inout [Int]) -> Int { + for i in stride(from: cost.count - 3, through: 0, by: -1) { + cost[i] += min(cost[i + 1], cost[i + 2]) + } + return min(cost[0], cost[1]) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/min-cost-to-connect-points.md b/articles/min-cost-to-connect-points.md index 8e9e5226a..6688ee3a1 100644 --- a/articles/min-cost-to-connect-points.md +++ b/articles/min-cost-to-connect-points.md @@ -45,7 +45,7 @@ class Solution: ``` ```java -public class DSU { +class DSU { int[] Parent, Size; public DSU(int n) { @@ -398,6 +398,68 @@ class Solution { } ``` +```swift +class DSU { + private var parent: [Int] + private var size: [Int] + + init(_ n: Int) { + parent = Array(0...n) + size = Array(repeating: 1, count: n + 1) + } + + func find(_ node: Int) -> Int { + if parent[node] != node { + parent[node] = find(parent[node]) + } + return parent[node] + } + + func union(_ u: Int, _ v: Int) -> Bool { + let pu = find(u) + let pv = find(v) + if pu == pv { + return false + } + if size[pu] < size[pv] { + parent[pu] = pv + size[pv] += size[pu] + } else { + parent[pv] = pu + size[pu] += size[pv] + } + return true + } +} + +class Solution { + func minCostConnectPoints(_ points: [[Int]]) -> Int { + let n = points.count + let dsu = DSU(n) + var edges = [(Int, Int, Int)]() + + for i in 0.. Bool { + return lhs.cost < rhs.cost + } +} + +class Solution { + func minCostConnectPoints(_ points: [[Int]]) -> Int { + let N = points.count + var adj = [Int: [(Int, Int)]]() + + for i in 0..() + var minHeap = Heap() + minHeap.insert(Item(cost: 0, node: 0)) + + while visit.count < N { + guard let item = minHeap.popMin() else { break } + let cost = item.cost + let i = item.node + + if visit.contains(i) { + continue + } + + res += cost + visit.insert(i) + + if let neighbors = adj[i] { + for (neiCost, nei) in neighbors { + if !visit.contains(nei) { + minHeap.insert(Item(cost: neiCost, node: nei)) + } + } + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -940,6 +1058,42 @@ class Solution { } ``` +```swift +class Solution { + func minCostConnectPoints(_ points: [[Int]]) -> Int { + let n = points.count + var node = 0 + var dist = Array(repeating: 100000000, count: n) + var visit = Array(repeating: false, count: n) + var edges = 0 + var res = 0 + + while edges < n - 1 { + visit[node] = true + var nextNode = -1 + + for i in 0.. 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/minimum-interval-including-query.md b/articles/minimum-interval-including-query.md index cd76921c2..3c1cf82d5 100644 --- a/articles/minimum-interval-including-query.md +++ b/articles/minimum-interval-including-query.md @@ -149,12 +149,39 @@ class Solution { } ``` +```swift +class Solution { + func minInterval(_ intervals: [[Int]], _ queries: [Int]) -> [Int] { + var res = [Int]() + + for q in queries { + var cur = -1 + for interval in intervals { + let l = interval[0] + let r = interval[1] + + if l <= q && q <= r { + if cur == -1 || (r - l + 1) < cur { + cur = r - l + 1 + } + } + } + res.append(cur) + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(m * n)$ -* Space complexity: $O(1)$ +* Space complexity: + * $O(1)$ extra space. + * $O(m)$ space for the output array. > Where $m$ is the length of the array $queries$ and $n$ is the length of the array $intervals$. @@ -508,6 +535,78 @@ class Solution { } ``` +```swift +struct Event { + let time: Int + let type: Int // 0: interval start, 1: query, 2: interval end + let size: Int? // interval size for start/end events + let idx: Int? // index for interval (for start/end) or query index (for query) +} + +struct Item: Comparable { + let size: Int + let idx: Int + + static func < (lhs: Item, rhs: Item) -> Bool { + return lhs.size < rhs.size + } +} + +class Solution { + func minInterval(_ intervals: [[Int]], _ queries: [Int]) -> [Int] { + var events = [Event]() + + // Create events for intervals + for (idx, interval) in intervals.enumerated() { + let start = interval[0] + let end = interval[1] + let intervalSize = end - start + 1 + events.append(Event(time: start, type: 0, size: intervalSize, idx: idx)) + events.append(Event(time: end, type: 2, size: intervalSize, idx: idx)) + } + + // Create events for queries + for (i, q) in queries.enumerated() { + events.append(Event(time: q, type: 1, size: nil, idx: i)) + } + + // Sort by time and type (end before query) + events.sort { (a, b) in + if a.time != b.time { + return a.time < b.time + } + return a.type < b.type + } + + // Min heap storing [size, index] + var sizes = Heap() + var ans = Array(repeating: -1, count: queries.count) + var inactive = Array(repeating: false, count: intervals.count) + + for event in events { + if event.type == 0 { // Interval start + let intervalSize = event.size! + let idx = event.idx! + sizes.insert(Item(size: intervalSize, idx: idx)) + } else if event.type == 2 { // Interval end + let idx = event.idx! + inactive[idx] = true + } else { // Query + let queryIdx = event.idx! + while !sizes.isEmpty, inactive[sizes.min!.idx] { + sizes.removeMin() + } + if !sizes.isEmpty { + ans[queryIdx] = sizes.min!.size + } + } + } + + return ans + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -779,6 +878,44 @@ class Solution { } ``` +```swift +struct HeapItem: Comparable { + let size: Int + let end: Int + static func < (lhs: HeapItem, rhs: HeapItem) -> Bool { + if lhs.size == rhs.size { + return lhs.end < rhs.end + } + return lhs.size < rhs.size + } +} + +class Solution { + func minInterval(_ intervals: [[Int]], _ queries: [Int]) -> [Int] { + let sortedIntervals = intervals.sorted { $0[0] < $1[0] } + var minHeap = Heap() + var res = [Int: Int]() + var i = 0 + + for q in queries.sorted() { + while i < sortedIntervals.count && sortedIntervals[i][0] <= q { + let l = sortedIntervals[i][0] + let r = sortedIntervals[i][1] + minHeap.insert(HeapItem(size: r - l + 1, end: r)) + i += 1 + } + + while !minHeap.isEmpty, minHeap.min!.end < q { + minHeap.removeMin() + } + res[q] = minHeap.isEmpty ? -1 : minHeap.min!.size + } + + return queries.map { res[$0] ?? -1 } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -871,7 +1008,7 @@ class Solution: ``` ```java -public class SegmentTree { +class SegmentTree { int n; int[] tree; int[] lazy; @@ -1471,11 +1608,120 @@ class Solution { } ``` +```swift +class SegmentTree { + let n: Int + var tree: [Int] + var lazy: [Int] + let INF = Int.max + + init(_ N: Int) { + self.n = N + self.tree = [Int](repeating: INF, count: 4 * N) + self.lazy = [Int](repeating: INF, count: 4 * N) + } + + // Propagate lazy value at tree index over range [lo, hi] + func propagate(_ treeidx: Int, _ lo: Int, _ hi: Int) { + if lazy[treeidx] != INF { + tree[treeidx] = min(tree[treeidx], lazy[treeidx]) + if lo != hi { + lazy[2 * treeidx + 1] = min(lazy[2 * treeidx + 1], lazy[treeidx]) + lazy[2 * treeidx + 2] = min(lazy[2 * treeidx + 2], lazy[treeidx]) + } + lazy[treeidx] = INF + } + } + + // Update the segment tree over range [left, right] with value val + func update(_ treeidx: Int, _ lo: Int, _ hi: Int, _ left: Int, _ right: Int, _ val: Int) { + propagate(treeidx, lo, hi) + if lo > right || hi < left { + return + } + if lo >= left && hi <= right { + lazy[treeidx] = min(lazy[treeidx], val) + propagate(treeidx, lo, hi) + return + } + let mid = (lo + hi) / 2 + update(2 * treeidx + 1, lo, mid, left, right, val) + update(2 * treeidx + 2, mid + 1, hi, left, right, val) + tree[treeidx] = min(tree[2 * treeidx + 1], tree[2 * treeidx + 2]) + } + + // Query the value at index idx in the original array + func query(_ treeidx: Int, _ lo: Int, _ hi: Int, _ idx: Int) -> Int { + propagate(treeidx, lo, hi) + if lo == hi { + return tree[treeidx] + } + let mid = (lo + hi) / 2 + if idx <= mid { + return query(2 * treeidx + 1, lo, mid, idx) + } else { + return query(2 * treeidx + 2, mid + 1, hi, idx) + } + } + + func update_range(_ left: Int, _ right: Int, _ val: Int) { + update(0, 0, n - 1, left, right, val) + } + + func query_point(_ idx: Int) -> Int { + return query(0, 0, n - 1, idx) + } +} + +class Solution { + func minInterval(_ intervals: [[Int]], _ queries: [Int]) -> [Int] { + var points = [Int]() + // Create events for intervals + for interval in intervals { + points.append(interval[0]) + points.append(interval[1]) + } + // Create events for queries + for q in queries { + points.append(q) + } + + // Compress the coordinates + let sortedPoints = Array(Set(points)).sorted() + var compress = [Int: Int]() + for (i, point) in sortedPoints.enumerated() { + compress[point] = i + } + + // Lazy Segment Tree + let segTree = SegmentTree(sortedPoints.count) + + for interval in intervals { + let start = compress[interval[0]]! + let end = compress[interval[1]]! + let length = interval[1] - interval[0] + 1 + segTree.update_range(start, end, length) + } + + var ans = [Int]() + for q in queries { + let idx = compress[q]! + // Query for minSize + let res = segTree.query_point(idx) + ans.append(res == segTree.INF ? -1 : res) + } + return ans + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O((n + m)\log k)$ -* Space complexity: $O(k)$ +* Space complexity: + * $O(k)$ extra space. + * $O(m)$ space for the output array. > Where $m$ is the length of the array $queries$, $n$ is the length of the array $intervals$ and $k$ is the number of unique points. \ No newline at end of file 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/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 diff --git a/articles/minimum-size-subarray-sum.md b/articles/minimum-size-subarray-sum.md index 74be08d78..683582184 100644 --- a/articles/minimum-size-subarray-sum.md +++ b/articles/minimum-size-subarray-sum.md @@ -94,6 +94,28 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinSubArrayLen(int target, int[] nums) { + int n = nums.Length; + int res = int.MaxValue; + + for (int i = 0; i < n; i++) { + int curSum = 0; + for (int j = i; j < n; j++) { + curSum += nums[j]; + if (curSum >= target) { + res = Math.Min(res, j - i + 1); + break; + } + } + } + + return res == int.MaxValue ? 0 : res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -188,6 +210,27 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinSubArrayLen(int target, int[] nums) { + int l = 0, total = 0; + int res = int.MaxValue; + + for (int r = 0; r < nums.Length; r++) { + total += nums[r]; + + while (total >= target) { + res = Math.Min(res, r - l + 1); + total -= nums[l]; + l++; + } + } + + return res == int.MaxValue ? 0 : res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -324,6 +367,39 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinSubArrayLen(int target, int[] nums) { + int n = nums.Length; + int[] prefixSum = new int[n + 1]; + + for (int i = 0; i < n; i++) { + prefixSum[i + 1] = prefixSum[i] + nums[i]; + } + + int res = n + 1; + + for (int i = 0; i < n; i++) { + int l = i, r = n; + while (l < r) { + int mid = (l + r) / 2; + int curSum = prefixSum[mid + 1] - prefixSum[i]; + if (curSum >= target) { + r = mid; + } else { + l = mid + 1; + } + } + if (l != n) { + res = Math.Min(res, l - i + 1); + } + } + + return res % (n + 1); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/minimum-stack.md b/articles/minimum-stack.md index 28527e995..29041a02c 100644 --- a/articles/minimum-stack.md +++ b/articles/minimum-stack.md @@ -278,6 +278,42 @@ class MinStack() { } ``` +```swift +class MinStack { + private var stack: [Int] = [] + + init() {} + + func push(_ val: Int) { + stack.append(val) + } + + func pop() { + stack.popLast() + } + + func top() -> Int { + return stack.last! + } + + func getMin() -> Int { + var tmp = [Int]() + var mini = stack.last! + + while !stack.isEmpty { + mini = min(mini, stack.last!) + tmp.append(stack.removeLast()) + } + + while !tmp.isEmpty { + stack.append(tmp.removeLast()) + } + + return mini + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -524,6 +560,34 @@ class MinStack() { } ``` +```swift +class MinStack { + private var stack: [Int] = [] + private var minStack: [Int] = [] + + init() {} + + func push(_ val: Int) { + stack.append(val) + let minVal = min(val, minStack.last ?? val) + minStack.append(minVal) + } + + func pop() { + stack.popLast() + minStack.popLast() + } + + func top() -> Int { + return stack.last! + } + + func getMin() -> Int { + return minStack.last! + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -543,14 +607,14 @@ class MinStack: self.min = float('inf') self.stack = [] - def push(self, x: int) -> None: + def push(self, val: int) -> None: if not self.stack: self.stack.append(0) - self.min = x + self.min = val else: - self.stack.append(x - self.min) - if x < self.min: - self.min = x + self.stack.append(val - self.min) + if val < self.min: + self.min = val def pop(self) -> None: if not self.stack: @@ -581,13 +645,13 @@ public class MinStack { stack = new Stack<>(); } - public void push(int x) { + public void push(int val) { if (stack.isEmpty()) { stack.push(0L); - min = x; + min = val; } else { - stack.push(x - min); - if (x < min) min = x; + stack.push(val - min); + if (val < min) min = val; } } @@ -621,9 +685,7 @@ private: std::stack stack; public: - MinStack() { - - } + MinStack() {} void push(int val) { if (stack.empty()) { @@ -755,14 +817,14 @@ func Constructor() MinStack { } } -func (this *MinStack) Push(x int) { +func (this *MinStack) Push(val int) { if len(this.stack) == 0 { this.stack = append(this.stack, 0) - this.min = x + this.min = val } else { - this.stack = append(this.stack, x - this.min) - if x < this.min { - this.min = x + this.stack = append(this.stack, val - this.min) + if val < this.min { + this.min = val } } } @@ -796,8 +858,8 @@ class MinStack() { private var min: Long = Long.MAX_VALUE private val stack = ArrayDeque() - fun push(x: Int) { - val valAsLong = x.toLong() + fun push(`val`: Int) { + val valAsLong = `val`.toLong() if (stack.isEmpty()) { stack.addLast(0L) min = valAsLong @@ -828,6 +890,48 @@ class MinStack() { } ``` +```swift +class MinStack { + private var minVal: Int = Int.max + private var stack: [Int] = [] + + init() {} + + func push(_ val: Int) { + if stack.isEmpty { + stack.append(0) + minVal = val + } else { + stack.append(val - minVal) + if val < minVal { + minVal = val + } + } + } + + func pop() { + if stack.isEmpty { + return + } + + let pop = stack.removeLast() + + if pop < 0 { + minVal -= pop + } + } + + func top() -> Int { + let top = stack.last! + return top > 0 ? top + minVal : minVal + } + + func getMin() -> Int { + return minVal + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/minimum-window-with-characters.md b/articles/minimum-window-with-characters.md index 9e0b36005..887cb769c 100644 --- a/articles/minimum-window-with-characters.md +++ b/articles/minimum-window-with-characters.md @@ -279,6 +279,48 @@ class Solution { } ``` +```swift +class Solution { + func minWindow(_ s: String, _ t: String) -> String { + if t.isEmpty { + return "" + } + + var countT = [Character: Int]() + for c in t { + countT[c, default: 0] += 1 + } + + var res = [-1, -1] + var resLen = Int.max + let chars = Array(s) + + for i in 0.. countS[c, default: 0] { + flag = false + break + } + } + + if flag && (j - i + 1) < resLen { + resLen = j - i + 1 + res = [i, j] + } + } + } + + let (l, r) = (res[0], res[1]) + return resLen != Int.max ? String(chars[l...r]) : "" + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -608,6 +650,53 @@ class Solution { } ``` +```swift +class Solution { + func minWindow(_ s: String, _ t: String) -> String { + if t.isEmpty { + return "" + } + + var countT = [Character: Int]() + var window = [Character: Int]() + for c in t { + countT[c, default: 0] += 1 + } + + var have = 0, need = countT.count + var res = [-1, -1], resLen = Int.max + let chars = Array(s) + var l = 0 + + for r in 0.. Int { + var nums = nums.sorted() + let n = nums.count + for i in 0.. Int { + let numSet = Set(nums) + let n = nums.count + for i in 0...n { + if !numSet.contains(i) { + return i + } + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -331,6 +361,21 @@ class Solution { } ``` +```swift +class Solution { + func missingNumber(_ nums: [Int]) -> Int { + let n = nums.count + var xorr = n + + for i in 0.. Int { + var res = nums.count + + for i in 0.. String { + if num1 == "0" || num2 == "0" { + return "0" + } + if num1.count < num2.count { + return multiply(num2, num1) + } + + var res = "" + var zero = 0 + let num2Arr = Array(num2) + + for i in stride(from: num2Arr.count - 1, through: 0, by: -1) { + let cur = mul(num1, num2Arr[i], zero) + res = add(res, cur) + zero += 1 + } + + return res + } + + func mul(_ s: String, _ d: Character, _ zero: Int) -> String { + var i = s.count - 1 + var carry = 0 + let dInt = Int(String(d))! + let sArr = Array(s) + var cur = [String]() + + while i >= 0 || carry > 0 { + let n = i >= 0 ? Int(String(sArr[i]))! : 0 + let prod = n * dInt + carry + cur.append(String(prod % 10)) + carry = prod / 10 + i -= 1 + } + + let prodStr = cur.reversed().joined() + let zeros = String(repeating: "0", count: zero) + return prodStr + zeros + } + + func add(_ num1: String, _ num2: String) -> String { + let s1 = Array(num1) + let s2 = Array(num2) + var i = s1.count - 1 + var j = s2.count - 1 + var carry = 0 + var res = [String]() + + while i >= 0 || j >= 0 || carry > 0 { + let n1 = i >= 0 ? Int(String(s1[i]))! : 0 + let n2 = j >= 0 ? Int(String(s2[j]))! : 0 + let total = n1 + n2 + carry + res.append(String(total % 10)) + carry = total / 10 + i -= 1 + j -= 1 + } + + return res.reversed().joined() + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -667,6 +733,37 @@ class Solution { } ``` +```swift +class Solution { + func multiply(_ num1: String, _ num2: String) -> String { + if num1 == "0" || num2 == "0" { + return "0" + } + + let n1 = Array(num1.reversed()).map { Int(String($0))! } + let n2 = Array(num2.reversed()).map { Int(String($0))! } + var res = [Int](repeating: 0, count: num1.count + num2.count) + + for i1 in 0..= 0; row--) { + if (board[row][c] == 'Q') return false; + } + + // Check top-left diagonal + for (int row = r - 1, col = c - 1; row >= 0 && col >= 0; row--, col--) { + if (board[row][col] == 'Q') return false; + } + + // Check top-right diagonal + for (int row = r - 1, col = c + 1; row >= 0 && col < board.Length; row--, col++) { + if (board[row][col] == 'Q') return false; + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -346,6 +397,43 @@ class Solution { } ``` +```csharp +public class Solution { + private HashSet col = new HashSet(); + private HashSet posDiag = new HashSet(); // r + c + private HashSet negDiag = new HashSet(); // r - c + private int res = 0; + + public int TotalNQueens(int n) { + res = 0; + Backtrack(0, n); + return res; + } + + private void Backtrack(int r, int n) { + if (r == n) { + res++; + return; + } + + for (int c = 0; c < n; c++) { + if (col.Contains(c) || posDiag.Contains(r + c) || negDiag.Contains(r - c)) + continue; + + col.Add(c); + posDiag.Add(r + c); + negDiag.Add(r - c); + + Backtrack(r + 1, n); + + col.Remove(c); + posDiag.Remove(r + c); + negDiag.Remove(r - c); + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -509,6 +597,42 @@ class Solution { } ``` +```csharp +public class Solution { + public int TotalNQueens(int n) { + bool[] col = new bool[n]; + bool[] posDiag = new bool[2 * n]; + bool[] negDiag = new bool[2 * n]; + int res = 0; + + void Backtrack(int r) { + if (r == n) { + res++; + return; + } + + for (int c = 0; c < n; c++) { + if (col[c] || posDiag[r + c] || negDiag[r - c + n]) + continue; + + col[c] = true; + posDiag[r + c] = true; + negDiag[r - c + n] = true; + + Backtrack(r + 1); + + col[c] = false; + posDiag[r + c] = false; + negDiag[r - c + n] = false; + } + } + + Backtrack(0); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -664,6 +788,44 @@ class Solution { } ``` +```csharp +public class Solution { + public int TotalNQueens(int n) { + int col = 0; + int posDiag = 0; + int negDiag = 0; + int res = 0; + + void Backtrack(int r) { + if (r == n) { + res++; + return; + } + + for (int c = 0; c < n; c++) { + if (((col & (1 << c)) != 0) || + ((posDiag & (1 << (r + c))) != 0) || + ((negDiag & (1 << (r - c + n))) != 0)) + continue; + + col ^= (1 << c); + posDiag ^= (1 << (r + c)); + negDiag ^= (1 << (r - c + n)); + + Backtrack(r + 1); + + col ^= (1 << c); + posDiag ^= (1 << (r + c)); + negDiag ^= (1 << (r - c + n)); + } + } + + Backtrack(0); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/n-queens.md b/articles/n-queens.md index 523b992a6..e75cd714b 100644 --- a/articles/n-queens.md +++ b/articles/n-queens.md @@ -334,6 +334,57 @@ class Solution { } ``` +```swift +class Solution { + func solveNQueens(_ n: Int) -> [[String]] { + var res = [[String]]() + var board = Array(repeating: Array(repeating: ".", count: n), count: n) + + func backtrack(_ r: Int) { + if r == n { + let copy = board.map { $0.joined() } + res.append(copy) + return + } + for c in 0.. Bool { + var row = r - 1 + while row >= 0 { + if board[row][c] == "Q" { return false } + row -= 1 + } + + var row1 = r - 1, col1 = c - 1 + while row1 >= 0, col1 >= 0 { + if board[row1][col1] == "Q" { return false } + row1 -= 1 + col1 -= 1 + } + + var row2 = r - 1, col2 = c + 1 + while row2 >= 0, col2 < board.count { + if board[row2][col2] == "Q" { return false } + row2 -= 1 + col2 += 1 + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -666,6 +717,47 @@ class Solution { } ``` +```swift +class Solution { + func solveNQueens(_ n: Int) -> [[String]] { + var col = Set() + var posDiag = Set() + var negDiag = Set() + var res = [[String]]() + var board = Array(repeating: Array(repeating: ".", count: n), count: n) + + func backtrack(_ r: Int) { + if r == n { + let copy = board.map { $0.joined() } + res.append(copy) + return + } + + for c in 0.. [[String]] { + var col = Array(repeating: false, count: n) + var posDiag = Array(repeating: false, count: 2 * n) + var negDiag = Array(repeating: false, count: 2 * n) + var res = [[String]]() + var board = Array(repeating: Array(repeating: ".", count: n), count: n) + + func backtrack(_ r: Int) { + if r == n { + let copy = board.map { $0.joined() } + res.append(copy) + return + } + + for c in 0.. [[String]] { + var col = 0 + var posDiag = 0 + var negDiag = 0 + var res = [[String]]() + var board = Array(repeating: Array(repeating: ".", count: n), count: n) + + func backtrack(_ r: Int) { + if r == n { + let copy = board.map { $0.joined() } + res.append(copy) + return + } + + for c in 0.. dp = new Dictionary(); + + public int Tribonacci(int n) { + if (n == 0) return 0; + if (n <= 2) return 1; + if (dp.ContainsKey(n)) return dp[n]; + + dp[n] = Tribonacci(n - 1) + Tribonacci(n - 2) + Tribonacci(n - 3); + return dp[n]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -220,6 +245,25 @@ class Solution { } ``` +```csharp +public class Solution { + public int Tribonacci(int n) { + if (n == 0) return 0; + if (n <= 2) return 1; + + int[] dp = new int[n + 1]; + dp[0] = 0; + dp[1] = dp[2] = 1; + + for (int i = 3; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]; + } + + return dp[n]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -293,6 +337,21 @@ class Solution { } ``` +```csharp +public class Solution { + public int Tribonacci(int n) { + int[] t = {0, 1, 1}; + if (n < 3) return t[n]; + + for (int i = 3; i <= n; i++) { + t[i % 3] = t[0] + t[1] + t[2]; + } + + return t[n % 3]; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/network-delay-time.md b/articles/network-delay-time.md index 1a9aa0afb..ae9fb93fc 100644 --- a/articles/network-delay-time.md +++ b/articles/network-delay-time.md @@ -216,6 +216,40 @@ class Solution { } ``` +```swift +class Solution { + func networkDelayTime(_ times: [[Int]], _ n: Int, _ k: Int) -> Int { + var adj = [Int: [(Int, Int)]]() + for time in times { + let u = time[0], v = time[1], w = time[2] + adj[u, default: []].append((v, w)) + } + + var dist = [Int: Int]() + for node in 1...n { + dist[node] = Int.max + } + + func dfs(_ node: Int, _ time: Int) { + if time >= dist[node]! { + return + } + + dist[node] = time + if let neighbors = adj[node] { + for (nei, w) in neighbors { + dfs(nei, time + w) + } + } + } + + dfs(k, 0) + let res = dist.values.max()! + return res == Int.max ? -1 : res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -450,6 +484,34 @@ class Solution { } ``` +```swift +class Solution { + func networkDelayTime(_ times: [[Int]], _ n: Int, _ k: Int) -> Int { + let inf = Int.max / 2 + var dist = Array(repeating: Array(repeating: inf, count: n), count: n) + + for time in times { + let u = time[0] - 1, v = time[1] - 1, w = time[2] + dist[u][v] = w + } + for i in 0..= inf ? -1 : res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -621,6 +683,32 @@ class Solution { } ``` +```swift +class Solution { + func networkDelayTime(_ times: [[Int]], _ n: Int, _ k: Int) -> Int { + var dist = Array(repeating: Int.max, count: n) + dist[k - 1] = 0 + + for _ in 0.. Int { + var adj = [Int: [(Int, Int)]]() + for time in times { + let u = time[0], v = time[1], w = time[2] + adj[u, default: []].append((v, w)) + } + + var dist = [Int: Int]() + for node in 1...n { + dist[node] = Int.max + } + dist[k] = 0 + + var queue = Deque<(Int, Int)>() + queue.append((k, 0)) + + while !queue.isEmpty { + let (node, time) = queue.popFirst()! + if dist[node]! < time { + continue + } + if let neighbors = adj[node] { + for (nei, w) in neighbors { + if time + w < dist[nei]! { + dist[nei] = time + w + queue.append((nei, time + w)) + } + } + } + } + + let res = dist.values.max()! + return res == Int.max ? -1 : res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1175,6 +1302,53 @@ class Solution { } ``` +```swift +struct Item: Comparable { + let weight: Int + let node: Int + + static func < (lhs: Item, rhs: Item) -> Bool { + return lhs.weight < rhs.weight + } +} + +class Solution { + func networkDelayTime(_ times: [[Int]], _ n: Int, _ k: Int) -> Int { + var edges = [Int: [(Int, Int)]]() + for time in times { + let u = time[0], v = time[1], w = time[2] + edges[u, default: []].append((v, w)) + } + + var minHeap = Heap() + minHeap.insert(Item(weight: 0, node: k)) + var visit = Set() + var t = 0 + + while !minHeap.isEmpty { + let item = minHeap.removeMin() + let w1 = item.weight + let n1 = item.node + + if visit.contains(n1) { + continue + } + visit.insert(n1) + t = w1 + + if let neighbors = edges[n1] { + for (n2, w2) in neighbors { + if !visit.contains(n2) { + minHeap.insert(Item(weight: w1 + w2, node: n2)) + } + } + } + } + return visit.count == n ? t : -1 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/non-cyclical-number.md b/articles/non-cyclical-number.md index 5290a69a7..6b3053011 100644 --- a/articles/non-cyclical-number.md +++ b/articles/non-cyclical-number.md @@ -206,6 +206,36 @@ class Solution { } ``` +```swift +class Solution { + func isHappy(_ n: Int) -> Bool { + var visit = Set() + var num = n + + while !visit.contains(num) { + visit.insert(num) + num = sumOfSquares(num) + if num == 1 { + return true + } + } + return false + } + + private func sumOfSquares(_ n: Int) -> Int { + var num = n + var output = 0 + + while num > 0 { + let digit = num % 10 + output += digit * digit + num /= 10 + } + return output + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -404,6 +434,34 @@ class Solution { } ``` +```swift +class Solution { + func isHappy(_ n: Int) -> Bool { + var slow = n + var fast = sumOfSquares(n) + + while slow != fast { + fast = sumOfSquares(fast) + fast = sumOfSquares(fast) + slow = sumOfSquares(slow) + } + return fast == 1 + } + + private func sumOfSquares(_ n: Int) -> Int { + var num = n + var output = 0 + + while num > 0 { + let digit = num % 10 + output += digit * digit + num /= 10 + } + return output + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -636,6 +694,40 @@ class Solution { } ``` +```swift +class Solution { + func isHappy(_ n: Int) -> Bool { + var slow = n + var fast = sumOfSquares(n) + var power = 1 + var lam = 1 + + while slow != fast { + if power == lam { + slow = fast + power *= 2 + lam = 0 + } + fast = sumOfSquares(fast) + lam += 1 + } + return fast == 1 + } + + private func sumOfSquares(_ n: Int) -> Int { + var num = n + var output = 0 + + while num > 0 { + let digit = num % 10 + output += digit * digit + num /= 10 + } + return output + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/non-overlapping-intervals.md b/articles/non-overlapping-intervals.md index 7970155cb..60f0b89a1 100644 --- a/articles/non-overlapping-intervals.md +++ b/articles/non-overlapping-intervals.md @@ -147,6 +147,28 @@ class Solution { } ``` +```swift +class Solution { + func eraseOverlapIntervals(_ intervals: [[Int]]) -> Int { + var intervals = intervals + intervals.sort { $0[0] < $1[0] } + + func dfs(_ i: Int, _ prev: Int) -> Int { + if i == intervals.count { + return 0 + } + var res = dfs(i + 1, prev) + if prev == -1 || intervals[prev][1] <= intervals[i][0] { + res = max(res, 1 + dfs(i + 1, i)) + } + return res + } + + return intervals.count - dfs(0, -1) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -365,6 +387,34 @@ class Solution { } ``` +```swift +class Solution { + func eraseOverlapIntervals(_ intervals: [[Int]]) -> Int { + var intervals = intervals + intervals.sort { $0[1] < $1[1] } + let n = intervals.count + var memo = [Int: Int]() + + func dfs(_ i: Int) -> Int { + if let result = memo[i] { + return result + } + + var res = 1 + for j in i + 1.. Int { + var intervals = intervals + intervals.sort { $0[1] < $1[1] } + let n = intervals.count + var dp = [Int](repeating: 0, count: n) + + for i in 0.. Int { + var intervals = intervals + intervals.sort { $0[1] < $1[1] } + let n = intervals.count + var dp = [Int](repeating: 0, count: n) + dp[0] = 1 + + func bs(_ r: Int, _ target: Int) -> Int { + var l = 0 + var r = r + while l < r { + let m = (l + r) >> 1 + if intervals[m][1] <= target { + l = m + 1 + } else { + r = m + } + } + return l + } + + for i in 1.. Int { + var intervals = intervals + intervals.sort { $0[0] < $1[0] } + + var res = 0 + var prevEnd = intervals[0][1] + + for i in 1..= prevEnd { + prevEnd = end + } else { + res += 1 + prevEnd = min(end, prevEnd) + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1142,6 +1275,28 @@ class Solution { } ``` +```swift +class Solution { + func eraseOverlapIntervals(_ intervals: [[Int]]) -> Int { + var intervals = intervals + intervals.sort { $0[1] < $1[1] } + + var prevEnd = intervals[0][1] + var res = 0 + + for i in 1.. intervals[i][0] { + res += 1 + } else { + prevEnd = intervals[i][1] + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/number-of-one-bits.md b/articles/number-of-one-bits.md index 9468bf89b..4ea545b0d 100644 --- a/articles/number-of-one-bits.md +++ b/articles/number-of-one-bits.md @@ -99,6 +99,20 @@ class Solution { } ``` +```swift +class Solution { + func hammingWeight(_ n: Int) -> Int { + var res = 0 + for i in 0..<32 { + if (1 << i) & n != 0 { + res += 1 + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -208,6 +222,20 @@ class Solution { } ``` +```swift +class Solution { + func hammingWeight(_ n: Int) -> Int { + var n = n + var res = 0 + while n != 0 { + res += (n & 1) != 0 ? 1 : 0 + n >>= 1 + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -313,6 +341,20 @@ class Solution { } ``` +```swift +class Solution { + func hammingWeight(_ n: Int) -> Int { + var n = n + var res = 0 + while n != 0 { + n &= (n - 1) + res += 1 + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -383,6 +425,14 @@ class Solution { } ``` +```swift +class Solution { + func hammingWeight(_ n: Int) -> Int { + return n.nonzeroBitCount + } +} +``` + ::tabs-end ### Time & Space Complexity 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/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/open-the-lock.md b/articles/open-the-lock.md index 6ded4c7ee..910704fd6 100644 --- a/articles/open-the-lock.md +++ b/articles/open-the-lock.md @@ -159,6 +159,44 @@ class Solution { } ``` +```csharp +public class Solution { + public int OpenLock(string[] deadends, string target) { + var dead = new HashSet(deadends); + if (dead.Contains("0000")) return -1; + + List Children(string lockStr) { + var res = new List(); + for (int i = 0; i < 4; i++) { + int digit = lockStr[i] - '0'; + string up = lockStr.Substring(0, i) + ((digit + 1) % 10) + lockStr.Substring(i + 1); + string down = lockStr.Substring(0, i) + ((digit + 9) % 10) + lockStr.Substring(i + 1); + res.Add(up); + res.Add(down); + } + return res; + } + + var q = new Queue<(string, int)>(); + q.Enqueue(("0000", 0)); + var visited = new HashSet(dead); + + while (q.Count > 0) { + var (lockStr, turns) = q.Dequeue(); + if (lockStr == target) return turns; + foreach (var child in Children(lockStr)) { + if (!visited.Contains(child)) { + visited.Add(child); + q.Enqueue((child, turns + 1)); + } + } + } + + return -1; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -313,6 +351,42 @@ class Solution { } ``` +```csharp +public class Solution { + public int OpenLock(string[] deadends, string target) { + if (target == "0000") return 0; + + var visited = new HashSet(deadends); + if (visited.Contains("0000")) return -1; + + var q = new Queue(); + q.Enqueue("0000"); + visited.Add("0000"); + int steps = 0; + + while (q.Count > 0) { + steps++; + int size = q.Count; + for (int i = 0; i < size; i++) { + string lockStr = q.Dequeue(); + for (int j = 0; j < 4; j++) { + foreach (int move in new int[] {1, -1}) { + int digit = (lockStr[j] - '0' + move + 10) % 10; + string nextLock = lockStr.Substring(0, j) + digit.ToString() + lockStr.Substring(j + 1); + if (visited.Contains(nextLock)) continue; + if (nextLock == target) return steps; + q.Enqueue(nextLock); + visited.Add(nextLock); + } + } + } + } + + return -1; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -491,6 +565,51 @@ class Solution { } ``` +```csharp +public class Solution { + public int OpenLock(string[] deadends, string target) { + if (target == "0000") return 0; + + var visit = new HashSet(deadends); + if (visit.Contains("0000")) return -1; + + var begin = new HashSet { "0000" }; + var end = new HashSet { target }; + int steps = 0; + + while (begin.Count > 0 && end.Count > 0) { + if (begin.Count > end.Count) { + var tempSet = begin; + begin = end; + end = tempSet; + } + + var temp = new HashSet(); + steps++; + + foreach (var lockStr in begin) { + for (int i = 0; i < 4; i++) { + foreach (int j in new int[] { -1, 1 }) { + int digit = (lockStr[i] - '0' + j + 10) % 10; + string nextLock = lockStr.Substring(0, i) + digit.ToString() + lockStr.Substring(i + 1); + + if (end.Contains(nextLock)) return steps; + if (visit.Contains(nextLock)) continue; + + visit.Add(nextLock); + temp.Add(nextLock); + } + } + } + + begin = temp; + } + + return -1; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/pacific-atlantic-water-flow.md b/articles/pacific-atlantic-water-flow.md index 1b718571a..1245a570d 100644 --- a/articles/pacific-atlantic-water-flow.md +++ b/articles/pacific-atlantic-water-flow.md @@ -351,6 +351,57 @@ class Solution { } ``` +```swift +class Solution { + func pacificAtlantic(_ heights: [[Int]]) -> [[Int]] { + var heights = heights + let ROWS = heights.count + let COLS = heights[0].count + let directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] + + var pacific = false + var atlantic = false + + func dfs(_ r: Int, _ c: Int, _ prevVal: Int) { + if r < 0 || c < 0 { + pacific = true + return + } + if r >= ROWS || c >= COLS { + atlantic = true + return + } + if heights[r][c] > prevVal { + return + } + + let tmp = heights[r][c] + heights[r][c] = Int.max + for dir in directions { + dfs(r + dir.0, c + dir.1, tmp) + if pacific && atlantic { + break + } + } + heights[r][c] = tmp + } + + var res = [[Int]]() + for r in 0.. [[Int]] { + let ROWS = heights.count + let COLS = heights[0].count + var pac = Set<[Int]>() + var atl = Set<[Int]>() + + func dfs(_ r: Int, _ c: Int, _ visit: inout Set<[Int]>, _ prevHeight: Int) { + if (visit.contains([r, c]) || r < 0 || c < 0 || r == ROWS || + c == COLS || heights[r][c] < prevHeight) { + return + } + visit.insert([r, c]) + dfs(r + 1, c, &visit, heights[r][c]) + dfs(r - 1, c, &visit, heights[r][c]) + dfs(r, c + 1, &visit, heights[r][c]) + dfs(r, c - 1, &visit, heights[r][c]) + } + + for c in 0.. [[Int]] { + let ROWS = heights.count + let COLS = heights[0].count + let directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] + + var pac = Array(repeating: Array(repeating: false, count: COLS), count: ROWS) + var atl = Array(repeating: Array(repeating: false, count: COLS), count: ROWS) + + func bfs(_ source: [(Int, Int)], _ ocean: inout [[Bool]]) { + var queue = Deque(source) + while !queue.isEmpty { + let (r, c) = queue.popFirst()! + ocean[r][c] = true + for dir in directions { + let nr = r + dir.0 + let nc = c + dir.1 + if nr >= 0, nr < ROWS, nc >= 0, nc < COLS, + !ocean[nr][nc], heights[nr][nc] >= heights[r][c] { + queue.append((nr, nc)) + } + } + } + } + + var pacific: [(Int, Int)] = [] + var atlantic: [(Int, Int)] = [] + + for c in 0.. [[String]] { + var res = [[String]]() + var part = [String]() + let sArray = Array(s) + + func dfs(_ j: Int, _ i: Int) { + if i >= sArray.count { + if i == j { + res.append(part) + } + return + } + + if isPali(sArray, j, i) { + part.append(String(sArray[j...i])) + dfs(i + 1, i + 1) + part.removeLast() + } + + dfs(j, i + 1) + } + + func isPali(_ s: [Character], _ l: Int, _ r: Int) -> Bool { + var l = l, r = r + while l < r { + if s[l] != s[r] { + return false + } + l += 1 + r -= 1 + } + return true + } + + dfs(0, 0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * 2 ^ n)$ -* Space complexity: $O(n)$ +* Space complexity: + * $O(n)$ extra space. + * $O(n * 2 ^ n)$ space for the output list. --- -## 2. Backtracking +## 2. Backtracking - II ::tabs-start @@ -562,12 +606,53 @@ class Solution { } ``` +```swift +class Solution { + func partition(_ s: String) -> [[String]] { + var res = [[String]]() + var part = [String]() + let sArray = Array(s) + + func dfs(_ i: Int) { + if i >= sArray.count { + res.append(part) + return + } + for j in i.. Bool { + var l = l, r = r + while l < r { + if s[l] != s[r] { + return false + } + l += 1 + r -= 1 + } + return true + } + + dfs(0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * 2 ^ n)$ -* Space complexity: $O(n)$ +* Space complexity: + * $O(n)$ extra space. + * $O(n * 2 ^ n)$ space for the output list. --- @@ -823,12 +908,51 @@ class Solution { } ``` +```swift +class Solution { + func partition(_ s: String) -> [[String]] { + let n = s.count + let sArray = Array(s) + var dp = Array(repeating: Array(repeating: false, count: n), count: n) + + for l in 1...n { + for i in 0...(n - l) { + dp[i][i + l - 1] = (sArray[i] == sArray[i + l - 1] && + (i + 1 > (i + l - 2) || dp[i + 1][i + l - 2])) + } + } + + var res = [[String]]() + var part = [String]() + + func dfs(_ i: Int) { + if i >= sArray.count { + res.append(part) + return + } + for j in i.. [[String]] { + let n = s.count + let sArray = Array(s) + var dp = Array(repeating: Array(repeating: false, count: n), count: n) + + for l in 1...n { + for i in 0...(n - l) { + dp[i][i + l - 1] = (sArray[i] == sArray[i + l - 1] && + (i + 1 > (i + l - 2) || dp[i + 1][i + l - 2])) + } + } + + func dfs(_ i: Int) -> [[String]] { + if i >= n { + return [[]] + } + + var ret = [[String]]() + for j in i.. Int { + let chars = Array(s) + var res = 0 + + for i in 0..= r { + res += 1 + } + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -313,6 +337,28 @@ class Solution { } ``` +```swift +class Solution { + func countSubstrings(_ s: String) -> Int { + let n = s.count + var res = 0 + var dp = Array(repeating: Array(repeating: false, count: n), count: n) + let chars = Array(s) + + for i in stride(from: n - 1, through: 0, by: -1) { + for j in i.. Int { + let chars = Array(s) + var res = 0 + + for i in 0..= 0 && r < chars.count && chars[l] == chars[r] { + res += 1 + l -= 1 + r += 1 + } + + // Even length palindromes + l = i + r = i + 1 + while l >= 0 && r < chars.count && chars[l] == chars[r] { + res += 1 + l -= 1 + r += 1 + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -722,6 +798,33 @@ class Solution { } ``` +```swift +class Solution { + func countSubstrings(_ s: String) -> Int { + var res = 0 + let chars = Array(s) + + for i in 0.. Int { + var res = 0 + var left = l, right = r + + while left >= 0 && right < s.count && s[left] == s[right] { + res += 1 + left -= 1 + right += 1 + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -982,6 +1085,42 @@ class Solution { } ``` +```swift +class Solution { + func countSubstrings(_ s: String) -> Int { + func manacher(_ s: String) -> [Int] { + let t = "#" + s.map { "\($0)#" }.joined() + let chars = Array(t) + let n = chars.count + var p = Array(repeating: 0, count: n) + var l = 0, r = 0 + + for i in 0..= 0, + chars[i + p[i] + 1] == chars[i - p[i] - 1] { + p[i] += 1 + } + if i + p[i] > r { + l = i - p[i] + r = i + p[i] + } + } + return p + } + + let p = manacher(s) + var res = 0 + for i in p { + res += (i + 1) / 2 + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/partition-equal-subset-sum.md b/articles/partition-equal-subset-sum.md index d51654692..6d6fd0caa 100644 --- a/articles/partition-equal-subset-sum.md +++ b/articles/partition-equal-subset-sum.md @@ -194,6 +194,33 @@ class Solution { } ``` +```swift +class Solution { + func canPartition(_ nums: [Int]) -> Bool { + let totalSum = nums.reduce(0, +) + if totalSum % 2 != 0 { + return false + } + + let target = totalSum / 2 + let n = nums.count + + func dfs(_ i: Int, _ target: Int) -> Bool { + if i >= n { + return target == 0 + } + if target < 0 { + return false + } + + return dfs(i + 1, target) || dfs(i + 1, target - nums[i]) + } + + return dfs(0, target) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -454,6 +481,39 @@ class Solution { } ``` +```swift +class Solution { + func canPartition(_ nums: [Int]) -> Bool { + let total = nums.reduce(0, +) + if total % 2 != 0 { + return false + } + + let target = total / 2 + let n = nums.count + var memo = Array(repeating: Array(repeating: -1, count: target + 1), count: n + 1) + + func dfs(_ i: Int, _ target: Int) -> Bool { + if target == 0 { + return true + } + if i >= n || target < 0 { + return false + } + if memo[i][target] != -1 { + return memo[i][target] == 1 + } + + let result = dfs(i + 1, target) || dfs(i + 1, target - nums[i]) + memo[i][target] = result ? 1 : 0 + return result + } + + return dfs(0, target) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -702,6 +762,37 @@ class Solution { } ``` +```swift +class Solution { + func canPartition(_ nums: [Int]) -> Bool { + let total = nums.reduce(0, +) + if total % 2 != 0 { + return false + } + + let target = total / 2 + let n = nums.count + var dp = Array(repeating: Array(repeating: false, count: target + 1), count: n + 1) + + for i in 0...n { + dp[i][0] = true + } + + for i in 1...n { + for j in 1...target { + if nums[i - 1] <= j { + dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]] + } else { + dp[i][j] = dp[i - 1][j] + } + } + } + + return dp[n][target] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -940,6 +1031,34 @@ class Solution { } ``` +```swift +class Solution { + func canPartition(_ nums: [Int]) -> Bool { + if nums.reduce(0, +) % 2 != 0 { + return false + } + + let target = nums.reduce(0, +) / 2 + var dp = Array(repeating: false, count: target + 1) + var nextDp = Array(repeating: false, count: target + 1) + + dp[0] = true + for num in nums { + for j in stride(from: target, through: 1, by: -1) { + if j >= num { + nextDp[j] = dp[j] || dp[j - num] + } else { + nextDp[j] = dp[j] + } + } + swap(&dp, &nextDp) + } + + return dp[target] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1147,6 +1266,32 @@ class Solution { } ``` +```swift +class Solution { + func canPartition(_ nums: [Int]) -> Bool { + if nums.reduce(0, +) % 2 != 0 { + return false + } + + var dp: Set = [0] + let target = nums.reduce(0, +) / 2 + + for i in stride(from: nums.count - 1, through: 0, by: -1) { + var nextDP: Set = [] + for t in dp { + if t + nums[i] == target { + return true + } + nextDP.insert(t + nums[i]) + nextDP.insert(t) + } + dp = nextDP + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1342,6 +1487,28 @@ class Solution { } ``` +```swift +class Solution { + func canPartition(_ nums: [Int]) -> Bool { + if nums.reduce(0, +) % 2 != 0 { + return false + } + + let target = nums.reduce(0, +) / 2 + var dp = Array(repeating: false, count: target + 1) + + dp[0] = true + for num in nums { + for j in stride(from: target, through: num, by: -1) { + dp[j] = dp[j] || dp[j - num] + } + } + + return dp[target] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1366,10 +1533,10 @@ class Solution: target = total // 2 dp = 1 << 0 - + for num in nums: dp |= dp << num - + return (dp & (1 << target)) != 0 ``` diff --git a/articles/partition-labels.md b/articles/partition-labels.md index 5eb089e85..1e4e2b3a1 100644 --- a/articles/partition-labels.md +++ b/articles/partition-labels.md @@ -169,6 +169,31 @@ class Solution { } ``` +```swift +class Solution { + func partitionLabels(_ s: String) -> [Int] { + var lastIndex = [Character: Int]() + for (i, c) in s.enumerated() { + lastIndex[c] = i + } + + var res = [Int]() + var size = 0 + var end = 0 + for (i, c) in s.enumerated() { + size += 1 + end = max(end, lastIndex[c]!) + + if i == end { + res.append(size) + size = 0 + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/partition-to-k-equal-sum-subsets.md b/articles/partition-to-k-equal-sum-subsets.md index 260fe7e37..d217736df 100644 --- a/articles/partition-to-k-equal-sum-subsets.md +++ b/articles/partition-to-k-equal-sum-subsets.md @@ -132,6 +132,38 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CanPartitionKSubsets(int[] nums, int k) { + int totalSum = nums.Sum(); + if (totalSum % k != 0) return false; + + int target = totalSum / k; + Array.Sort(nums); + Array.Reverse(nums); + + bool[] used = new bool[nums.Length]; + + bool Backtrack(int i, int kRemaining, int subsetSum) { + if (kRemaining == 0) return true; + if (subsetSum == target) return Backtrack(0, kRemaining - 1, 0); + + for (int j = i; j < nums.Length; j++) { + if (used[j] || subsetSum + nums[j] > target) continue; + + used[j] = true; + if (Backtrack(j + 1, kRemaining, subsetSum + nums[j])) return true; + used[j] = false; + } + + return false; + } + + return Backtrack(0, k, 0); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -291,6 +323,39 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CanPartitionKSubsets(int[] nums, int k) { + int total = nums.Sum(); + if (total % k != 0) return false; + + Array.Sort(nums); + Array.Reverse(nums); + int target = total / k; + bool[] used = new bool[nums.Length]; + + bool Backtrack(int i, int kRemaining, int subsetSum) { + if (kRemaining == 0) return true; + if (subsetSum == target) return Backtrack(0, kRemaining - 1, 0); + + for (int j = i; j < nums.Length; j++) { + if (used[j] || subsetSum + nums[j] > target) continue; + + used[j] = true; + if (Backtrack(j + 1, kRemaining, subsetSum + nums[j])) return true; + used[j] = false; + + if (subsetSum == 0) return false; // Pruning + } + + return false; + } + + return Backtrack(0, k, 0); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -442,6 +507,38 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CanPartitionKSubsets(int[] nums, int k) { + int total = nums.Sum(); + if (total % k != 0) return false; + + Array.Sort(nums); + Array.Reverse(nums); + int target = total / k; + int n = nums.Length; + + bool Backtrack(int i, int kRemaining, int subsetSum, int mask) { + if (kRemaining == 0) return true; + if (subsetSum == target) return Backtrack(0, kRemaining - 1, 0, mask); + + for (int j = i; j < n; j++) { + if ((mask & (1 << j)) == 0 || subsetSum + nums[j] > target) continue; + + if (Backtrack(j + 1, kRemaining, subsetSum + nums[j], mask ^ (1 << j))) + return true; + + if (subsetSum == 0) return false; + } + + return false; + } + + return Backtrack(0, k, 0, (1 << n) - 1); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -641,6 +738,53 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CanPartitionKSubsets(int[] nums, int k) { + int total = nums.Sum(); + if (total % k != 0) return false; + + Array.Sort(nums); + Array.Reverse(nums); + + int target = total / k; + int n = nums.Length; + bool?[] dp = new bool?[1 << n]; + + bool Backtrack(int i, int kRemaining, int subsetSum, int mask) { + if (dp[mask].HasValue) return (bool)dp[mask]; + if (kRemaining == 0) { + dp[mask] = true; + return true; + } + if (subsetSum == target) { + dp[mask] = Backtrack(0, kRemaining - 1, 0, mask); + return (bool)dp[mask]; + } + + for (int j = i; j < n; j++) { + if ((mask & (1 << j)) == 0 || subsetSum + nums[j] > target) continue; + + if (Backtrack(j + 1, kRemaining, subsetSum + nums[j], mask ^ (1 << j))) { + dp[mask] = true; + return true; + } + + if (subsetSum == 0) { + dp[mask] = false; + return false; + } + } + + dp[mask] = false; + return false; + } + + return Backtrack(0, k, 0, (1 << n) - 1); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -764,6 +908,35 @@ class Solution { } ``` +```csharp +public class Solution { + public bool CanPartitionKSubsets(int[] nums, int k) { + int total = nums.Sum(); + if (total % k != 0) return false; + + int target = total / k; + int n = nums.Length; + int N = 1 << n; + int[] dp = new int[N]; + for (int i = 1; i < N; i++) { + dp[i] = -1; + } + + for (int mask = 0; mask < N; mask++) { + if (dp[mask] == -1) continue; + for (int i = 0; i < n; i++) { + if ((mask & (1 << i)) == 0 && dp[mask] + nums[i] <= target) { + int nextMask = mask | (1 << i); + dp[nextMask] = (dp[mask] + nums[i]) % target; + } + } + } + + return dp[N - 1] == 0; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/path-with-minimum-effort.md b/articles/path-with-minimum-effort.md index bccc0e7b9..5f151c2c8 100644 --- a/articles/path-with-minimum-effort.md +++ b/articles/path-with-minimum-effort.md @@ -132,7 +132,7 @@ class Solution { ); dist[0][0] = 0; - const minHeap = new MinPriorityQueue({ priority: (a) => a[0] }); + const minHeap = new MinPriorityQueue(a => a[0]); minHeap.enqueue([0, 0, 0]); // [diff, row, col] const directions = [ @@ -141,7 +141,7 @@ class Solution { ]; while (!minHeap.isEmpty()) { - const [diff, r, c] = minHeap.dequeue().element; + const [diff, r, c] = minHeap.dequeue(); if (r === rows - 1 && c === cols - 1) return diff; if (dist[r][c] < diff) continue; @@ -169,6 +169,50 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinimumEffortPath(int[][] heights) { + int rows = heights.Length, cols = heights[0].Length; + var directions = new int[][] { + new int[] { 0, 1 }, + new int[] { 0, -1 }, + new int[] { 1, 0 }, + new int[] { -1, 0 } + }; + + var minHeap = new PriorityQueue<(int diff, int r, int c), int>(); + var visited = new HashSet<(int, int)>(); + minHeap.Enqueue((0, 0, 0), 0); + + while (minHeap.Count > 0) { + var current = minHeap.Dequeue(); + int diff = current.diff, r = current.r, c = current.c; + + if (visited.Contains((r, c))) continue; + visited.Add((r, c)); + + if (r == rows - 1 && c == cols - 1) { + return diff; + } + + foreach (var dir in directions) { + int newR = r + dir[0]; + int newC = c + dir[1]; + + if (newR < 0 || newC < 0 || newR >= rows || newC >= cols || visited.Contains((newR, newC))) { + continue; + } + + int newDiff = Math.Max(diff, Math.Abs(heights[r][c] - heights[newR][newC])); + minHeap.Enqueue((newDiff, newR, newC), newDiff); + } + } + + return 0; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -390,6 +434,59 @@ class Solution { } ``` +```csharp +public class Solution { + private int[][] directions = new int[][] { + new int[] { 0, 1 }, + new int[] { 0, -1 }, + new int[] { 1, 0 }, + new int[] { -1, 0 } + }; + + public int MinimumEffortPath(int[][] heights) { + int rows = heights.Length; + int cols = heights[0].Length; + + bool Dfs(int r, int c, int limit, HashSet<(int, int)> visited) { + if (r == rows - 1 && c == cols - 1) + return true; + + visited.Add((r, c)); + + foreach (var dir in directions) { + int newR = r + dir[0]; + int newC = c + dir[1]; + + if (newR < 0 || newC < 0 || newR >= rows || newC >= cols || + visited.Contains((newR, newC)) || + Math.Abs(heights[newR][newC] - heights[r][c]) > limit) + continue; + + if (Dfs(newR, newC, limit, visited)) + return true; + } + + return false; + } + + int left = 0, right = 1000000, res = right; + + while (left <= right) { + int mid = (left + right) / 2; + var visited = new HashSet<(int, int)>(); + if (Dfs(0, 0, mid, visited)) { + res = mid; + right = mid - 1; + } else { + left = mid + 1; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -654,6 +751,77 @@ class Solution { } ``` +```csharp +public class DSU { + private int[] parent; + private int[] size; + + public DSU(int n) { + parent = new int[n + 1]; + size = new int[n + 1]; + for (int i = 0; i <= n; i++) { + parent[i] = i; + size[i] = 1; + } + } + + public int Find(int node) { + if (parent[node] != node) { + parent[node] = Find(parent[node]); + } + return parent[node]; + } + + public bool Union(int u, int v) { + int pu = Find(u); + int pv = Find(v); + if (pu == pv) return false; + if (size[pu] < size[pv]) { + (pu, pv) = (pv, pu); + } + size[pu] += size[pv]; + parent[pv] = pu; + return true; + } +} + +public class Solution { + public int MinimumEffortPath(int[][] heights) { + int rows = heights.Length; + int cols = heights[0].Length; + List<(int, int, int)> edges = new List<(int, int, int)>(); + + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + int id = r * cols + c; + if (r + 1 < rows) { + int downId = (r + 1) * cols + c; + int diff = Math.Abs(heights[r][c] - heights[r + 1][c]); + edges.Add((diff, id, downId)); + } + if (c + 1 < cols) { + int rightId = r * cols + (c + 1); + int diff = Math.Abs(heights[r][c] - heights[r][c + 1]); + edges.Add((diff, id, rightId)); + } + } + } + + edges.Sort((a, b) => a.Item1.CompareTo(b.Item1)); + DSU dsu = new DSU(rows * cols); + + foreach (var (weight, u, v) in edges) { + dsu.Union(u, v); + if (dsu.Find(0) == dsu.Find(rows * cols - 1)) { + return weight; + } + } + + return 0; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -839,6 +1007,53 @@ class Solution { } ``` +```csharp +public class Solution { + public int MinimumEffortPath(int[][] heights) { + int rows = heights.Length; + int cols = heights[0].Length; + int[] dist = Enumerable.Repeat(int.MaxValue, rows * cols).ToArray(); + bool[] inQueue = new bool[rows * cols]; + dist[0] = 0; + + int Index(int r, int c) => r * cols + c; + + Queue queue = new Queue(); + queue.Enqueue(0); + inQueue[0] = true; + + int[][] directions = new int[][] { + new int[] {0, 1}, new int[] {0, -1}, + new int[] {1, 0}, new int[] {-1, 0} + }; + + while (queue.Count > 0) { + int u = queue.Dequeue(); + inQueue[u] = false; + int r = u / cols, c = u % cols; + + foreach (var dir in directions) { + int newR = r + dir[0], newC = c + dir[1]; + if (newR >= 0 && newR < rows && newC >= 0 && newC < cols) { + int v = Index(newR, newC); + int weight = Math.Abs(heights[r][c] - heights[newR][newC]); + int newDist = Math.Max(dist[u], weight); + if (newDist < dist[v]) { + dist[v] = newDist; + if (!inQueue[v]) { + queue.Enqueue(v); + inQueue[v] = true; + } + } + } + } + } + + return dist[rows * cols - 1]; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/perfect-squares.md b/articles/perfect-squares.md index ce067516a..eb92e5450 100644 --- a/articles/perfect-squares.md +++ b/articles/perfect-squares.md @@ -83,6 +83,25 @@ class Solution { } ``` +```csharp +public class Solution { + public int NumSquares(int n) { + return Dfs(n); + } + + private int Dfs(int target) { + if (target == 0) return 0; + + int res = target; + for (int i = 1; i * i <= target; i++) { + res = Math.Min(res, 1 + Dfs(target - i * i)); + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -193,6 +212,29 @@ class Solution { } ``` +```csharp +public class Solution { + private Dictionary memo = new Dictionary(); + + public int NumSquares(int n) { + return Dfs(n); + } + + private int Dfs(int target) { + if (target == 0) return 0; + if (memo.ContainsKey(target)) return memo[target]; + + int res = target; + for (int i = 1; i * i <= target; i++) { + res = Math.Min(res, 1 + Dfs(target - i * i)); + } + + memo[target] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -279,6 +321,25 @@ class Solution { } ``` +```csharp +public class Solution { + public int NumSquares(int n) { + int[] dp = new int[n + 1]; + Array.Fill(dp, n); + dp[0] = 0; + + for (int target = 1; target <= n; target++) { + for (int s = 1; s * s <= target; s++) { + int square = s * s; + dp[target] = Math.Min(dp[target], 1 + dp[target - square]); + } + } + + return dp[n]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -403,6 +464,40 @@ class Solution { } ``` +```csharp +public class Solution { + public int NumSquares(int n) { + Queue q = new Queue(); + HashSet seen = new HashSet(); + + int res = 0; + q.Enqueue(0); + + while (q.Count > 0) { + res++; + int size = q.Count; + for (int i = 0; i < size; i++) { + int cur = q.Dequeue(); + int s = 1; + while (s * s + cur <= n) { + int nxt = cur + s * s; + if (nxt == n) { + return res; + } + if (!seen.Contains(nxt)) { + seen.Add(nxt); + q.Enqueue(nxt); + } + s++; + } + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -540,6 +635,37 @@ class Solution { } ``` +```csharp +public class Solution { + public int NumSquares(int n) { + while (n % 4 == 0) { + n /= 4; + } + + if (n % 8 == 7) { + return 4; + } + + bool IsSquareNum(int num) { + int s = (int)Math.Sqrt(num); + return s * s == num; + } + + if (IsSquareNum(n)) { + return 1; + } + + for (int i = 1; i * i <= n; i++) { + if (IsSquareNum(n - i * i)) { + return 2; + } + } + + return 3; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/permutation-string.md b/articles/permutation-string.md index 07e79c7ef..482890ee4 100644 --- a/articles/permutation-string.md +++ b/articles/permutation-string.md @@ -149,6 +149,25 @@ class Solution { } ``` +```swift +class Solution { + func checkInclusion(_ s1: String, _ s2: String) -> Bool { + let s1Sorted = s1.sorted() + let chars = Array(s2) + + for i in 0.. Bool { + var count1 = [Character: Int]() + for c in s1 { + count1[c, default: 0] += 1 + } + + let need = count1.count + let chars = Array(s2) + + for i in 0.. Where $n$ is the length of the string1 and $m$ is the length of string2. @@ -736,6 +788,61 @@ class Solution { } ``` +```swift +class Solution { + func checkInclusion(_ s1: String, _ s2: String) -> Bool { + if s1.count > s2.count { + return false + } + + var s1Count = [Int](repeating: 0, count: 26) + var s2Count = [Int](repeating: 0, count: 26) + let aAscii = Int(Character("a").asciiValue!) + + let s1Array = Array(s1) + let s2Array = Array(s2) + + for i in 0..> PermuteUnique(int[] nums) { + HashSet resSet = new HashSet(); + List> result = new List>(); + Backtrack(new List(), nums, resSet, result); + return result; + } + + private void Backtrack(List perm, int[] nums, HashSet resSet, List> result) { + if (perm.Count == nums.Length) { + string key = string.Join(",", perm); + if (resSet.Add(key)) { + result.Add(new List(perm)); + } + return; + } + + for (int i = 0; i < nums.Length; i++) { + if (nums[i] != int.MinValue) { + int temp = nums[i]; + perm.Add(temp); + nums[i] = int.MinValue; + Backtrack(perm, nums, resSet, result); + nums[i] = temp; + perm.RemoveAt(perm.Count - 1); + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -268,6 +300,44 @@ class Solution { } ``` +```csharp +public class Solution { + public List> PermuteUnique(int[] nums) { + var res = new List>(); + var perm = new List(); + var count = new Dictionary(); + + foreach (int num in nums) { + if (!count.ContainsKey(num)) { + count[num] = 0; + } + count[num]++; + } + + void Dfs() { + if (perm.Count == nums.Length) { + res.Add(new List(perm)); + return; + } + + foreach (var kvp in count) { + int num = kvp.Key; + if (count[num] > 0) { + perm.Add(num); + count[num]--; + Dfs(); + count[num]++; + perm.RemoveAt(perm.Count - 1); + } + } + } + + Dfs(); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -413,6 +483,39 @@ class Solution { } ``` +```csharp +public class Solution { + public List> PermuteUnique(int[] nums) { + var res = new List>(); + var perm = new List(); + int n = nums.Length; + bool[] visit = new bool[n]; + Array.Sort(nums); + + void Dfs() { + if (perm.Count == n) { + res.Add(new List(perm)); + return; + } + + for (int i = 0; i < n; i++) { + if (visit[i]) continue; + if (i > 0 && nums[i] == nums[i - 1] && !visit[i - 1]) continue; + + visit[i] = true; + perm.Add(nums[i]); + Dfs(); + perm.RemoveAt(perm.Count - 1); + visit[i] = false; + } + } + + Dfs(); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -552,6 +655,41 @@ class Solution { } ``` +```csharp +public class Solution { + public List> PermuteUnique(int[] nums) { + var res = new List>(); + Array.Sort(nums); + Dfs(0); + return res; + + void Dfs(int i) { + if (i == nums.Length) { + res.Add(new List(nums)); + return; + } + + for (int j = i; j < nums.Length; j++) { + if (j > i && nums[j] == nums[i]) continue; + + Swap(i, j); + Dfs(i + 1); + } + + for (int j = nums.Length - 1; j > i; j--) { + Swap(i, j); + } + } + + void Swap(int a, int b) { + int temp = nums[a]; + nums[a] = nums[b]; + nums[b] = temp; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -704,6 +842,48 @@ class Solution { } ``` +```csharp +public class Solution { + public List> PermuteUnique(int[] nums) { + int n = nums.Length; + Array.Sort(nums); + var res = new List>(); + res.Add(new List(nums)); + + while (true) { + int i = n - 2; + while (i >= 0 && nums[i] >= nums[i + 1]) { + i--; + } + + if (i < 0) break; + + int j = n - 1; + while (nums[j] <= nums[i]) { + j--; + } + + Swap(nums, i, j); + + int left = i + 1, right = n - 1; + while (left < right) { + Swap(nums, left++, right--); + } + + res.Add(new List(nums)); + } + + return res; + } + + private void Swap(int[] nums, int i, int j) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/permutations.md b/articles/permutations.md index 492290c73..83dea1986 100644 --- a/articles/permutations.md +++ b/articles/permutations.md @@ -146,6 +146,29 @@ class Solution { } ``` +```swift +class Solution { + func permute(_ nums: [Int]) -> [[Int]] { + if nums.isEmpty { + return [[]] + } + + let perms = permute(Array(nums.dropFirst())) + var res = [[Int]]() + + for p in perms { + for i in 0...p.count { + var pCopy = p + pCopy.insert(nums[0], at: i) + res.append(pCopy) + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -303,6 +326,28 @@ class Solution { } ``` +```swift +class Solution { + func permute(_ nums: [Int]) -> [[Int]] { + var perms: [[Int]] = [[]] + + for num in nums { + var newPerms = [[Int]]() + for p in perms { + for i in 0...p.count { + var pCopy = p + pCopy.insert(num, at: i) + newPerms.append(pCopy) + } + } + perms = newPerms + } + + return perms + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -501,6 +546,35 @@ class Solution { } ``` +```swift +class Solution { + func permute(_ nums: [Int]) -> [[Int]] { + var res = [[Int]]() + var pick = [Bool](repeating: false, count: nums.count) + + func backtrack(_ perm: inout [Int]) { + if perm.count == nums.count { + res.append(perm) + return + } + for i in 0.. [[Int]] { + var res = [[Int]]() + + func backtrack(_ perm: inout [Int], _ mask: Int) { + if perm.count == nums.count { + res.append(perm) + return + } + for i in 0.. [[Int]] { + var res = [[Int]]() + var nums = nums + + func backtrack(_ idx: Int) { + if idx == nums.count { + res.append(nums) + return + } + for i in idx.. [Int] { + if digits.isEmpty { + return [1] + } + + var digits = digits + if digits[digits.count - 1] < 9 { + digits[digits.count - 1] += 1 + return digits + } else { + return plusOne(Array(digits.dropLast())) + [0] + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -139,7 +157,7 @@ class Solution { --- -## 2. Iteration +## 2. Iteration - I ::tabs-start @@ -148,7 +166,7 @@ class Solution: def plusOne(self, digits: List[int]) -> List[int]: one = 1 i = 0 - digits = digits[::-1] + digits.reverse() while one: if i < len(digits): @@ -161,7 +179,9 @@ class Solution: digits.append(one) one = 0 i += 1 - return digits[::-1] + + digits.reverse() + return digits ``` ```java @@ -339,16 +359,45 @@ class Solution { } ``` +```swift +class Solution { + func plusOne(_ digits: [Int]) -> [Int] { + var digits = digits + var one = 1 + var i = 0 + digits.reverse() + + while one > 0 { + if i < digits.count { + if digits[i] == 9 { + digits[i] = 0 + } else { + digits[i] += 1 + one = 0 + } + } else { + digits.append(one) + one = 0 + } + i += 1 + } + + digits.reverse() + return digits + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the language. --- -## 3. Iteration (Optimal) +## 3. Iteration - II ::tabs-start @@ -474,9 +523,28 @@ class Solution { } ``` +```swift +class Solution { + func plusOne(_ digits: [Int]) -> [Int] { + var digits = digits + let n = digits.count + + for i in stride(from: n - 1, through: 0, by: -1) { + if digits[i] < 9 { + digits[i] += 1 + return digits + } + digits[i] = 0 + } + + return [1] + digits + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ \ No newline at end of file +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/pow-x-n.md b/articles/pow-x-n.md index 341e3ae9d..50beeb0f4 100644 --- a/articles/pow-x-n.md +++ b/articles/pow-x-n.md @@ -139,6 +139,25 @@ class Solution { } ``` +```swift +class Solution { + func myPow(_ x: Double, _ n: Int) -> Double { + if x == 0 { + return 0 + } + if n == 0 { + return 1 + } + + var res: Double = 1 + for _ in 0..= 0 ? res : 1 / res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -320,12 +339,33 @@ class Solution { } ``` +```swift +class Solution { + func myPow(_ x: Double, _ n: Int) -> Double { + func helper(_ x: Double, _ n: Int) -> Double { + if x == 0 { + return 0 + } + if n == 0 { + return 1 + } + + let res = helper(x * x, n / 2) + return n % 2 == 0 ? res : x * res + } + + let res = helper(x, abs(n)) + return n >= 0 ? res : 1 / res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(\log n)$ -* Space complexity: $O(\log n)$ +* Space complexity: $O(\log n)$ for recursion stack. --- @@ -501,6 +541,33 @@ class Solution { } ``` +```swift +class Solution { + func myPow(_ x: Double, _ n: Int) -> Double { + if x == 0 { + return 0 + } + if n == 0 { + return 1 + } + + var res: Double = 1 + var base = x + var power = abs(n) + + while power > 0 { + if power & 1 == 1 { + res *= base + } + base *= base + power >>= 1 + } + + return n >= 0 ? res : 1 / res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/products-of-array-discluding-self.md b/articles/products-of-array-discluding-self.md index 1a74a5c68..1370fac97 100644 --- a/articles/products-of-array-discluding-self.md +++ b/articles/products-of-array-discluding-self.md @@ -142,12 +142,37 @@ class Solution { } ``` +```swift +class Solution { + func productExceptSelf(_ nums: [Int]) -> [Int] { + let n = nums.count + var res = [Int](repeating: 0, count: n) + + for i in 0.. [Int] { + var prod = 1 + var zeroCount = 0 + + for num in nums { + if num != 0 { + prod *= num + } else { + zeroCount += 1 + } + } + + if zeroCount > 1 { + return [Int](repeating: 0, count: nums.count) + } + + var res = [Int](repeating: 0, count: nums.count) + for (i, num) in nums.enumerated() { + if zeroCount > 0 { + res[i] = num == 0 ? prod : 0 + } else { + res[i] = prod / num + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n)$ -* Space complexity: $O(1)$ since the output array is excluded from space analysis. +* Space complexity: + * $O(1)$ extra space. + * $O(n)$ space for the output array. --- @@ -533,6 +592,34 @@ class Solution { } ``` +```swift +class Solution { + func productExceptSelf(_ nums: [Int]) -> [Int] { + let n = nums.count + var res = [Int](repeating: 0, count: n) + var pref = [Int](repeating: 0, count: n) + var suff = [Int](repeating: 0, count: n) + + pref[0] = 1 + suff[n - 1] = 1 + + for i in 1.. [Int] { + var res = [Int](repeating: 1, count: nums.count) + + var prefix = 1 + for i in 0.. int: + n = len(weights) + cache = {} + + def dfs(i, k): + if (i, k) in cache: + return cache[(i, k)] + if k == 0: + return [0, 0] + if i == n - 1 or n - i - 1 < k: + return [-float("inf"), float("inf")] + + res = [0, float("inf")] # [maxScore, minScore] + + # make partition + cur = dfs(i + 1, k - 1) + res[0] = max(res[0], weights[i] + weights[i + 1] + cur[0]) + res[1] = min(res[1], weights[i] + weights[i + 1] + cur[1]) + + # skip + cur = dfs(i + 1, k) + res[0] = max(res[0], cur[0]) + res[1] = min(res[1], cur[1]) + + cache[(i, k)] = res + return res + + ans = dfs(0, k - 1) + return ans[0] - ans[1] +``` + +```java +public class Solution { + Map cache = new HashMap<>(); + + public long putMarbles(int[] weights, int k) { + int n = weights.length; + long[] ans = dfs(0, k - 1, weights, n); + return ans[0] - ans[1]; + } + + private long[] dfs(int i, int k, int[] weights, int n) { + String key = i + "," + k; + if (cache.containsKey(key)) return cache.get(key); + if (k == 0) return new long[]{0L, 0L}; + if (i == n - 1 || n - i - 1 < k) { + return new long[]{(long)-1e15, (long)1e15}; + } + + long[] res = new long[]{0L, (long)1e15}; + + long[] cur = dfs(i + 1, k - 1, weights, n); + res[0] = Math.max(res[0], weights[i] + weights[i + 1] + cur[0]); + res[1] = Math.min(res[1], weights[i] + weights[i + 1] + cur[1]); + + cur = dfs(i + 1, k, weights, n); + res[0] = Math.max(res[0], cur[0]); + res[1] = Math.min(res[1], cur[1]); + + cache.put(key, res); + return res; + } +} +``` + +```cpp +class Solution { +public: + unordered_map> cache; + + long long putMarbles(vector& weights, int k) { + int n = weights.size(); + auto ans = dfs(0, k - 1, weights, n); + return ans.first - ans.second; + } + + pair dfs(int i, int k, vector& weights, int n) { + string key = to_string(i) + "," + to_string(k); + if (cache.count(key)) return cache[key]; + if (k == 0) return {0LL, 0LL}; + if (i == n - 1 || n - i - 1 < k) { + return {-1000000000000000LL, 1000000000000000LL}; + } + + pair res = {0LL, 1000000000000000LL}; + + auto cur = dfs(i + 1, k - 1, weights, n); + res.first = max(res.first, (long long)weights[i] + weights[i + 1] + cur.first); + res.second = min(res.second, (long long)weights[i] + weights[i + 1] + cur.second); + + cur = dfs(i + 1, k, weights, n); + res.first = max(res.first, cur.first); + res.second = min(res.second, cur.second); + + return cache[key] = res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} weights + * @param {number} k + * @return {number} + */ + putMarbles(weights, k) { + const n = weights.length; + const cache = new Map(); + + const dfs = (i, k) => { + const key = `${i},${k}`; + if (cache.has(key)) return cache.get(key); + if (k === 0) return [0, 0]; + if (i === n - 1 || n - i - 1 < k) return [-1e15, 1e15]; + + let res = [0, 1e15]; + + let cur = dfs(i + 1, k - 1); + res[0] = Math.max(res[0], weights[i] + weights[i + 1] + cur[0]); + res[1] = Math.min(res[1], weights[i] + weights[i + 1] + cur[1]); + + cur = dfs(i + 1, k); + res[0] = Math.max(res[0], cur[0]); + res[1] = Math.min(res[1], cur[1]); + + cache.set(key, res); + return res; + }; + + const ans = dfs(0, k - 1); + return ans[0] - ans[1]; + } +} +``` + +```csharp +public class Solution { + Dictionary cache = new Dictionary(); + + public long PutMarbles(int[] weights, int k) { + int n = weights.Length; + long[] ans = Dfs(0, k - 1, weights, n); + return (int)(ans[0] - ans[1]); + } + + private long[] Dfs(int i, int k, int[] weights, int n) { + string key = $"{i},{k}"; + if (cache.ContainsKey(key)) return cache[key]; + if (k == 0) return new long[] { 0L, 0L }; + if (i == n - 1 || n - i - 1 < k) { + return new long[] { -1000000000000000L, 1000000000000000L }; + } + + long[] res = new long[] { 0L, 1000000000000000L }; + + long[] cur = Dfs(i + 1, k - 1, weights, n); + res[0] = Math.Max(res[0], weights[i] + weights[i + 1] + cur[0]); + res[1] = Math.Min(res[1], weights[i] + weights[i + 1] + cur[1]); + + cur = Dfs(i + 1, k, weights, n); + res[0] = Math.Max(res[0], cur[0]); + res[1] = Math.Min(res[1], cur[1]); + + cache[key] = res; + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n * k)$ +* Space complexity: $O(n * k)$ + +> Where $n$ is the number of marbles, and $k$ is the number of bags. + +--- + +## 2. Greedy + Sorting + +::tabs-start + +```python +class Solution: + def putMarbles(self, weights: List[int], k: int) -> int: + if k == 1: + return 0 + + splits = [] + for i in range(len(weights) - 1): + splits.append(weights[i] + weights[i + 1]) + + splits.sort() + i = k - 1 + + max_score = sum(splits[-i:]) + min_score = sum(splits[:i]) + return max_score - min_score +``` + +```java +public class Solution { + public long putMarbles(int[] weights, int k) { + if (k == 1) return 0L; + + int n = weights.length; + List splits = new ArrayList<>(); + + for (int i = 0; i < n - 1; i++) { + splits.add(weights[i] + weights[i + 1]); + } + + Collections.sort(splits); + int i = k - 1; + long maxScore = 0, minScore = 0; + + for (int j = 0; j < i; j++) minScore += splits.get(j); + for (int j = splits.size() - i; j < splits.size(); j++) { + maxScore += splits.get(j); + } + + return maxScore - minScore; + } +} +``` + +```cpp +class Solution { +public: + long long putMarbles(vector& weights, int k) { + if (k == 1) return 0LL; + + int n = weights.size(); + vector splits; + + for (int i = 0; i < n - 1; ++i) { + splits.push_back(weights[i] + weights[i + 1]); + } + + sort(splits.begin(), splits.end()); + int i = k - 1; + long long minScore = 0, maxScore = 0; + + for (int j = 0; j < i; ++j) minScore += splits[j]; + for (int j = splits.size() - i; j < splits.size(); ++j) { + maxScore += splits[j]; + } + + return maxScore - minScore; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} weights + * @param {number} k + * @return {number} + */ + putMarbles(weights, k) { + if (k === 1) return 0; + + const splits = []; + for (let i = 0; i < weights.length - 1; i++) { + splits.push(weights[i] + weights[i + 1]); + } + + splits.sort((a, b) => a - b); + const i = k - 1; + + let minScore = 0, maxScore = 0; + for (let j = 0; j < i; j++) minScore += splits[j]; + for (let j = splits.length - i; j < splits.length; j++) { + maxScore += splits[j]; + } + + return maxScore - minScore; + } +} +``` + +```csharp +public class Solution { + public long PutMarbles(int[] weights, int k) { + if (k == 1) return 0L; + + int n = weights.Length; + List splits = new List(); + + for (int i = 0; i < n - 1; i++) { + splits.Add(weights[i] + weights[i + 1]); + } + + splits.Sort(); + int iVal = k - 1; + long minScore = 0, maxScore = 0; + + for (int j = 0; j < iVal; j++) minScore += splits[j]; + for (int j = splits.Count - iVal; j < splits.Count; j++) { + maxScore += splits[j]; + } + + return maxScore - minScore; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +> Where $n$ is the number of marbles, and $k$ is the number of bags. + +--- + +## 3. Heap + +::tabs-start + +```python +class Solution: + def putMarbles(self, weights: List[int], k: int) -> int: + if k == 1: + return 0 + + max_heap = [] + min_heap = [] + + for i in range(len(weights) - 1): + split = weights[i] + weights[i + 1] + + if len(max_heap) < k - 1: + heapq.heappush(max_heap, split) + else: + heapq.heappushpop(max_heap, split) + + if len(min_heap) < k - 1: + heapq.heappush(min_heap, -split) + else: + heapq.heappushpop(min_heap, -split) + + max_score = sum(max_heap) + min_score = -sum(min_heap) + return max_score - min_score +``` + +```java +public class Solution { + public long putMarbles(int[] weights, int k) { + if (k == 1) return 0L; + + PriorityQueue maxHeap = new PriorityQueue<>(); + PriorityQueue minHeap = new PriorityQueue<>(Collections.reverseOrder()); + + for (int i = 0; i < weights.length - 1; i++) { + int split = weights[i] + weights[i + 1]; + + if (maxHeap.size() < k - 1) maxHeap.offer(split); + else if (split > maxHeap.peek()) { + maxHeap.poll(); + maxHeap.offer(split); + } + + if (minHeap.size() < k - 1) minHeap.offer(split); + else if (split < minHeap.peek()) { + minHeap.poll(); + minHeap.offer(split); + } + } + + long maxScore = 0, minScore = 0; + for (int val : maxHeap) maxScore += val; + for (int val : minHeap) minScore += val; + + return maxScore - minScore; + } +} +``` + +```cpp +class Solution { +public: + long long putMarbles(vector& weights, int k) { + if (k == 1) return 0LL; + + priority_queue, greater> maxHeap; + priority_queue minHeap; + + for (int i = 0; i < weights.size() - 1; ++i) { + int split = weights[i] + weights[i + 1]; + + if ((int)maxHeap.size() < k - 1) maxHeap.push(split); + else if (split > maxHeap.top()) { + maxHeap.pop(); + maxHeap.push(split); + } + + if ((int)minHeap.size() < k - 1) minHeap.push(split); + else if (split < minHeap.top()) { + minHeap.pop(); + minHeap.push(split); + } + } + + long long maxScore = 0, minScore = 0; + while (!maxHeap.empty()) { + maxScore += maxHeap.top(); + maxHeap.pop(); + } + while (!minHeap.empty()) { + minScore += minHeap.top(); + minHeap.pop(); + } + + return maxScore - minScore; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} weights + * @param {number} k + * @return {number} + */ + putMarbles(weights, k) { + if (k === 1) return 0; + + const minHeap = new MinPriorityQueue(); + const maxHeap = new MaxPriorityQueue(); + + for (let i = 0; i < weights.length - 1; i++) { + const sum = weights[i] + weights[i + 1]; + + minHeap.enqueue(sum); + if (minHeap.size() > k - 1) minHeap.dequeue(); + + maxHeap.enqueue(sum); + if (maxHeap.size() > k - 1) maxHeap.dequeue(); + } + + let maxScore = 0, minScore = 0; + while (!minHeap.isEmpty()) maxScore += minHeap.dequeue(); + while (!maxHeap.isEmpty()) minScore += maxHeap.dequeue(); + + return maxScore - minScore; + } +} +``` + +```csharp +public class Solution { + public long PutMarbles(int[] weights, int k) { + if (k == 1) return 0L; + + var maxHeap = new PriorityQueue(); + var minHeap = new PriorityQueue( + Comparer.Create((a, b) => b.CompareTo(a)) + ); + + for (int i = 0; i < weights.Length - 1; i++) { + int split = weights[i] + weights[i + 1]; + + maxHeap.Enqueue(split, split); + if (maxHeap.Count > k - 1) maxHeap.Dequeue(); + + minHeap.Enqueue(split, split); + if (minHeap.Count > k - 1) minHeap.Dequeue(); + } + + long maxScore = 0, minScore = 0; + while (maxHeap.Count > 0) maxScore += maxHeap.Dequeue(); + while (minHeap.Count > 0) minScore += minHeap.Dequeue(); + + return maxScore - minScore; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log k)$ +* Space complexity: $O(k)$ + +> Where $n$ is the number of marbles, and $k$ is the number of bags. \ No newline at end of file diff --git a/articles/reconstruct-flight-path.md b/articles/reconstruct-flight-path.md index b76aff7a7..26ca58784 100644 --- a/articles/reconstruct-flight-path.md +++ b/articles/reconstruct-flight-path.md @@ -283,6 +283,46 @@ class Solution { } ``` +```swift +class Solution { + func findItinerary(_ tickets: [[String]]) -> [String] { + var adj = [String: [String]]() + for ticket in tickets { + adj[ticket[0], default: []].append(ticket[1]) + } + + for key in adj.keys { + adj[key]?.sort() + } + + var res = ["JFK"] + + func dfs(_ src: String) -> Bool { + if res.count == tickets.count + 1 { + return true + } + guard let destinations = adj[src] else { + return false + } + + var temp = destinations + for i in 0.. [String] { + var adj = [String: [String]]() + for ticket in tickets.sorted(by: { $0[1] > $1[1] }) { + adj[ticket[0], default: []].append(ticket[1]) + } + + var res = [String]() + + func dfs(_ src: String) { + while let destinations = adj[src], !destinations.isEmpty { + let dst = adj[src]!.removeLast() + dfs(dst) + } + res.append(src) + } + + dfs("JFK") + return res.reversed() + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -718,6 +782,31 @@ class Solution { } ``` +```swift +class Solution { + func findItinerary(_ tickets: [[String]]) -> [String] { + var adj = [String: [String]]() + for ticket in tickets.sorted(by: { $0[1] > $1[1] }) { + adj[ticket[0], default: []].append(ticket[1]) + } + + var stack = ["JFK"] + var res = [String]() + + while !stack.isEmpty { + let curr = stack.last! + if adj[curr] == nil || adj[curr]!.isEmpty { + res.append(stack.removeLast()) + } else { + stack.append(adj[curr]!.removeLast()) + } + } + + return res.reversed() + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/redundant-connection.md b/articles/redundant-connection.md index 81a67ff84..154493da7 100644 --- a/articles/redundant-connection.md +++ b/articles/redundant-connection.md @@ -247,6 +247,45 @@ class Solution { } ``` +```swift +class Solution { + func findRedundantConnection(_ edges: [[Int]]) -> [Int] { + let n = edges.count + var adj = Array(repeating: [Int](), count: n + 1) + + func dfs(_ node: Int, _ par: Int, _ visit: inout [Bool]) -> Bool { + if visit[node] { + return true + } + + visit[node] = true + for nei in adj[node] { + if nei == par { + continue + } + if dfs(nei, node, &visit) { + return true + } + } + return false + } + + for edge in edges { + let u = edge[0] + let v = edge[1] + adj[u].append(v) + adj[v].append(u) + var visit = Array(repeating: false, count: n + 1) + + if dfs(u, -1, &visit) { + return [u, v] + } + } + return [] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -606,6 +645,62 @@ class Solution { } ``` +```swift +class Solution { + func findRedundantConnection(_ edges: [[Int]]) -> [Int] { + let n = edges.count + var adj = Array(repeating: [Int](), count: n + 1) + + for edge in edges { + let u = edge[0] + let v = edge[1] + adj[u].append(v) + adj[v].append(u) + } + + var visit = Array(repeating: false, count: n + 1) + var cycle = Set() + var cycleStart = -1 + + func dfs(_ node: Int, _ par: Int) -> Bool { + if visit[node] { + cycleStart = node + return true + } + + visit[node] = true + for nei in adj[node] { + if nei == par { + continue + } + if dfs(nei, node) { + if cycleStart != -1 { + cycle.insert(node) + } + if node == cycleStart { + cycleStart = -1 + } + return true + } + } + return false + } + + dfs(1, -1) + + for edge in edges.reversed() { + let u = edge[0] + let v = edge[1] + if cycle.contains(u) && cycle.contains(v) { + return [u, v] + } + } + + return [] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -895,6 +990,52 @@ class Solution { } ``` +```swift +class Solution { + func findRedundantConnection(_ edges: [[Int]]) -> [Int] { + let n = edges.count + var indegree = Array(repeating: 0, count: n + 1) + var adj = Array(repeating: [Int](), count: n + 1) + + for edge in edges { + let u = edge[0] + let v = edge[1] + adj[u].append(v) + adj[v].append(u) + indegree[u] += 1 + indegree[v] += 1 + } + + var queue = Deque() + for i in 1...n { + if indegree[i] == 1 { + queue.append(i) + } + } + + while !queue.isEmpty { + let node = queue.popFirst()! + indegree[node] -= 1 + for nei in adj[node] { + indegree[nei] -= 1 + if indegree[nei] == 1 { + queue.append(nei) + } + } + } + + for edge in edges.reversed() { + let u = edge[0] + let v = edge[1] + if indegree[u] == 2 && indegree[v] > 0 { + return [u, v] + } + } + return [] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1212,6 +1353,50 @@ class Solution { } ``` +```swift +class Solution { + func findRedundantConnection(_ edges: [[Int]]) -> [Int] { + var par = Array(0...edges.count) + var rank = Array(repeating: 1, count: edges.count + 1) + + func find(_ n: Int) -> Int { + var p = par[n] + while p != par[p] { + par[p] = par[par[p]] + p = par[p] + } + return p + } + + func union(_ n1: Int, _ n2: Int) -> Bool { + let p1 = find(n1) + let p2 = find(n2) + + if p1 == p2 { + return false + } + if rank[p1] > rank[p2] { + par[p2] = p1 + rank[p1] += rank[p2] + } else { + par[p1] = p2 + rank[p2] += rank[p1] + } + return true + } + + for edge in edges { + let n1 = edge[0] + let n2 = edge[1] + if !union(n1, n2) { + return [n1, n2] + } + } + return [] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/regular-expression-matching.md b/articles/regular-expression-matching.md index 31b2a26a4..fd4bfda86 100644 --- a/articles/regular-expression-matching.md +++ b/articles/regular-expression-matching.md @@ -184,6 +184,35 @@ class Solution { } ``` +```swift +class Solution { + func isMatch(_ s: String, _ p: String) -> Bool { + let sArr = Array(s), pArr = Array(p) + let m = sArr.count, n = pArr.count + + func dfs(_ i: Int, _ j: Int) -> Bool { + if j == n { + return i == m + } + + let match = i < m && (sArr[i] == pArr[j] || pArr[j] == ".") + + if j + 1 < n && pArr[j + 1] == "*" { + return dfs(i, j + 2) || (match && dfs(i + 1, j)) + } + + if match { + return dfs(i + 1, j + 1) + } + + return false + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -432,6 +461,42 @@ class Solution { } ``` +```swift +class Solution { + func isMatch(_ s: String, _ p: String) -> Bool { + let sArr = Array(s), pArr = Array(p) + let m = sArr.count, n = pArr.count + var cache = [[Bool?]](repeating: [Bool?](repeating: nil, count: n + 1), count: m + 1) + + func dfs(_ i: Int, _ j: Int) -> Bool { + if j == n { + return i == m + } + if let cached = cache[i][j] { + return cached + } + + let match = i < m && (sArr[i] == pArr[j] || pArr[j] == ".") + + if j + 1 < n && pArr[j + 1] == "*" { + cache[i][j] = dfs(i, j + 2) || (match && dfs(i + 1, j)) + return cache[i][j]! + } + + if match { + cache[i][j] = dfs(i + 1, j + 1) + return cache[i][j]! + } + + cache[i][j] = false + return false + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -635,6 +700,34 @@ class Solution { } ``` +```swift +class Solution { + func isMatch(_ s: String, _ p: String) -> Bool { + let sArr = Array(s), pArr = Array(p) + let m = sArr.count, n = pArr.count + var dp = Array(repeating: Array(repeating: false, count: n + 1), count: m + 1) + dp[m][n] = true + + for i in stride(from: m, through: 0, by: -1) { + for j in stride(from: n - 1, through: 0, by: -1) { + let match = i < m && (sArr[i] == pArr[j] || pArr[j] == ".") + + if j + 1 < n && pArr[j + 1] == "*" { + dp[i][j] = dp[i][j + 2] + if match { + dp[i][j] = dp[i][j] || dp[i + 1][j] + } + } else if match { + dp[i][j] = dp[i + 1][j + 1] + } + } + } + + return dp[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -862,6 +955,38 @@ class Solution { } ``` +```swift +class Solution { + func isMatch(_ s: String, _ p: String) -> Bool { + let sArr = Array(s), pArr = Array(p) + var dp = Array(repeating: false, count: pArr.count + 1) + dp[pArr.count] = true + + for i in stride(from: sArr.count, through: 0, by: -1) { + var nextDp = Array(repeating: false, count: pArr.count + 1) + nextDp[pArr.count] = (i == sArr.count) + + for j in stride(from: pArr.count - 1, through: 0, by: -1) { + let match = i < sArr.count && (sArr[i] == pArr[j] || pArr[j] == ".") + + if j + 1 < pArr.count && pArr[j + 1] == "*" { + nextDp[j] = nextDp[j + 2] + if match { + nextDp[j] = nextDp[j] || dp[j] + } + } else if match { + nextDp[j] = dp[j + 1] + } + } + + dp = nextDp + } + + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1096,6 +1221,39 @@ class Solution { } ``` +```swift +class Solution { + func isMatch(_ s: String, _ p: String) -> Bool { + let sArr = Array(s) + let pArr = Array(p) + var dp = [Bool](repeating: false, count: pArr.count + 1) + dp[pArr.count] = true + + for i in stride(from: sArr.count, through: 0, by: -1) { + var dp1 = dp[pArr.count] + dp[pArr.count] = (i == sArr.count) + + for j in stride(from: pArr.count - 1, through: 0, by: -1) { + let match = i < sArr.count && (sArr[i] == pArr[j] || pArr[j] == ".") + var res = false + if j + 1 < pArr.count && pArr[j + 1] == "*" { + res = dp[j + 2] + if match { + res = res || dp[j] + } + } else if match { + res = dp1 + } + dp1 = dp[j] + dp[j] = res + } + } + + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity 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 diff --git a/articles/remove-duplicates-from-sorted-array.md b/articles/remove-duplicates-from-sorted-array.md index 57bb96cdc..7629a2ff3 100644 --- a/articles/remove-duplicates-from-sorted-array.md +++ b/articles/remove-duplicates-from-sorted-array.md @@ -56,6 +56,16 @@ class Solution { } ``` +```csharp +public class Solution { + public int RemoveDuplicates(int[] nums) { + int[] unique = nums.Distinct().OrderBy(x => x).ToArray(); + Array.Copy(unique, nums, unique.Length); + return unique.Length; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -135,6 +145,25 @@ class Solution { } ``` +```csharp +public class Solution { + public int RemoveDuplicates(int[] nums) { + int n = nums.Length; + int l = 0, r = 0; + + while (r < n) { + nums[l] = nums[r]; + while (r < n && nums[r] == nums[l]) { + r++; + } + l++; + } + + return l; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -206,6 +235,22 @@ class Solution { } ``` +```csharp +public class Solution { + public int RemoveDuplicates(int[] nums) { + int l = 1; + for (int r = 1; r < nums.Length; r++) { + if (nums[r] != nums[r - 1]) { + nums[l] = nums[r]; + l++; + } + } + + return l; + } +} +``` + ::tabs-end ### Time & Space Complexity 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/remove-element.md b/articles/remove-element.md index 1c3d722e4..14d2c78b4 100644 --- a/articles/remove-element.md +++ b/articles/remove-element.md @@ -72,6 +72,25 @@ class Solution { } ``` +```csharp +public class Solution { + public int RemoveElement(int[] nums, int val) { + List tmp = new List(); + foreach (int num in nums) { + if (num != val) { + tmp.Add(num); + } + } + + for (int i = 0; i < tmp.Count; i++) { + nums[i] = tmp[i]; + } + + return tmp.Count; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -144,6 +163,20 @@ class Solution { } ``` +```csharp +public class Solution { + public int RemoveElement(int[] nums, int val) { + int k = 0; + for (int i = 0; i < nums.Length; i++) { + if (nums[i] != val) { + nums[k++] = nums[i]; + } + } + return k; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -225,6 +258,22 @@ class Solution { } ``` +```csharp +public class Solution { + public int RemoveElement(int[] nums, int val) { + int i = 0, n = nums.Length; + while (i < n) { + if (nums[i] == val) { + nums[i] = nums[--n]; + } else { + i++; + } + } + return n; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/remove-node-from-end-of-linked-list.md b/articles/remove-node-from-end-of-linked-list.md index 141817504..ee936f416 100644 --- a/articles/remove-node-from-end-of-linked-list.md +++ b/articles/remove-node-from-end-of-linked-list.md @@ -216,6 +216,38 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? { + var nodes: [ListNode] = [] + var cur = head + + while cur != nil { + nodes.append(cur!) + cur = cur?.next + } + + let removeIndex = nodes.count - n + if removeIndex == 0 { + return head?.next + } + + nodes[removeIndex - 1].next = nodes[removeIndex].next + return head + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -490,6 +522,44 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? { + var N = 0 + var cur = head + while cur != nil { + N += 1 + cur = cur?.next + } + + let removeIndex = N - n + if removeIndex == 0 { + return head?.next + } + + cur = head + for i in 0..<(N - 1) { + if (i + 1) == removeIndex { + cur?.next = cur?.next?.next + break + } + cur = cur?.next + } + return head + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -723,12 +793,44 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func rec(_ head: ListNode?, _ n: inout Int) -> ListNode? { + if head == nil { + return nil + } + + head?.next = rec(head?.next, &n) + n -= 1 + if n == 0 { + return head?.next + } + return head + } + + func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? { + var n = n + return rec(head, &n) + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(N)$ -* Space complexity: $O(N)$ +* Space complexity: $O(N)$ for recursion stack. --- @@ -964,6 +1066,40 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? { + let dummy = ListNode(0, head) + var left: ListNode? = dummy + var right: ListNode? = head + var n = n + + while n > 0 { + right = right?.next + n -= 1 + } + + while right != nil { + left = left?.next + right = right?.next + } + + left?.next = left?.next?.next + return dummy.next + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/reorder-linked-list.md b/articles/reorder-linked-list.md index 399860a22..75e0ef82c 100644 --- a/articles/reorder-linked-list.md +++ b/articles/reorder-linked-list.md @@ -260,6 +260,47 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func reorderList(_ head: ListNode?) { + if head == nil { + return + } + + var nodes: [ListNode] = [] + var cur = head + + while cur != nil { + nodes.append(cur!) + cur = cur?.next + } + + var i = 0, j = nodes.count - 1 + while i < j { + nodes[i].next = nodes[j] + i += 1 + if i >= j { + break + } + nodes[j].next = nodes[i] + j -= 1 + } + + nodes[i].next = nil + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -286,10 +327,11 @@ class Solution: def rec(root: ListNode, cur: ListNode) -> ListNode: if not cur: return root - root = rec(root, cur.next) + root = rec(root, cur.next) if not root: return None + tmp = None if root == cur or root.next == cur: cur.next = None @@ -297,8 +339,9 @@ class Solution: tmp = root.next root.next = cur cur.next = tmp + return tmp - + head = rec(head, head.next) ``` @@ -323,10 +366,12 @@ public class Solution { if (cur == null) { return root; } + root = rec(root, cur.next); if (root == null) { return null; } + ListNode tmp = null; if (root == cur || root.next == cur) { cur.next = null; @@ -335,6 +380,7 @@ public class Solution { root.next = cur; cur.next = tmp; } + return tmp; } } @@ -363,10 +409,12 @@ private: if (cur == nullptr) { return root; } + root = rec(root, cur->next); if (root == nullptr) { return nullptr; } + ListNode* tmp = nullptr; if (root == cur || root->next == cur) { cur->next = nullptr; @@ -375,6 +423,7 @@ private: root->next = cur; cur->next = tmp; } + return tmp; } }; @@ -409,10 +458,12 @@ class Solution { if (cur === null) { return root; } + root = this.rec(root, cur.next); if (root === null) { return null; } + let tmp = null; if (root === cur || root.next === cur) { cur.next = null; @@ -421,6 +472,7 @@ class Solution { root.next = cur; cur.next = tmp; } + return tmp; } } @@ -448,10 +500,12 @@ public class Solution { if (cur == null) { return root; } + root = Rec(root, cur.next); if (root == null) { return null; } + ListNode tmp = null; if (root == cur || root.next == cur) { cur.next = null; @@ -460,6 +514,7 @@ public class Solution { root.next = cur; cur.next = tmp; } + return tmp; } } @@ -483,11 +538,12 @@ func reorderList(head *ListNode) { if cur == nil { return root } - root = rec(root, cur.Next) + root = rec(root, cur.Next) if root == nil { return nil } + var tmp *ListNode if root == cur || root.Next == cur { cur.Next = nil @@ -496,6 +552,7 @@ func reorderList(head *ListNode) { root.Next = cur cur.Next = tmp } + return tmp } @@ -521,11 +578,12 @@ class Solution { if (cur == null) { return root } - var updatedRoot = rec(root, cur.next) + var updatedRoot = rec(root, cur.next) if (updatedRoot == null) { return null } + var tmp: ListNode? = null if (updatedRoot == cur || updatedRoot?.next == cur) { cur.next = null @@ -534,6 +592,7 @@ class Solution { updatedRoot.next = cur cur.next = tmp } + return tmp } @@ -542,6 +601,46 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func reorderList(_ head: ListNode?) { + func rec(_ root: ListNode?, _ cur: ListNode?) -> ListNode? { + if cur == nil { + return root + } + + var root = rec(root, cur?.next) + if root == nil { + return nil + } + + var tmp: ListNode? = nil + if root === cur || root?.next === cur { + cur?.next = nil + } else { + tmp = root?.next + root?.next = cur + cur?.next = tmp + } + + return tmp + } + + rec(head, head?.next) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -852,6 +951,51 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func reorderList(_ head: ListNode?) { + var slow = head, fast = head?.next + while fast != nil && fast?.next != nil { + slow = slow?.next + fast = fast?.next?.next + } + + var second = slow?.next + var prev: ListNode? = nil + slow?.next = nil + + while second != nil { + let tmp = second?.next + second?.next = prev + prev = second + second = tmp + } + + var first = head + second = prev + + while second != nil { + let tmp1 = first?.next + let tmp2 = second?.next + first?.next = second + second?.next = tmp1 + first = tmp1 + second = tmp2 + } + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/reorganize-string.md b/articles/reorganize-string.md index 57d672327..868c78dca 100644 --- a/articles/reorganize-string.md +++ b/articles/reorganize-string.md @@ -183,6 +183,42 @@ class Solution { } ``` +```csharp +public class Solution { + public string ReorganizeString(string s) { + int[] freq = new int[26]; + foreach (char c in s) { + freq[c - 'a']++; + } + + int maxFreq = freq.Max(); + if (maxFreq > (s.Length + 1) / 2) { + return ""; + } + + List res = new List(); + while (res.Count < s.Length) { + int maxIdx = Array.IndexOf(freq, freq.Max()); + char ch = (char)(maxIdx + 'a'); + res.Add(ch); + freq[maxIdx]--; + + if (freq[maxIdx] == 0) continue; + + int tmp = freq[maxIdx]; + freq[maxIdx] = int.MinValue; + int nextMaxIdx = Array.IndexOf(freq, freq.Max()); + char nextCh = (char)(nextMaxIdx + 'a'); + res.Add(nextCh); + freq[maxIdx] = tmp; + freq[nextMaxIdx]--; + } + + return new string(res.ToArray()); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -352,6 +388,45 @@ class Solution { } ``` +```csharp +public class Solution { + public string ReorganizeString(string s) { + Dictionary count = new(); + foreach (char c in s) { + if (!count.ContainsKey(c)) count[c] = 0; + count[c]++; + } + + PriorityQueue maxHeap = new(); + foreach (var kvp in count) { + maxHeap.Enqueue(new int[] { kvp.Value, kvp.Key }, -kvp.Value); + } + + string res = ""; + int[] prev = null; + + while (maxHeap.Count > 0 || prev != null) { + if (prev != null && maxHeap.Count == 0) return ""; + + int[] curr = maxHeap.Dequeue(); + res += (char)curr[1]; + curr[0]--; + + if (prev != null) { + maxHeap.Enqueue(prev, -prev[0]); + prev = null; + } + + if (curr[0] > 0) { + prev = curr; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -536,6 +611,48 @@ class Solution { } ``` +```csharp +public class Solution { + public string ReorganizeString(string s) { + int[] freq = new int[26]; + foreach (char c in s) { + freq[c - 'a']++; + } + + int maxIdx = 0; + for (int i = 1; i < 26; i++) { + if (freq[i] > freq[maxIdx]) { + maxIdx = i; + } + } + + int maxFreq = freq[maxIdx]; + if (maxFreq > (s.Length + 1) / 2) return ""; + + char[] res = new char[s.Length]; + int idx = 0; + char maxChar = (char)(maxIdx + 'a'); + + while (freq[maxIdx] > 0) { + res[idx] = maxChar; + idx += 2; + freq[maxIdx]--; + } + + for (int i = 0; i < 26; i++) { + while (freq[i] > 0) { + if (idx >= s.Length) idx = 1; + res[idx] = (char)(i + 'a'); + idx += 2; + freq[i]--; + } + } + + return new string(res); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/reverse-a-linked-list.md b/articles/reverse-a-linked-list.md index 98f5ee98d..3a205a543 100644 --- a/articles/reverse-a-linked-list.md +++ b/articles/reverse-a-linked-list.md @@ -200,6 +200,35 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func reverseList(_ head: ListNode?) -> ListNode? { + if head == nil { + return nil + } + + var newHead = head + if head?.next != nil { + newHead = reverseList(head?.next) + head?.next?.next = head + } + head?.next = nil + + return newHead + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -397,6 +426,33 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func reverseList(_ head: ListNode?) -> ListNode? { + var prev: ListNode? = nil + var curr = head + + while curr != nil { + let temp = curr?.next + curr?.next = prev + prev = curr + curr = temp + } + return prev + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/reverse-bits.md b/articles/reverse-bits.md index d5267bf19..84cbe88ce 100644 --- a/articles/reverse-bits.md +++ b/articles/reverse-bits.md @@ -162,6 +162,30 @@ class Solution { } ``` +```swift +class Solution { + func reverseBits(_ n: Int) -> Int { + var binary = "" + for i in 0..<32 { + if (n & (1 << i)) != 0 { + binary += "1" + } else { + binary += "0" + } + } + + var res = 0 + for (i, bit) in binary.reversed().enumerated() { + if bit == "1" { + res |= (1 << i) + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -266,6 +290,20 @@ class Solution { } ``` +```swift +class Solution { + func reverseBits(_ n: Int) -> Int { + var res = 0 + var num = n + for i in 0..<32 { + let bit = (num >> i) & 1 + res |= (bit << (31 - i)) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -378,6 +416,20 @@ class Solution { } ``` +```swift +class Solution { + func reverseBits(_ n: Int) -> Int { + var res = n + res = (res >> 16) | (res << 16) & 0xFFFFFFFF + res = ((res & 0xff00ff00) >> 8) | ((res & 0x00ff00ff) << 8) + res = ((res & 0xf0f0f0f0) >> 4) | ((res & 0x0f0f0f0f) << 4) + res = ((res & 0xcccccccc) >> 2) | ((res & 0x33333333) << 2) + res = ((res & 0xaaaaaaaa) >> 1) | ((res & 0x55555555) << 1) + return res & 0xFFFFFFFF + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/reverse-integer.md b/articles/reverse-integer.md index f6d060a33..c388a821f 100644 --- a/articles/reverse-integer.md +++ b/articles/reverse-integer.md @@ -147,6 +147,25 @@ class Solution { } ``` +```swift +class Solution { + func reverse(_ x: Int) -> Int { + let org = x + var x = abs(x) + var res = Int(String(String(x).reversed()))! + + if org < 0 { + res *= -1 + } + if res < Int32.min || res > Int32.max { + return 0 + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -310,6 +329,28 @@ class Solution { } ``` +```swift +class Solution { + func reverse(_ x: Int) -> Int { + func rec(_ n: Int, _ rev: Int) -> Int { + if n == 0 { + return rev + } + return rec(n / 10, rev * 10 + n % 10) + } + + let sign = x < 0 ? -1 : 1 + let reversedNum = rec(abs(x), 0) * sign + + if reversedNum < Int32.min || reversedNum > Int32.max { + return 0 + } + + return reversedNum + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -489,6 +530,33 @@ class Solution { } ``` +```swift +class Solution { + func reverse(_ x: Int) -> Int { + let MIN = Int32.min + let MAX = Int32.max + + var res = 0 + var num = x + + while num != 0 { + let digit = num % 10 + num /= 10 + + if res > MAX / 10 || (res == MAX / 10 && digit > MAX % 10) { + return 0 + } + if res < MIN / 10 || (res == MIN / 10 && digit < MIN % 10) { + return 0 + } + res = res * 10 + digit + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/reverse-linked-list-ii.md b/articles/reverse-linked-list-ii.md index 5a3d69df7..98f00e838 100644 --- a/articles/reverse-linked-list-ii.md +++ b/articles/reverse-linked-list-ii.md @@ -194,6 +194,57 @@ class Solution { } ``` +```csharp +/** + * Definition for singly-linked list. + * public class ListNode { + * public int val; + * public ListNode next; + * public ListNode(int val=0, ListNode next=null) { + * this.val = val; + * this.next = next; + * } + * } + */ +public class Solution { + public ListNode ReverseBetween(ListNode head, int left, int right) { + ListNode dummy = new ListNode(0, head); + ListNode prev = dummy; + + for (int i = 0; i < left - 1; i++) { + prev = prev.next; + } + + ListNode sublistHead = prev.next; + ListNode sublistTail = sublistHead; + for (int i = 0; i < right - left; i++) { + sublistTail = sublistTail.next; + } + + ListNode nextNode = sublistTail.next; + sublistTail.next = null; + + ListNode reversedSublist = ReverseList(sublistHead); + prev.next = reversedSublist; + sublistHead.next = nextNode; + + return dummy.next; + } + + private ListNode ReverseList(ListNode head) { + if (head == null) return null; + + ListNode newHead = head; + if (head.next != null) { + newHead = ReverseList(head.next); + head.next.next = head; + } + head.next = null; + return newHead; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -334,6 +385,42 @@ class Solution { } ``` +```csharp +/** + * Definition for singly-linked list. + * public class ListNode { + * public int val; + * public ListNode next; + * public ListNode(int val=0, ListNode next=null) { + * this.val = val; + * this.next = next; + * } + * } + */ +public class Solution { + private ListNode successor = null; + + private ListNode ReverseList(ListNode node, int n) { + if (n == 1) { + successor = node.next; + return node; + } + ListNode newHead = ReverseList(node.next, n - 1); + node.next.next = node; + node.next = successor; + return newHead; + } + + public ListNode ReverseBetween(ListNode head, int left, int right) { + if (left == 1) { + return ReverseList(head, right); + } + head.next = ReverseBetween(head.next, left - 1, right - 1); + return head; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -540,6 +627,58 @@ class Solution { } ``` +```csharp +/** + * Definition for singly-linked list. + * public class ListNode { + * public int val; + * public ListNode next; + * public ListNode(int val=0, ListNode next=null) { + * this.val = val; + * this.next = next; + * } + * } + */ +public class Solution { + public ListNode ReverseBetween(ListNode head, int left, int right) { + ListNode dummy = new ListNode(0); + dummy.next = head; + ListNode prev = dummy; + + for (int i = 0; i < left - 1; i++) { + prev = prev.next; + } + + ListNode sublistHead = prev.next; + ListNode sublistTail = sublistHead; + for (int i = 0; i < right - left; i++) { + sublistTail = sublistTail.next; + } + + ListNode nextNode = sublistTail.next; + sublistTail.next = null; + + ListNode reversedSublist = ReverseList(sublistHead); + prev.next = reversedSublist; + + sublistHead.next = nextNode; + return dummy.next; + } + + private ListNode ReverseList(ListNode head) { + ListNode prev = null; + ListNode curr = head; + while (curr != null) { + ListNode temp = curr.next; + curr.next = prev; + prev = curr; + curr = temp; + } + return prev; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -699,6 +838,44 @@ class Solution { } ``` +```csharp +/** + * Definition for singly-linked list. + * public class ListNode { + * public int val; + * public ListNode next; + * public ListNode(int val=0, ListNode next=null) { + * this.val = val; + * this.next = next; + * } + * } + */ +public class Solution { + public ListNode ReverseBetween(ListNode head, int left, int right) { + ListNode dummy = new ListNode(0, head); + ListNode leftPrev = dummy, curr = head; + + for (int i = 0; i < left - 1; i++) { + leftPrev = curr; + curr = curr.next; + } + + ListNode prev = null; + for (int i = 0; i < right - left + 1; i++) { + ListNode tmpNext = curr.next; + curr.next = prev; + prev = curr; + curr = tmpNext; + } + + leftPrev.next.next = curr; + leftPrev.next = prev; + + return dummy.next; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/reverse-nodes-in-k-group.md b/articles/reverse-nodes-in-k-group.md index ad54de13e..f5836142d 100644 --- a/articles/reverse-nodes-in-k-group.md +++ b/articles/reverse-nodes-in-k-group.md @@ -251,6 +251,47 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func reverseKGroup(_ head: ListNode?, _ k: Int) -> ListNode? { + var cur = head + var group = 0 + + while cur != nil && group < k { + cur = cur!.next + group += 1 + } + + if group == k { + cur = reverseKGroup(cur, k) + + var tempHead = head + while group > 0 { + let tmp = tempHead!.next + tempHead!.next = cur + cur = tempHead + tempHead = tmp + group -= 1 + } + + return cur + } + + return head + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -603,6 +644,57 @@ class Solution { } ``` +```swift +/** + * Definition for singly-linked list. + * public class ListNode { + * public var val: Int + * public var next: ListNode? + * public init() { self.val = 0; self.next = nil; } + * public init(_ val: Int) { self.val = val; self.next = nil; } + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } + * } + */ +class Solution { + func reverseKGroup(_ head: ListNode?, _ k: Int) -> ListNode? { + let dummy = ListNode(0, head) + var groupPrev: ListNode? = dummy + + while true { + guard let kth = getKth(groupPrev, k) else { + break + } + let groupNext = kth.next + + var prev: ListNode? = kth.next + var curr = groupPrev?.next + + while curr !== groupNext { + let tmp = curr?.next + curr?.next = prev + prev = curr + curr = tmp + } + + let tmp = groupPrev?.next + groupPrev?.next = kth + groupPrev = tmp + } + return dummy.next + } + + private func getKth(_ curr: ListNode?, _ k: Int) -> ListNode? { + var curr = curr + var k = k + while curr != nil && k > 0 { + curr = curr?.next + k -= 1 + } + return curr + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/reverse-string.md b/articles/reverse-string.md index ac60401c5..6c671dd5f 100644 --- a/articles/reverse-string.md +++ b/articles/reverse-string.md @@ -62,6 +62,23 @@ class Solution { } ``` +```csharp +public class Solution { + public void ReverseString(char[] s) { + char[] tmp = new char[s.Length]; + int n = s.Length; + + for (int i = 0; i < n; i++) { + tmp[i] = s[n - 1 - i]; + } + + for (int i = 0; i < n; i++) { + s[i] = tmp[i]; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -141,6 +158,23 @@ class Solution { } ``` +```csharp +public class Solution { + public void ReverseString(char[] s) { + Reverse(s, 0, s.Length - 1); + } + + private void Reverse(char[] s, int left, int right) { + if (left < right) { + Reverse(s, left + 1, right - 1); + char temp = s[left]; + s[left] = s[right]; + s[right] = temp; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -220,6 +254,22 @@ class Solution { } ``` +```csharp +public class Solution { + public void ReverseString(char[] s) { + Stack stack = new Stack(); + + foreach (char c in s) { + stack.Push(c); + } + + for (int i = 0; i < s.Length; i++) { + s[i] = stack.Pop(); + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -279,6 +329,14 @@ class Solution { } ``` +```csharp +public class Solution { + public void ReverseString(char[] s) { + Array.Reverse(s); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -349,6 +407,21 @@ class Solution { } ``` +```csharp +public class Solution { + public void ReverseString(char[] s) { + int l = 0, r = s.Length - 1; + while (l < r) { + char temp = s[l]; + s[l] = s[r]; + s[r] = temp; + l++; + r--; + } + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/rotate-array.md b/articles/rotate-array.md index 72dfcb037..790679e20 100644 --- a/articles/rotate-array.md +++ b/articles/rotate-array.md @@ -75,6 +75,24 @@ class Solution { } ``` +```csharp +public class Solution { + public void Rotate(int[] nums, int k) { + int n = nums.Length; + k %= n; + + while (k > 0) { + int tmp = nums[n - 1]; + for (int i = n - 1; i > 0; i--) { + nums[i] = nums[i - 1]; + } + nums[0] = tmp; + k--; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -153,6 +171,23 @@ class Solution { } ``` +```csharp +public class Solution { + public void Rotate(int[] nums, int k) { + int n = nums.Length; + int[] tmp = new int[n]; + + for (int i = 0; i < n; i++) { + tmp[(i + k) % n] = nums[i]; + } + + for (int i = 0; i < n; i++) { + nums[i] = tmp[i]; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -265,6 +300,30 @@ class Solution { } ``` +```csharp +public class Solution { + public void Rotate(int[] nums, int k) { + int n = nums.Length; + k %= n; + int count = 0; + + for (int start = 0; count < n; start++) { + int current = start; + int prev = nums[start]; + + do { + int nextIdx = (current + k) % n; + int temp = nums[nextIdx]; + nums[nextIdx] = prev; + prev = temp; + current = nextIdx; + count++; + } while (start != current); + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -369,6 +428,29 @@ class Solution { } ``` +```csharp +public class Solution { + public void Rotate(int[] nums, int k) { + int n = nums.Length; + k %= n; + + Reverse(nums, 0, n - 1); + Reverse(nums, 0, k - 1); + Reverse(nums, k, n - 1); + } + + private void Reverse(int[] nums, int left, int right) { + while (left < right) { + int temp = nums[left]; + nums[left] = nums[right]; + nums[right] = temp; + left++; + right--; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -425,6 +507,20 @@ class Solution { } ``` +```csharp +public class Solution { + public void Rotate(int[] nums, int k) { + int n = nums.Length; + k %= n; + + int[] rotated = new int[n]; + Array.Copy(nums, n - k, rotated, 0, k); + Array.Copy(nums, 0, rotated, k, n - k); + Array.Copy(rotated, nums, n); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/rotate-matrix.md b/articles/rotate-matrix.md index 2f050d984..c7ea787f1 100644 --- a/articles/rotate-matrix.md +++ b/articles/rotate-matrix.md @@ -145,6 +145,27 @@ class Solution { } ``` +```swift +class Solution { + func rotate(_ matrix: inout [[Int]]) { + let n = matrix.count + var rotated = Array(repeating: Array(repeating: 0, count: n), count: n) + + for i in 0.. Int { + var grid = grid + var queue = Deque<(Int, Int)>() + var fresh = 0 + var time = 0 + + let ROWS = grid.count + let COLS = grid[0].count + + for r in 0.. 0 && !queue.isEmpty { + let length = queue.count + for _ in 0..= 0 && row < ROWS && col >= 0 && col < COLS && grid[row][col] == 1 { + grid[row][col] = 2 + queue.append((row, col)) + fresh -= 1 + } + } + } + time += 1 + } + + return fresh == 0 ? time : -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -704,6 +752,64 @@ class Solution { } ``` +```swift +class Solution { + func orangesRotting(_ grid: [[Int]]) -> Int { + var grid = grid + let ROWS = grid.count + let COLS = grid[0].count + var fresh = 0 + var time = 0 + + for r in 0.. 0 { + var flag = false + for r in 0..= 0 && row < ROWS && col >= 0 && + col < COLS && grid[row][col] == 1) { + grid[row][col] = 3 + fresh -= 1 + flag = true + } + } + } + } + } + + if !flag { + return -1 + } + + for r in 0.. Bool { + if p == nil && q == nil { + return true + } + if let p = p, let q = q, p.val == q.val { + return isSameTree(p.left, q.left) && isSameTree(p.right, q.right) + } else { + return false + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -444,6 +474,45 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func isSameTree(_ p: TreeNode?, _ q: TreeNode?) -> Bool { + var stack: [(TreeNode?, TreeNode?)] = [(p, q)] + + while !stack.isEmpty { + let (node1, node2) = stack.removeLast() + + if node1 == nil && node2 == nil { + continue + } + if node1 == nil || node2 == nil || node1!.val != node2!.val { + return false + } + + stack.append((node1!.right, node2!.right)) + stack.append((node1!.left, node2!.left)) + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -742,6 +811,51 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func isSameTree(_ p: TreeNode?, _ q: TreeNode?) -> Bool { + var q1 = Deque() + var q2 = Deque() + q1.append(p) + q2.append(q) + + while !q1.isEmpty && !q2.isEmpty { + let nodeP = q1.removeFirst() + let nodeQ = q2.removeFirst() + + if nodeP == nil && nodeQ == nil { + continue + } + if nodeP == nil || nodeQ == nil || nodeP!.val != nodeQ!.val { + return false + } + + q1.append(nodeP!.left) + q1.append(nodeP!.right) + q2.append(nodeQ!.left) + q2.append(nodeQ!.right) + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity 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/search-2d-matrix.md b/articles/search-2d-matrix.md index 722cbe2b6..45181e5df 100644 --- a/articles/search-2d-matrix.md +++ b/articles/search-2d-matrix.md @@ -106,6 +106,21 @@ class Solution { } ``` +```swift +class Solution { + func searchMatrix(_ matrix: [[Int]], _ target: Int) -> Bool { + for r in 0.. Bool { + let m = matrix.count + let n = matrix[0].count + var r = 0, c = n - 1 + + while r < m && c >= 0 { + if matrix[r][c] > target { + c -= 1 + } else if matrix[r][c] < target { + r += 1 + } else { + return true + } + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -546,6 +582,44 @@ class Solution { } ``` +```swift +class Solution { + func searchMatrix(_ matrix: [[Int]], _ target: Int) -> Bool { + let ROWS = matrix.count + let COLS = matrix[0].count + + var top = 0, bot = ROWS - 1 + while top <= bot { + let row = (top + bot) / 2 + if target > matrix[row][COLS - 1] { + top = row + 1 + } else if target < matrix[row][0] { + bot = row - 1 + } else { + break + } + } + + if !(top <= bot) { + return false + } + let row = (top + bot) / 2 + var l = 0, r = COLS - 1 + while l <= r { + let m = (l + r) / 2 + if target > matrix[row][m] { + l = m + 1 + } else if target < matrix[row][m] { + r = m - 1 + } else { + return true + } + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -718,6 +792,31 @@ class Solution { } ``` +```swift +class Solution { + func searchMatrix(_ matrix: [[Int]], _ target: Int) -> Bool { + let ROWS = matrix.count + let COLS = matrix[0].count + + var l = 0, r = ROWS * COLS - 1 + while l <= r { + let m = l + (r - l) / 2 + let row = m / COLS + let col = m % COLS + + if target > matrix[row][col] { + l = m + 1 + } else if target < matrix[row][col] { + r = m - 1 + } else { + return true + } + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/search-for-word-ii.md b/articles/search-for-word-ii.md index d304ea983..519307f04 100644 --- a/articles/search-for-word-ii.md +++ b/articles/search-for-word-ii.md @@ -282,6 +282,53 @@ class Solution { } ``` +```swift +class Solution { + func findWords(_ board: [[Character]], _ words: [String]) -> [String] { + let ROWS = board.count + let COLS = board[0].count + var res: [String] = [] + var board = board + + func backtrack(_ r: Int, _ c: Int, _ i: Int, _ word: [Character]) -> Bool { + if i == word.count { + return true + } + if r < 0 || c < 0 || r >= ROWS || c >= COLS || board[r][c] != word[i] { + return false + } + + board[r][c] = "*" + let ret = backtrack(r + 1, c, i + 1, word) || + backtrack(r - 1, c, i + 1, word) || + backtrack(r, c + 1, i + 1, word) || + backtrack(r, c - 1, i + 1, word) + board[r][c] = word[i] + return ret + } + + for word in words { + var flag = false + let wordArray = Array(word) + for r in 0.. children; boolean isWord; @@ -743,6 +790,68 @@ class Solution { } ``` +```swift +class TrieNode { + var children: [Character: TrieNode] = [:] + var isWord: Bool = false + + func addWord(_ word: String) { + var current = self + for char in word { + if current.children[char] == nil { + current.children[char] = TrieNode() + } + current = current.children[char]! + } + current.isWord = true + } +} + +class Solution { + func findWords(_ board: [[Character]], _ words: [String]) -> [String] { + let root = TrieNode() + for word in words { + root.addWord(word) + } + + let ROWS = board.count + let COLS = board[0].count + var result = Set() + var visited = Set<[Int]>() + + func dfs(_ r: Int, _ c: Int, _ node: TrieNode, _ word: String) { + if r < 0 || c < 0 || r >= ROWS || c >= COLS || + visited.contains([r, c]) || node.children[board[r][c]] == nil { + return + } + + visited.insert([r, c]) + let nextNode = node.children[board[r][c]]! + let newWord = word + String(board[r][c]) + + if nextNode.isWord { + result.insert(newWord) + } + + dfs(r + 1, c, nextNode, newWord) + dfs(r - 1, c, nextNode, newWord) + dfs(r, c + 1, nextNode, newWord) + dfs(r, c - 1, nextNode, newWord) + + visited.remove([r, c]) + } + + for r in 0.. [String] { + let root = TrieNode() + for i in 0.. Int { + return Int(c.asciiValue! - Character("a").asciiValue!) + } + + func dfs(_ r: Int, _ c: Int, _ node: TrieNode) { + if r < 0 || c < 0 || r >= ROWS || c >= COLS || + boardCopy[r][c] == "*" || + node.children[getIndex(boardCopy[r][c])] == nil { + return + } + + let tmp = boardCopy[r][c] + boardCopy[r][c] = "*" + let prev = node + let nextNode = node.children[getIndex(tmp)]! + + if nextNode.idx != -1 { + res.append(words[nextNode.idx]) + nextNode.idx = -1 + nextNode.refs -= 1 + if nextNode.refs == 0 { + prev.children[getIndex(tmp)] = nil + boardCopy[r][c] = tmp + return + } + } + + dfs(r + 1, c, nextNode) + dfs(r - 1, c, nextNode) + dfs(r, c + 1, nextNode) + dfs(r, c - 1, nextNode) + + boardCopy[r][c] = tmp + } + + for r in 0.. Bool { + let ROWS = board.count + let COLS = board[0].count + var path = Set<[Int]>() + let wordArray = Array(word) + + func dfs(_ r: Int, _ c: Int, _ i: Int) -> Bool { + if i == wordArray.count { + return true + } + if (r < 0 || c < 0 || r >= ROWS || c >= COLS || + board[r][c] != wordArray[i] || path.contains([r, c])) { + return false + } + + path.insert([r, c]) + let res = dfs(r + 1, c, i + 1) || + dfs(r - 1, c, i + 1) || + dfs(r, c + 1, i + 1) || + dfs(r, c - 1, i + 1) + path.remove([r, c]) + return res + } + + for r in 0.. Bool { + let ROWS = board.count + let COLS = board[0].count + var visited = Array(repeating: Array(repeating: false, count: COLS), count: ROWS) + let wordArray = Array(word) + + func dfs(_ r: Int, _ c: Int, _ i: Int) -> Bool { + if i == wordArray.count { + return true + } + if (r < 0 || c < 0 || r >= ROWS || c >= COLS || + board[r][c] != wordArray[i] || visited[r][c]) { + return false + } + + visited[r][c] = true + let res = dfs(r + 1, c, i + 1) || + dfs(r - 1, c, i + 1) || + dfs(r, c + 1, i + 1) || + dfs(r, c - 1, i + 1) + visited[r][c] = false + return res + } + + for r in 0.. Bool { + let ROWS = board.count + let COLS = board[0].count + let wordArray = Array(word) + var board = board + + func dfs(_ r: Int, _ c: Int, _ i: Int) -> Bool { + if i == wordArray.count { + return true + } + if (r < 0 || c < 0 || r >= ROWS || c >= COLS || + board[r][c] != wordArray[i] || board[r][c] == "#") { + return false + } + + let temp = board[r][c] + board[r][c] = "#" + let res = dfs(r + 1, c, i + 1) || + dfs(r - 1, c, i + 1) || + dfs(r, c + 1, i + 1) || + dfs(r, c - 1, i + 1) + board[r][c] = temp + return res + } + + for r in 0.. nums[m]) { + if (nums[m] < target && target <= nums[r]) { + l = m + 1; + } else { + r = m - 1; + } + } else { + l++; + } + } + return false; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/search-insert-position.md b/articles/search-insert-position.md index 225a7e0a1..7e6cbd60e 100644 --- a/articles/search-insert-position.md +++ b/articles/search-insert-position.md @@ -56,6 +56,19 @@ class Solution { } ``` +```csharp +public class Solution { + public int SearchInsert(int[] nums, int target) { + for (int i = 0; i < nums.Length; i++) { + if (nums[i] >= target) { + return i; + } + } + return nums.Length; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -158,6 +171,30 @@ class Solution { } ``` +```csharp +public class Solution { + public int SearchInsert(int[] nums, int target) { + int res = nums.Length; + int l = 0, r = nums.Length - 1; + + while (l <= r) { + int mid = (l + r) / 2; + if (nums[mid] == target) { + return mid; + } + if (nums[mid] > target) { + res = mid; + r = mid - 1; + } else { + l = mid + 1; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -252,6 +289,28 @@ class Solution { } ``` +```csharp +public class Solution { + public int SearchInsert(int[] nums, int target) { + int l = 0, r = nums.Length - 1; + + while (l <= r) { + int mid = (l + r) / 2; + if (nums[mid] == target) { + return mid; + } + if (nums[mid] > target) { + r = mid - 1; + } else { + l = mid + 1; + } + } + + return l; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -335,6 +394,25 @@ class Solution { } ``` +```csharp +public class Solution { + public int SearchInsert(int[] nums, int target) { + int l = 0, r = nums.Length; + + while (l < r) { + int m = l + (r - l) / 2; + if (nums[m] >= target) { + r = m; + } else { + l = m + 1; + } + } + + return l; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -388,6 +466,15 @@ class Solution { } ``` +```csharp +public class Solution { + public int SearchInsert(int[] nums, int target) { + int idx = Array.BinarySearch(nums, target); + return idx >= 0 ? idx : ~idx; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/serialize-and-deserialize-binary-tree.md b/articles/serialize-and-deserialize-binary-tree.md index 01a3b0d41..ad965e002 100644 --- a/articles/serialize-and-deserialize-binary-tree.md +++ b/articles/serialize-and-deserialize-binary-tree.md @@ -401,6 +401,61 @@ class Codec { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init(_ val: Int) { + * self.val = val + * self.left = nil + * self.right = nil + * } + * } + */ + +class Codec { + + func serialize(_ root: TreeNode?) -> String { + var res = [String]() + + func dfs(_ node: TreeNode?) { + guard let node = node else { + res.append("N") + return + } + res.append("\(node.val)") + dfs(node.left) + dfs(node.right) + } + + dfs(root) + return res.joined(separator: ",") + } + + func deserialize(_ data: String) -> TreeNode? { + var vals = data.split(separator: ",").map { String($0) } + var i = 0 + + func dfs() -> TreeNode? { + if vals[i] == "N" { + i += 1 + return nil + } + let node = TreeNode(Int(vals[i])!) + i += 1 + node.left = dfs() + node.right = dfs() + return node + } + + return dfs() + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -863,6 +918,76 @@ class Codec { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init(_ val: Int) { + * self.val = val + * self.left = nil + * self.right = nil + * } + * } + */ + +class Codec { + + func serialize(_ root: TreeNode?) -> String { + guard let root = root else { + return "N" + } + + var res = [String]() + var queue: Deque = [root] + + while !queue.isEmpty { + let node = queue.removeFirst() + if let node = node { + res.append("\(node.val)") + queue.append(node.left) + queue.append(node.right) + } else { + res.append("N") + } + } + + return res.joined(separator: ",") + } + + func deserialize(_ data: String) -> TreeNode? { + let vals = data.split(separator: ",").map { String($0) } + guard vals[0] != "N" else { + return nil + } + + let root = TreeNode(Int(vals[0])!) + var queue: Deque = [root] + var index = 1 + + while !queue.isEmpty { + let node = queue.popFirst()! + + if vals[index] != "N" { + node.left = TreeNode(Int(vals[index])!) + queue.append(node.left!) + } + index += 1 + + if vals[index] != "N" { + node.right = TreeNode(Int(vals[index])!) + queue.append(node.right!) + } + index += 1 + } + + return root + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/set-zeroes-in-matrix.md b/articles/set-zeroes-in-matrix.md index 905883b5c..72cef4283 100644 --- a/articles/set-zeroes-in-matrix.md +++ b/articles/set-zeroes-in-matrix.md @@ -208,11 +208,40 @@ class Solution { } ``` +```swift +class Solution { + func setZeroes(_ matrix: inout [[Int]]) { + let rows = matrix.count + let cols = matrix[0].count + var mark = matrix + + for r in 0.. Where $m$ is the number of rows and $n$ is the number of columns. @@ -407,6 +436,34 @@ class Solution { } ``` +```swift +class Solution { + func setZeroes(_ matrix: inout [[Int]]) { + let rows = matrix.count + let cols = matrix[0].count + var rowFlags = Array(repeating: false, count: rows) + var colFlags = Array(repeating: false, count: cols) + + for r in 0.. 0 { + matrix[r][0] = 0 + } else { + rowZero = true + } + } + } + } + + for r in 1.. 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/simplify-path.md b/articles/simplify-path.md index 23fe29c96..ae0ecb3ee 100644 --- a/articles/simplify-path.md +++ b/articles/simplify-path.md @@ -105,6 +105,32 @@ class Solution { } ``` +```csharp +public class Solution { + public string SimplifyPath(string path) { + Stack stack = new Stack(); + string cur = ""; + + foreach (char c in path + "/") { + if (c == '/') { + if (cur == "..") { + if (stack.Count > 0) stack.Pop(); + } else if (cur != "" && cur != ".") { + stack.Push(cur); + } + cur = ""; + } else { + cur += c; + } + } + + var result = new List(stack); + result.Reverse(); + return "/" + string.Join("/", result); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -205,6 +231,29 @@ class Solution { } ``` +```csharp +public class Solution { + public string SimplifyPath(string path) { + Stack stack = new Stack(); + string[] parts = path.Split('/'); + + foreach (string part in parts) { + if (part == "..") { + if (stack.Count > 0) { + stack.Pop(); + } + } else if (part != "" && part != ".") { + stack.Push(part); + } + } + + var result = new List(stack); + result.Reverse(); + return "/" + string.Join("/", result); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/single-number.md b/articles/single-number.md index f46078213..8919e9baa 100644 --- a/articles/single-number.md +++ b/articles/single-number.md @@ -136,6 +136,26 @@ class Solution { } ``` +```swift +class Solution { + func singleNumber(_ nums: [Int]) -> Int { + for i in 0.. Int { + var seen = Set() + + for num in nums { + if seen.contains(num) { + seen.remove(num) + } else { + seen.insert(num) + } + } + + return seen.first! + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -397,6 +435,25 @@ class Solution { } ``` +```swift +class Solution { + func singleNumber(_ nums: [Int]) -> Int { + var nums = nums.sorted() + var i = 0 + + while i < nums.count - 1 { + if nums[i] == nums[i + 1] { + i += 2 + } else { + return nums[i] + } + } + + return nums[i] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -494,6 +551,18 @@ class Solution { } ``` +```swift +class Solution { + func singleNumber(_ nums: [Int]) -> Int { + var res = 0 + for num in nums { + res ^= num + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/single-threaded-cpu.md b/articles/single-threaded-cpu.md index 5b7005989..16f487b94 100644 --- a/articles/single-threaded-cpu.md +++ b/articles/single-threaded-cpu.md @@ -109,12 +109,12 @@ class Solution { * @return {number[]} */ getOrder(tasks) { - const available = new MinPriorityQueue({ - compare: (a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0] - }); - const pending = new MinPriorityQueue({ - compare: (a, b) => a[0] - b[0] - }); + const available = new PriorityQueue( + (a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0] + ); + const pending = new PriorityQueue( + (a, b) => a[0] - b[0] + ); tasks.forEach(([enqueueTime, processTime], i) => { pending.enqueue([enqueueTime, processTime, i]); @@ -143,6 +143,42 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] GetOrder(int[][] tasks) { + var available = new PriorityQueue<(int procTime, int index), (int procTime, int index)>(); + var pending = new PriorityQueue<(int startTime, int procTime, int index), int>(); + + int n = tasks.Length; + for (int i = 0; i < n; i++) { + pending.Enqueue((tasks[i][0], tasks[i][1], i), tasks[i][0]); + } + + long time = 0; + int[] res = new int[n]; + int idx = 0; + + while (pending.Count > 0 || available.Count > 0) { + while (pending.Count > 0 && pending.Peek().startTime <= time) { + var task = pending.Dequeue(); + available.Enqueue((task.procTime, task.index), (task.procTime, task.index)); + } + + if (available.Count == 0) { + time = pending.Peek().startTime; + continue; + } + + var next = available.Dequeue(); + time += next.procTime; + res[idx++] = next.index; + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -259,9 +295,9 @@ class Solution { tasks.sort((a, b) => a[0] - b[0]); const res = []; - const minHeap = new MinPriorityQueue({ compare: (a, b) => + const minHeap = new PriorityQueue((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0] - }); + ); let i = 0, time = tasks[0][0]; while (minHeap.size() || i < n) { @@ -282,6 +318,44 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] GetOrder(int[][] tasks) { + int n = tasks.Length; + int i = 0; + for (; i < n; i++) { + tasks[i] = new int[] { tasks[i][0], tasks[i][1], i }; // {enqueueTime, processingTime, index} + } + + Array.Sort(tasks, (a, b) => a[0].CompareTo(b[0])); // sort by enqueueTime + + int[] res = new int[n]; + var minHeap = new PriorityQueue<(int procTime, int index), (int procTime, int index)>(); + + int idx = 0; + i = 0; + long time = tasks[0][0]; + + while (minHeap.Count > 0 || i < n) { + while (i < n && tasks[i][0] <= time) { + minHeap.Enqueue((tasks[i][1], tasks[i][2]), (tasks[i][1], tasks[i][2])); + i++; + } + + if (minHeap.Count == 0) { + time = tasks[i][0]; + } else { + var task = minHeap.Dequeue(); + time += task.procTime; + res[idx++] = task.index; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -430,14 +504,14 @@ class Solution { return a - b; }); - const minHeap = new MinPriorityQueue({ - compare: (a, b) => { + const minHeap = new PriorityQueue( + (a, b) => { if (tasks[a][1] !== tasks[b][1]) { return tasks[a][1] - tasks[b][1]; } return a - b; } - }); + ); const res = []; let time = 0; @@ -463,6 +537,48 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] GetOrder(int[][] tasks) { + int n = tasks.Length; + int[] indices = new int[n]; + int i = 0; + for (; i < n; i++) { + indices[i] = i; + } + + Array.Sort(indices, (a, b) => + tasks[a][0] != tasks[b][0] ? tasks[a][0].CompareTo(tasks[b][0]) : a.CompareTo(b) + ); + + var minHeap = new PriorityQueue(); + + int[] result = new int[n]; + long time = 0; + int resIndex = 0; + i = 0; + + while (minHeap.Count > 0 || i < n) { + while (i < n && tasks[indices[i]][0] <= time) { + int idx = indices[i]; + minHeap.Enqueue(idx, (tasks[idx][1], idx)); + i++; + } + + if (minHeap.Count == 0) { + time = tasks[indices[i]][0]; + } else { + int nextIndex = minHeap.Dequeue(); + time += tasks[nextIndex][1]; + result[resIndex++] = nextIndex; + } + } + + return result; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/sliding-window-maximum.md b/articles/sliding-window-maximum.md index c4accb268..a7af08296 100644 --- a/articles/sliding-window-maximum.md +++ b/articles/sliding-window-maximum.md @@ -133,12 +133,32 @@ class Solution { } ``` +```swift +class Solution { + func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] { + var output = [Int]() + + for i in 0...(nums.count - k) { + var maxi = nums[i] + for j in i..<(i + k) { + maxi = max(maxi, nums[j]) + } + output.append(maxi) + } + + return output + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * k)$ -* Space complexity: $O(1)$ +* Space complexity: + * $O(1)$ extra space. + * $O(n - k + 1)$ space for the output array. > Where $n$ is the length of the array and $k$ is the size of the window. @@ -537,6 +557,64 @@ class Solution { } ``` +```swift +class SegmentTree { + private var n: Int + private var tree: [Int] + + init(_ N: Int, _ A: [Int]) { + self.n = N + while (self.n & (self.n - 1)) != 0 { + self.n += 1 + } + self.tree = [Int](repeating: Int.min, count: 2 * self.n) + build(N, A) + } + + private func build(_ N: Int, _ A: [Int]) { + for i in 0.. Int { + var res = Int.min + var l = l + n + var r = r + n + 1 + while l < r { + if l & 1 != 0 { + res = max(res, tree[l]) + l += 1 + } + if r & 1 != 0 { + r -= 1 + res = max(res, tree[r]) + } + l >>= 1 + r >>= 1 + } + return res + } +} + +class Solution { + func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] { + let n = nums.count + let segTree = SegmentTree(n, nums) + var output = [Int]() + + for i in 0...(n - k) { + output.append(segTree.query(i, i + k - 1)) + } + + return output + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -635,8 +713,9 @@ class Solution { ```csharp public class Solution { public int[] MaxSlidingWindow(int[] nums, int k) { - PriorityQueue<(int val, int idx), int> pq = new PriorityQueue<(int val, int idx), int> - (Comparer.Create((a, b) => b.CompareTo(a))); + PriorityQueue<(int val, int idx), int> pq = new PriorityQueue<(int val, int idx), int>( + Comparer.Create((a, b) => b.CompareTo(a)) + ); int[] output = new int[nums.Length - k + 1]; int idx = 0; @@ -700,6 +779,36 @@ class Solution { } ``` +```swift +class Solution { + func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] { + var heap = Heap() + var output = [Int]() + + for i in 0..= k - 1 { + while heap.max!.index <= i - k { + heap.removeMax() + } + output.append(heap.max!.num) + } + } + return output + } +} + +struct Item: Comparable { + let num: Int + let index: Int + + static func < (lhs: Item, rhs: Item) -> Bool { + return lhs.num < rhs.num + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -963,6 +1072,41 @@ class Solution { } ``` +```swift +class Solution { + func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] { + let n = nums.count + var leftMax = [Int](repeating: 0, count: n) + var rightMax = [Int](repeating: 0, count: n) + + leftMax[0] = nums[0] + rightMax[n - 1] = nums[n - 1] + + for i in 1.. [Int] { + var output = [Int]() + var deque = [Int]() // Index + var l = 0, r = 0 + + while r < nums.count { + while !deque.isEmpty && nums[deque.last!] < nums[r] { + deque.removeLast() + } + deque.append(r) + + if l > deque.first! { + deque.removeFirst() + } + + if (r + 1) >= k { + output.append(nums[deque.first!]) + l += 1 + } + r += 1 + } + + return output + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/sort-an-array.md b/articles/sort-an-array.md index ba9edb507..6b34f49d2 100644 --- a/articles/sort-an-array.md +++ b/articles/sort-an-array.md @@ -205,11 +205,63 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] SortArray(int[] nums) { + QuickSort(nums, 0, nums.Length - 1); + return nums; + } + + private void QuickSort(int[] nums, int left, int right) { + if (right <= left + 1) { + if (right == left + 1 && nums[right] < nums[left]) { + Swap(nums, left, right); + } + return; + } + + int j = Partition(nums, left, right); + QuickSort(nums, left, j - 1); + QuickSort(nums, j + 1, right); + } + + private int Partition(int[] nums, int left, int right) { + int mid = (left + right) >> 1; + Swap(nums, mid, left + 1); + + if (nums[left] > nums[right]) Swap(nums, left, right); + if (nums[left + 1] > nums[right]) Swap(nums, left + 1, right); + if (nums[left] > nums[left + 1]) Swap(nums, left, left + 1); + + int pivot = nums[left + 1]; + int i = left + 1, j = right; + + while (true) { + while (++i <= right && nums[i] < pivot) ; + while (--j >= left && nums[j] > pivot) ; + + if (i > j) break; + + Swap(nums, i, j); + } + + Swap(nums, left + 1, j); + return j; + } + + private void Swap(int[] nums, int i, int j) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } +} +``` + ::tabs-end ### Time & Space Complexity -* Time complexity: $O(n)$ in average case, $O(n ^ 2)$ in worst case. +* Time complexity: $O(n \log n)$ in average case, $O(n ^ 2)$ in worst case. * Space complexity: $O(\log n)$ for recursive stack. --- @@ -397,6 +449,47 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] SortArray(int[] nums) { + MergeSort(nums, 0, nums.Length - 1); + return nums; + } + + private void MergeSort(int[] arr, int l, int r) { + if (l == r) return; + + int m = (l + r) / 2; + MergeSort(arr, l, m); + MergeSort(arr, m + 1, r); + Merge(arr, l, m, r); + } + + private void Merge(int[] arr, int L, int M, int R) { + int[] left = arr[L..(M + 1)]; + int[] right = arr[(M + 1)..(R + 1)]; + + int i = L, j = 0, k = 0; + + while (j < left.Length && k < right.Length) { + if (left[j] <= right[k]) { + arr[i++] = left[j++]; + } else { + arr[i++] = right[k++]; + } + } + + while (j < left.Length) { + arr[i++] = left[j++]; + } + + while (k < right.Length) { + arr[i++] = right[k++]; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -580,6 +673,53 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] SortArray(int[] nums) { + HeapSort(nums); + return nums; + } + + private void Heapify(int[] arr, int n, int i) { + int l = (i << 1) + 1; + int r = (i << 1) + 2; + int largestNode = i; + + if (l < n && arr[l] > arr[largestNode]) { + largestNode = l; + } + + if (r < n && arr[r] > arr[largestNode]) { + largestNode = r; + } + + if (largestNode != i) { + Swap(arr, i, largestNode); + Heapify(arr, n, largestNode); + } + } + + private void HeapSort(int[] arr) { + int n = arr.Length; + + for (int i = n / 2 - 1; i >= 0; i--) { + Heapify(arr, n, i); + } + + for (int i = n - 1; i > 0; i--) { + Swap(arr, 0, i); + Heapify(arr, i, 0); + } + } + + private void Swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -711,6 +851,37 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] SortArray(int[] nums) { + CountingSort(nums); + return nums; + } + + private void CountingSort(int[] nums) { + Dictionary count = new Dictionary(); + int minVal = int.MaxValue, maxVal = int.MinValue; + + foreach (int val in nums) { + if (!count.ContainsKey(val)) { + count[val] = 0; + } + count[val]++; + minVal = Math.Min(minVal, val); + maxVal = Math.Max(maxVal, val); + } + + int index = 0; + for (int val = minVal; val <= maxVal; val++) { + if (!count.ContainsKey(val)) continue; + while (count[val]-- > 0) { + nums[index++] = val; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -974,6 +1145,74 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] SortArray(int[] nums) { + List negatives = new List(); + List positives = new List(); + + foreach (int num in nums) { + if (num < 0) negatives.Add(-num); + else positives.Add(num); + } + + if (negatives.Count > 0) { + RadixSort(negatives); + negatives.Reverse(); + for (int i = 0; i < negatives.Count; i++) { + negatives[i] = -negatives[i]; + } + } + + if (positives.Count > 0) { + RadixSort(positives); + } + + List result = new List(); + result.AddRange(negatives); + result.AddRange(positives); + + return result.ToArray(); + } + + private void RadixSort(List arr) { + int n = arr.Count; + int maxElement = 0; + foreach (int num in arr) { + if (num > maxElement) maxElement = num; + } + + int d = 1; + while (maxElement / d > 0) { + CountSort(arr, n, d); + d *= 10; + } + } + + private void CountSort(List arr, int n, int d) { + int[] count = new int[10]; + for (int i = 0; i < n; i++) { + int digit = (arr[i] / d) % 10; + count[digit]++; + } + + for (int i = 1; i < 10; i++) { + count[i] += count[i - 1]; + } + + int[] res = new int[n]; + for (int i = n - 1; i >= 0; i--) { + int digit = (arr[i] / d) % 10; + res[--count[digit]] = arr[i]; + } + + for (int i = 0; i < n; i++) { + arr[i] = res[i]; + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1097,9 +1336,37 @@ class Solution { } ``` +```csharp +public class Solution { + public int[] SortArray(int[] nums) { + int n = nums.Length; + if (n == 1) return nums; + + ShellSort(nums, n); + return nums; + } + + private void ShellSort(int[] nums, int n) { + int gap = n / 2; + while (gap >= 1) { + for (int i = gap; i < n; i++) { + int tmp = nums[i]; + int j = i - gap; + while (j >= 0 && nums[j] > tmp) { + nums[j + gap] = nums[j]; + j -= gap; + } + nums[j + gap] = tmp; + } + gap /= 2; + } + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n \log n)$ in average case, $O(n ^ 2)$ in worst case. -* Space complexity: $O(1)$ \ No newline at end of file +* Space complexity: $O(1)$ 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-colors.md b/articles/sort-colors.md index c94416b39..46bc4a86a 100644 --- a/articles/sort-colors.md +++ b/articles/sort-colors.md @@ -40,6 +40,14 @@ class Solution { } ``` +```csharp +public class Solution { + public void SortColors(int[] nums) { + Array.Sort(nums); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -130,6 +138,24 @@ class Solution { } ``` +```csharp +public class Solution { + public void SortColors(int[] nums) { + int[] count = new int[3]; + foreach (int num in nums) { + count[num]++; + } + + int index = 0; + for (int i = 0; i < 3; i++) { + while (count[i]-- > 0) { + nums[index++] = i; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -236,6 +262,32 @@ class Solution { } ``` +```csharp +public class Solution { + public void SortColors(int[] nums) { + int i = 0, l = 0, r = nums.Length - 1; + + while (i <= r) { + if (nums[i] == 0) { + Swap(nums, l, i); + l++; + } else if (nums[i] == 2) { + Swap(nums, i, r); + r--; + i--; + } + i++; + } + } + + private void Swap(int[] nums, int i, int j) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -339,6 +391,27 @@ class Solution { } ``` +```csharp +public class Solution { + public void SortColors(int[] nums) { + int zero = 0, one = 0, two = 0; + + for (int i = 0; i < nums.Length; i++) { + if (nums[i] == 0) { + nums[two++] = 2; + nums[one++] = 1; + nums[zero++] = 0; + } else if (nums[i] == 1) { + nums[two++] = 2; + nums[one++] = 1; + } else { + nums[two++] = 2; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -429,6 +502,26 @@ class Solution { } ``` +```csharp +public class Solution { + public void SortColors(int[] nums) { + int zero = 0, one = 0; + + for (int two = 0; two < nums.Length; two++) { + int tmp = nums[two]; + nums[two] = 2; + + if (tmp < 2) { + nums[one++] = 1; + } + if (tmp < 1) { + nums[zero++] = 0; + } + } + } +} +``` + ::tabs-end ### Time & Space Complexity 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/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 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 diff --git a/articles/spiral-matrix.md b/articles/spiral-matrix.md index b9719b928..2e82fff76 100644 --- a/articles/spiral-matrix.md +++ b/articles/spiral-matrix.md @@ -198,12 +198,47 @@ class Solution { } ``` +```swift +class Solution { + func spiralOrder(_ matrix: [[Int]]) -> [Int] { + var m = matrix.count + var n = matrix[0].count + var res: [Int] = [] + + // append all the elements in the given direction + func dfs(_ row: Int, _ col: Int, _ r: inout Int, _ c: inout Int, _ dr: Int, _ dc: Int) { + if row == 0 || col == 0 { + return + } + + for _ in 0.. Where $m$ is the number of rows and $n$ is the number of columns. @@ -462,12 +497,48 @@ class Solution { } ``` +```swift +class Solution { + func spiralOrder(_ matrix: [[Int]]) -> [Int] { + var res: [Int] = [] + var left = 0, right = matrix[0].count + var top = 0, bottom = matrix.count + + while left < right && top < bottom { + for i in left.. Where $m$ is the number of rows and $n$ is the number of columns. @@ -650,11 +721,36 @@ class Solution { } ``` +```swift +class Solution { + func spiralOrder(_ matrix: [[Int]]) -> [Int] { + var res: [Int] = [] + let directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] + var steps = [matrix[0].count, matrix.count - 1] + + var r = 0, c = -1, d = 0 + while steps[d & 1] > 0 { + for _ in 0.. Where $m$ is the number of rows and $n$ is the number of columns. \ No newline at end of file diff --git a/articles/split-array-largest-sum.md b/articles/split-array-largest-sum.md index dccf649c5..617691f9b 100644 --- a/articles/split-array-largest-sum.md +++ b/articles/split-array-largest-sum.md @@ -113,6 +113,36 @@ class Solution { } ``` +```csharp +public class Solution { + public int SplitArray(int[] nums, int k) { + int n = nums.Length; + return Dfs(nums, 0, k, n); + } + + private int Dfs(int[] nums, int i, int m, int n) { + if (i == n) { + return m == 0 ? 0 : int.MaxValue; + } + if (m == 0) { + return int.MaxValue; + } + + int res = int.MaxValue; + int curSum = 0; + for (int j = i; j <= n - m; j++) { + curSum += nums[j]; + int next = Dfs(nums, j + 1, m - 1, n); + if (next != int.MaxValue) { + res = Math.Min(res, Math.Max(curSum, next)); + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -231,7 +261,7 @@ class Solution { */ splitArray(nums, k) { const n = nums.length; - const dp = Array.from({ length: n }, () => Array(m + 1).fill(-1)); + const dp = Array.from({ length: n }, () => Array(k + 1).fill(-1)); const dfs = (i, m) => { if (i === n) { @@ -259,6 +289,50 @@ class Solution { } ``` +```csharp +public class Solution { + private int[,] dp; + + public int SplitArray(int[] nums, int k) { + int n = nums.Length; + dp = new int[n, k + 1]; + + for (int i = 0; i < n; i++) { + for (int j = 0; j <= k; j++) { + dp[i, j] = -1; + } + } + + return Dfs(nums, 0, k, n); + } + + private int Dfs(int[] nums, int i, int m, int n) { + if (i == n) { + return m == 0 ? 0 : int.MaxValue; + } + if (m == 0) { + return int.MaxValue; + } + if (dp[i, m] != -1) { + return dp[i, m]; + } + + int res = int.MaxValue; + int curSum = 0; + for (int j = i; j <= n - m; j++) { + curSum += nums[j]; + int next = Dfs(nums, j + 1, m - 1, n); + if (next != int.MaxValue) { + res = Math.Min(res, Math.Max(curSum, next)); + } + } + + dp[i, m] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -368,6 +442,37 @@ class Solution { } ``` +```csharp +public class Solution { + public int SplitArray(int[] nums, int k) { + int n = nums.Length; + int[,] dp = new int[n + 1, k + 1]; + + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= k; j++) { + dp[i, j] = int.MaxValue; + } + } + + dp[n, 0] = 0; + + for (int m = 1; m <= k; m++) { + for (int i = n - 1; i >= 0; i--) { + int curSum = 0; + for (int j = i; j < n - m + 1; j++) { + curSum += nums[j]; + if (dp[j + 1, m - 1] != int.MaxValue) { + dp[i, m] = Math.Min(dp[i, m], Math.Max(curSum, dp[j + 1, m - 1])); + } + } + } + } + + return dp[0, k]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -485,6 +590,36 @@ class Solution { } ``` +```csharp +public class Solution { + public int SplitArray(int[] nums, int k) { + int n = nums.Length; + int[] dp = new int[n + 1]; + int[] nextDp = new int[n + 1]; + Array.Fill(dp, int.MaxValue); + dp[n] = 0; + + for (int m = 1; m <= k; m++) { + Array.Fill(nextDp, int.MaxValue); + for (int i = n - 1; i >= 0; i--) { + int curSum = 0; + for (int j = i; j < n - m + 1; j++) { + curSum += nums[j]; + if (dp[j + 1] != int.MaxValue) { + nextDp[i] = Math.Min(nextDp[i], Math.Max(curSum, dp[j + 1])); + } + } + } + var temp = dp; + dp = nextDp; + nextDp = temp; + } + + return dp[0]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -639,6 +774,43 @@ class Solution { } ``` +```csharp +public class Solution { + public int SplitArray(int[] nums, int k) { + int l = 0, r = 0, res = 0; + foreach (int num in nums) { + l = Math.Max(l, num); + r += num; + } + res = r; + + while (l <= r) { + int mid = l + (r - l) / 2; + if (CanSplit(nums, k, mid)) { + res = mid; + r = mid - 1; + } else { + l = mid + 1; + } + } + return res; + } + + private bool CanSplit(int[] nums, int k, int largest) { + int subarray = 1, curSum = 0; + foreach (int num in nums) { + curSum += num; + if (curSum > largest) { + subarray++; + if (subarray > k) return false; + curSum = num; + } + } + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -852,6 +1024,60 @@ class Solution { } ``` +```csharp +public class Solution { + private int[] prefix; + private int n; + + public int SplitArray(int[] nums, int k) { + n = nums.Length; + prefix = new int[n + 1]; + for (int i = 0; i < n; i++) { + prefix[i + 1] = prefix[i] + nums[i]; + } + + int l = int.MinValue, r = 0; + foreach (int num in nums) { + l = Math.Max(l, num); + r += num; + } + + int res = r; + while (l <= r) { + int mid = l + (r - l) / 2; + if (CanSplit(mid, k)) { + res = mid; + r = mid - 1; + } else { + l = mid + 1; + } + } + return res; + } + + private bool CanSplit(int largest, int k) { + int subarrays = 0, i = 0; + while (i < n) { + int l = i + 1, r = n; + while (l <= r) { + int mid = l + (r - l) / 2; + if (prefix[mid] - prefix[i] <= largest) { + l = mid + 1; + } else { + r = mid - 1; + } + } + subarrays++; + i = r; + if (subarrays > k) { + return false; + } + } + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/sqrtx.md b/articles/sqrtx.md index 13d854b33..bc2e10fa7 100644 --- a/articles/sqrtx.md +++ b/articles/sqrtx.md @@ -82,6 +82,23 @@ class Solution { } ``` +```csharp +public class Solution { + public int MySqrt(int x) { + if (x == 0) return 0; + + int res = 1; + for (int i = 1; i <= x; i++) { + if ((long)i * i > x) { + return res; + } + res = i; + } + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -130,6 +147,14 @@ class Solution { } ``` +```csharp +public class Solution { + public int MySqrt(int x) { + return (int)Math.Sqrt(x); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -236,6 +261,31 @@ class Solution { } ``` +```csharp +public class Solution { + public int MySqrt(int x) { + int l = 0, r = x; + int res = 0; + + while (l <= r) { + int m = l + (r - l) / 2; + long sq = (long)m * m; + + if (sq > x) { + r = m - 1; + } else if (sq < x) { + l = m + 1; + res = m; + } else { + return m; + } + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -307,6 +357,20 @@ class Solution { } ``` +```csharp +public class Solution { + public int MySqrt(int x) { + if (x < 2) { + return x; + } + + int l = MySqrt(x >> 2) << 1; + int r = l + 1; + return (long)r * r > x ? l : r; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -370,6 +434,18 @@ class Solution { } ``` +```csharp +public class Solution { + public int MySqrt(int x) { + long r = x; + while (r * r > x) { + r = (r + x / r) >> 1; + } + return (int)r; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/stone-game-iii.md b/articles/stone-game-iii.md index e95a8e508..781024036 100644 --- a/articles/stone-game-iii.md +++ b/articles/stone-game-iii.md @@ -144,6 +144,40 @@ class Solution { } ``` +```csharp +public class Solution { + public string StoneGameIII(int[] stoneValue) { + int n = stoneValue.Length; + int?[,] dp = new int?[n, 2]; + + int Dfs(int i, int alice) { + if (i >= n) return 0; + if (dp[i, alice].HasValue) return dp[i, alice].Value; + + int res = alice == 1 ? int.MinValue : int.MaxValue; + int score = 0; + + for (int j = i; j < Math.Min(i + 3, n); j++) { + if (alice == 1) { + score += stoneValue[j]; + res = Math.Max(res, score + Dfs(j + 1, 0)); + } else { + score -= stoneValue[j]; + res = Math.Min(res, score + Dfs(j + 1, 1)); + } + } + + dp[i, alice] = res; + return res; + } + + int result = Dfs(0, 1); + if (result == 0) return "Tie"; + return result > 0 ? "Alice" : "Bob"; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -277,6 +311,33 @@ class Solution { } ``` +```csharp +public class Solution { + public string StoneGameIII(int[] stoneValue) { + int n = stoneValue.Length; + Dictionary dp = new Dictionary(); + + int Dfs(int i) { + if (i >= n) return 0; + if (dp.ContainsKey(i)) return dp[i]; + + int res = int.MinValue, total = 0; + for (int j = i; j < Math.Min(i + 3, n); j++) { + total += stoneValue[j]; + res = Math.Max(res, total - Dfs(j + 1)); + } + + dp[i] = res; + return res; + } + + int result = Dfs(0); + if (result == 0) return "Tie"; + return result > 0 ? "Alice" : "Bob"; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -384,6 +445,29 @@ class Solution { } ``` +```csharp +public class Solution { + public string StoneGameIII(int[] stoneValue) { + int n = stoneValue.Length; + int[] dp = new int[n + 1]; + for (int i = 0; i <= n; i++) dp[i] = int.MinValue; + dp[n] = 0; + + for (int i = n - 1; i >= 0; i--) { + int total = 0; + for (int j = i; j < Math.Min(i + 3, n); j++) { + total += stoneValue[j]; + dp[i] = Math.Max(dp[i], total - dp[j + 1]); + } + } + + int result = dp[0]; + if (result == 0) return "Tie"; + return result > 0 ? "Alice" : "Bob"; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -483,6 +567,28 @@ class Solution { } ``` +```csharp +public class Solution { + public string StoneGameIII(int[] stoneValue) { + int n = stoneValue.Length; + int[] dp = new int[4]; + + for (int i = n - 1; i >= 0; i--) { + int total = 0; + dp[i % 4] = int.MinValue; + + for (int j = i; j < Math.Min(i + 3, n); j++) { + total += stoneValue[j]; + dp[i % 4] = Math.Max(dp[i % 4], total - dp[(j + 1) % 4]); + } + } + + if (dp[0] == 0) return "Tie"; + return dp[0] > 0 ? "Alice" : "Bob"; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/string-encode-and-decode.md b/articles/string-encode-and-decode.md index c0cad7e12..ca00a45b8 100644 --- a/articles/string-encode-and-decode.md +++ b/articles/string-encode-and-decode.md @@ -282,12 +282,62 @@ class Solution { } ``` +```swift +class Solution { + func encode(_ strs: [String]) -> String { + if strs.isEmpty { return "" } + + var sizes: [Int] = [] + var res = "" + for s in strs { + sizes.append(s.count) + } + for sz in sizes { + res += String(sz) + res += "," + } + + res += "#" + for s in strs { + res += s + } + return res + } + + func decode(_ s: String) -> [String] { + if s.isEmpty { return [] } + let sArr = Array(s) + var sizes: [Int] = [] + var res: [String] = [] + var i = 0 + + while sArr[i] != "#" { + var cur = "" + while sArr[i] != "," { + cur.append(sArr[i]) + i += 1 + } + sizes.append(Int(cur)!) + i += 1 + } + + i += 1 + for sz in sizes { + let substring = String(sArr[i.. Where $m$ is the sum of lengths of all the strings and $n$ is the number of strings. @@ -506,11 +556,46 @@ class Solution { } ``` +```swift +class Solution { + func encode(_ strs: [String]) -> String { + var res = "" + for s in strs { + res += "\(s.count)#\(s)" + } + return res + } + + func decode(_ s: String) -> [String] { + var res = [String]() + let sArr = Array(s) + var i = 0 + + while i < sArr.count { + var j = i + while sArr[j] != "#" { + j += 1 + } + let lengthStr = String(sArr[i.. Where $m$ is the sum of lengths of all the strings and $n$ is the number of strings. \ 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 diff --git a/articles/subarray-sum-equals-k.md b/articles/subarray-sum-equals-k.md index 5afa95bd3..fa979f529 100644 --- a/articles/subarray-sum-equals-k.md +++ b/articles/subarray-sum-equals-k.md @@ -69,6 +69,24 @@ class Solution { } ``` +```csharp +public class Solution { + public int SubarraySum(int[] nums, int k) { + int res = 0; + for (int i = 0; i < nums.Length; i++) { + int sum = 0; + for (int j = i; j < nums.Length; j++) { + sum += nums[j]; + if (sum == k) { + res++; + } + } + } + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -161,6 +179,32 @@ class Solution { } ``` +```csharp +public class Solution { + public int SubarraySum(int[] nums, int k) { + int res = 0, curSum = 0; + Dictionary prefixSums = new Dictionary(); + prefixSums[0] = 1; + + foreach (int num in nums) { + curSum += num; + int diff = curSum - k; + + if (prefixSums.ContainsKey(diff)) { + res += prefixSums[diff]; + } + + if (!prefixSums.ContainsKey(curSum)) { + prefixSums[curSum] = 0; + } + prefixSums[curSum]++; + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity 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 diff --git a/articles/subarrays-with-k-different-integers.md b/articles/subarrays-with-k-different-integers.md index 26328205c..a2e24a470 100644 --- a/articles/subarrays-with-k-different-integers.md +++ b/articles/subarrays-with-k-different-integers.md @@ -246,7 +246,7 @@ class Solution { --- -## 3. Slidingt Window (One Pass) - I +## 3. Sliding Window (One Pass) - I ::tabs-start diff --git a/articles/subsets-ii.md b/articles/subsets-ii.md index 7ceeedab6..fef683226 100644 --- a/articles/subsets-ii.md +++ b/articles/subsets-ii.md @@ -193,6 +193,31 @@ class Solution { } ``` +```swift +class Solution { + func subsetsWithDup(_ nums: [Int]) -> [[Int]] { + var res = Set<[Int]>() + var subset = [Int]() + let nums = nums.sorted() + + func backtrack(_ i: Int) { + if i == nums.count { + res.insert(subset) + return + } + + subset.append(nums[i]) + backtrack(i + 1) + subset.removeLast() + backtrack(i + 1) + } + + backtrack(0) + return Array(res) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -202,7 +227,7 @@ class Solution { --- -## 2. Backtracking (Pick / Not Pick) +## 2. Backtracking - I ::tabs-start @@ -405,16 +430,48 @@ class Solution { } ``` +```swift +class Solution { + func subsetsWithDup(_ nums: [Int]) -> [[Int]] { + var res = [[Int]]() + var subset = [Int]() + let nums = nums.sorted() + + func backtrack(_ i: Int) { + if i == nums.count { + res.append(subset) + return + } + + subset.append(nums[i]) + backtrack(i + 1) + subset.removeLast() + + var j = i + while j + 1 < nums.count && nums[j] == nums[j + 1] { + j += 1 + } + backtrack(j + 1) + } + + backtrack(0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * 2 ^ n)$ -* Space complexity: $O(n)$ +* Space complexity: + * $O(n)$ extra space. + * $O(2 ^ n)$ space for the output list. --- -## 3. Backtracking +## 3. Backtracking - II ::tabs-start @@ -595,12 +652,40 @@ class Solution { } ``` +```swift +class Solution { + func subsetsWithDup(_ nums: [Int]) -> [[Int]] { + var res = [[Int]]() + var subset = [Int]() + let nums = nums.sorted() + + func backtrack(_ i: Int) { + res.append(subset) + + for j in i.. i && nums[j] == nums[j - 1] { + continue + } + subset.append(nums[j]) + backtrack(j + 1) + subset.removeLast() + } + } + + backtrack(0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * 2 ^ n)$ -* Space complexity: $O(n)$ +* Space complexity: + * $O(n)$ extra space. + * $O(2 ^ n)$ space for the output list. --- @@ -614,6 +699,7 @@ class Solution: nums.sort() res = [[]] prev_Idx = idx = 0 + for i in range(len(nums)): idx = prev_idx if i >= 1 and nums[i] == nums[i - 1] else 0 prev_idx = len(res) @@ -621,6 +707,7 @@ class Solution: tmp = res[j].copy() tmp.append(nums[i]) res.append(tmp) + return res ``` @@ -632,6 +719,7 @@ public class Solution { res.add(new ArrayList<>()); int prevIdx = 0; int idx = 0; + for (int i = 0; i < nums.length; i++) { idx = (i >= 1 && nums[i] == nums[i - 1]) ? prevIdx : 0; prevIdx = res.size(); @@ -641,6 +729,7 @@ public class Solution { res.add(tmp); } } + return res; } } @@ -654,6 +743,7 @@ public: vector> res = {{}}; int prevIdx = 0; int idx = 0; + for (int i = 0; i < nums.size(); i++) { idx = (i >= 1 && nums[i] == nums[i - 1]) ? prevIdx : 0; prevIdx = res.size(); @@ -663,6 +753,7 @@ public: res.push_back(tmp); } } + return res; } }; @@ -679,6 +770,7 @@ class Solution { const res = [[]]; let prevIdx = 0; let idx = 0; + for (let i = 0; i < nums.length; i++) { idx = (i >= 1 && nums[i] === nums[i - 1]) ? prevIdx : 0; prevIdx = res.length; @@ -688,6 +780,7 @@ class Solution { res.push(tmp); } } + return res; } } @@ -700,6 +793,7 @@ public class Solution { var res = new List> { new List() }; int prevIdx = 0; int idx = 0; + for (int i = 0; i < nums.Length; i++) { idx = (i >= 1 && nums[i] == nums[i - 1]) ? prevIdx : 0; prevIdx = res.Count; @@ -709,6 +803,7 @@ public class Solution { res.Add(tmp); } } + return res; } } @@ -761,9 +856,35 @@ class Solution { } ``` +```swift +class Solution { + func subsetsWithDup(_ nums: [Int]) -> [[Int]] { + let nums = nums.sorted() + var res: [[Int]] = [[]] + var prevIdx = 0 + var idx = 0 + + for i in 0..= 1 && nums[i] == nums[i - 1]) ? prevIdx : 0 + prevIdx = res.count + + for j in idx.. List[List[int]]: res = [] - subset = [] def dfs(i): @@ -172,12 +171,37 @@ class Solution { } ``` +```swift +class Solution { + func subsets(_ nums: [Int]) -> [[Int]] { + var res = [[Int]]() + var subset = [Int]() + + func dfs(_ i: Int) { + if i >= nums.count { + res.append(subset) + return + } + subset.append(nums[i]) + dfs(i + 1) + subset.removeLast() + dfs(i + 1) + } + + dfs(0) + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * 2 ^ n)$ -* Space complexity: $O(n)$ +* Space complexity: + * $O(n)$ extra space. + * $O(2 ^ n)$ for the output list. --- @@ -316,12 +340,28 @@ class Solution { } ``` +```swift +class Solution { + func subsets(_ nums: [Int]) -> [[Int]] { + var res: [[Int]] = [[]] + + for num in nums { + res += res.map { $0 + [num] } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n * 2 ^ n)$ -* Space complexity: $O(n)$ +* Space complexity: + * $O(n)$ extra space. + * $O(2 ^ n)$ for the output list. --- @@ -461,9 +501,32 @@ class Solution { } ``` +```swift +class Solution { + func subsets(_ nums: [Int]) -> [[Int]] { + let n = nums.count + var res: [[Int]] = [] + + for i in 0..<(1 << n) { + var subset: [Int] = [] + for j in 0.. Bool { + if subRoot == nil { + return true + } + if root == nil { + return false + } + if sameTree(root, subRoot) { + return true + } + return isSubtree(root?.left, subRoot) || isSubtree(root?.right, subRoot) + } + + func sameTree(_ root: TreeNode?, _ subRoot: TreeNode?) -> Bool { + if root == nil && subRoot == nil { + return true + } + if let root = root, let subRoot = subRoot, root.val == subRoot.val { + return sameTree(root.left, subRoot.left) && sameTree(root.right, subRoot.right) + } + return false + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -319,11 +361,10 @@ class Solution { class Solution: def serialize(self, root: Optional[TreeNode]) -> str: - if root == None: - return "$#" - - return ("$" + str(root.val) + - self.serialize(root.left) + self.serialize(root.right)) + if root == None: + return "$#" + + return ("$" + str(root.val) + self.serialize(root.left) + self.serialize(root.right)) def z_function(self, s: str) -> list: z = [0] * len(s) @@ -341,10 +382,10 @@ class Solution: serialized_root = self.serialize(root) serialized_subRoot = self.serialize(subRoot) combined = serialized_subRoot + "|" + serialized_root - + z_values = self.z_function(combined) sub_len = len(serialized_subRoot) - + for i in range(sub_len + 1, len(combined)): if z_values[i] == sub_len: return True @@ -492,8 +533,7 @@ class Solution { if (root === null) { return "$#"; } - return "$" + root.val + - this.serialize(root.left) + this.serialize(root.right); + return "$" + root.val + this.serialize(root.left) + this.serialize(root.right); } /** @@ -714,6 +754,69 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func serialize(_ root: TreeNode?) -> String { + guard let root = root else { + return "$#" + } + return "$\(root.val)" + serialize(root.left) + serialize(root.right) + } + + func zFunction(_ s: String) -> [Int] { + let n = s.count + var z = [Int](repeating: 0, count: n) + var l = 0, r = 0 + let chars = Array(s) + + for i in 1.. r { + l = i + r = i + z[i] - 1 + } + } + return z + } + + func isSubtree(_ root: TreeNode?, _ subRoot: TreeNode?) -> Bool { + let serializedRoot = serialize(root) + let serializedSubRoot = serialize(subRoot) + let combined = serializedSubRoot + "|" + serializedRoot + + let zValues = zFunction(combined) + let subLen = serializedSubRoot.count + + for i in (subLen + 1)..(), nums); + return res; + } + + private void Backtrack(int i, List subset, int[] nums) { + int xorr = 0; + foreach (int num in subset) { + xorr ^= num; + } + res += xorr; + + for (int j = i; j < nums.Length; j++) { + subset.Add(nums[j]); + Backtrack(j + 1, subset, nums); + subset.RemoveAt(subset.Count - 1); + } + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -173,6 +198,21 @@ class Solution { } ``` +```csharp +public class Solution { + public int SubsetXORSum(int[] nums) { + return Dfs(0, 0, nums); + } + + private int Dfs(int i, int total, int[] nums) { + if (i == nums.Length) { + return total; + } + return Dfs(i + 1, total ^ nums[i], nums) + Dfs(i + 1, total, nums); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -270,6 +310,27 @@ class Solution { } ``` +```csharp +public class Solution { + public int SubsetXORSum(int[] nums) { + int n = nums.Length; + int res = 0; + + for (int mask = 0; mask < (1 << n); mask++) { + int xorr = 0; + for (int i = 0; i < n; i++) { + if ((mask & (1 << i)) != 0) { + xorr ^= nums[i]; + } + } + res += xorr; + } + + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -333,6 +394,18 @@ class Solution { } ``` +```csharp +public class Solution { + public int SubsetXORSum(int[] nums) { + int res = 0; + foreach (int num in nums) { + res |= num; + } + return res << (nums.Length - 1); + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/sum-of-two-integers.md b/articles/sum-of-two-integers.md index 4fffcb35f..6d43c0a14 100644 --- a/articles/sum-of-two-integers.md +++ b/articles/sum-of-two-integers.md @@ -60,6 +60,14 @@ class Solution { } ``` +```swift +class Solution { + func getSum(_ a: Int, _ b: Int) -> Int { + return a + b + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -250,6 +258,32 @@ class Solution { } ``` +```swift +class Solution { + func getSum(_ a: Int, _ b: Int) -> Int { + var carry = 0 + var res = 0 + let mask = 0xFFFFFFFF + + for i in 0..<32 { + let aBit = (a >> i) & 1 + let bBit = (b >> i) & 1 + let curBit = aBit ^ bBit ^ carry + carry = (aBit + bBit + carry) >= 2 ? 1 : 0 + if curBit == 1 { + res |= (1 << i) + } + } + + if res > 0x7FFFFFFF { + res = ~(res ^ mask) + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -379,6 +413,25 @@ class Solution { } ``` +```swift +class Solution { + func getSum(_ a: Int, _ b: Int) -> Int { + let mask = 0xFFFFFFFF + let maxInt = 0x7FFFFFFF + var a = a + var b = b + + while b != 0 { + let carry = (a & b) << 1 + a = (a ^ b) & mask + b = carry & mask + } + + return a <= maxInt ? a : ~(a ^ mask) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/surrounded-regions.md b/articles/surrounded-regions.md index f1009a0bc..1c0c5445c 100644 --- a/articles/surrounded-regions.md +++ b/articles/surrounded-regions.md @@ -330,6 +330,54 @@ class Solution { } ``` +```swift +class Solution { + func solve(_ board: inout [[Character]]) { + let ROWS = board.count + let COLS = board[0].count + + func capture(_ r: Int, _ c: Int) { + if r < 0 || c < 0 || r == ROWS || c == COLS || board[r][c] != "O" { + return + } + board[r][c] = "T" + capture(r + 1, c) + capture(r - 1, c) + capture(r, c + 1) + capture(r, c - 1) + } + + for r in 0.. { - let q = []; + let q = new Queue(); for (let r = 0; r < ROWS; r++) { for (let c = 0; c < COLS; c++) { if (r === 0 || r === ROWS - 1 || @@ -506,8 +554,8 @@ class Solution { } } } - while (q.length) { - let [r, c] = q.shift(); + while (!q.isEmpty()) { + let [r, c] = q.pop(); if (board[r][c] === 'O') { board[r][c] = 'T'; for (let [dr, dc] of directions) { @@ -684,6 +732,53 @@ class Solution { } ``` +```swift +class Solution { + func solve(_ board: inout [[Character]]) { + let ROWS = board.count + let COLS = board[0].count + let directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] + + func capture() { + var queue = Deque<(Int, Int)>() + for r in 0..= 0, nr < ROWS, nc >= 0, nc < COLS { + queue.append((nr, nc)) + } + } + } + } + } + + capture() + + for r in 0.. Int { + if parent[node] != node { + parent[node] = find(parent[node]) + } + return parent[node] + } + + func union(_ u: Int, _ v: Int) { + let pu = find(u) + let pv = find(v) + if pu == pv { return } + if size[pu] >= size[pv] { + size[pu] += size[pv] + parent[pv] = pu + } else { + size[pv] += size[pu] + parent[pu] = pv + } + } + + func connected(_ u: Int, _ v: Int) -> Bool { + return find(u) == find(v) + } +} + +class Solution { + func solve(_ board: inout [[Character]]) { + let ROWS = board.count + let COLS = board[0].count + let directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] + let dsu = DSU(ROWS * COLS + 1) + let N = ROWS * COLS + + for r in 0..= 0, nr < ROWS, nc >= 0, nc < COLS, board[nr][nc] == "O" { + dsu.union(r * COLS + c, nr * COLS + nc) + } + } + } + } + } + + for r in 0.. Int { + let n = grid.count + var visit = Array(repeating: Array(repeating: false, count: n), count: n) + + func dfs(_ node: (Int, Int), _ t: Int) -> Int { + let (r, c) = node + if r < 0 || c < 0 || r >= n || c >= n || visit[r][c] { + return 1000000 + } + if r == n - 1 && c == n - 1 { + return max(t, grid[r][c]) + } + visit[r][c] = true + let t = max(t, grid[r][c]) + let res = min(dfs((r + 1, c), t), + dfs((r - 1, c), t), + dfs((r, c + 1), t), + dfs((r, c - 1), t)) + visit[r][c] = false + return res + } + + return dfs((0, 0), 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -544,6 +573,51 @@ class Solution { } ``` +```swift +class Solution { + func swimInWater(_ grid: [[Int]]) -> Int { + let n = grid.count + var visit = Array(repeating: Array(repeating: false, count: n), count: n) + var minH = grid[0][0], maxH = grid[0][0] + + for row in 0.. Bool { + let (r, c) = node + if r < 0 || c < 0 || r >= n || c >= n || visit[r][c] || grid[r][c] > t { + return false + } + if r == n - 1 && c == n - 1 { + return true + } + visit[r][c] = true + return dfs((r + 1, c), t) || + dfs((r - 1, c), t) || + dfs((r, c + 1), t) || + dfs((r, c - 1), t) + } + + for t in minH...maxH { + if dfs((0, 0), t) { + return t + } + for r in 0.. Int { + let n = grid.count + var visit = Array(repeating: Array(repeating: false, count: n), count: n) + var minH = grid[0][0], maxH = grid[0][0] + + for row in 0.. Bool { + let (r, c) = node + if r < 0 || c < 0 || r >= n || c >= n || visit[r][c] || grid[r][c] > t { + return false + } + if r == n - 1 && c == n - 1 { + return true + } + visit[r][c] = true + return dfs((r + 1, c), t) || + dfs((r - 1, c), t) || + dfs((r, c + 1), t) || + dfs((r, c - 1), t) + } + + var l = minH, r = maxH + while l < r { + let m = (l + r) >> 1 + if dfs((0, 0), m) { + r = m + } else { + l = m + 1 + } + for row in 0.. Bool { + return lhs.time < rhs.time + } +} + +class Solution { + func swimInWater(_ grid: [[Int]]) -> Int { + let N = grid.count + var visit = Set<[Int]>() + var minHeap = Heap() + + let directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] + + minHeap.insert(Item(time: grid[0][0], row: 0, col: 0)) + visit.insert([0, 0]) + + while !minHeap.isEmpty { + let item = minHeap.removeMin() + let t = item.time, r = item.row, c = item.col + + if r == N - 1 && c == N - 1 { + return t + } + + for (dr, dc) in directions { + let neiR = r + dr, neiC = c + dc + if neiR < 0 || neiC < 0 || neiR == N || neiC == N || visit.contains([neiR, neiC]) { + continue + } + visit.insert([neiR, neiC]) + minHeap.insert(Item(time: max(t, grid[neiR][neiC]), row: neiR, col: neiC)) + } + } + + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1230,7 +1398,7 @@ class Solution: ``` ```java -public class DSU { +class DSU { private int[] Parent; private int[] Size; @@ -1625,6 +1793,75 @@ class Solution { } ``` +```swift +class DSU { + private var parent: [Int] + private var size: [Int] + + init(_ n: Int) { + parent = Array(0...(n - 1)) + size = Array(repeating: 1, count: n) + } + + func find(_ node: Int) -> Int { + if parent[node] != node { + parent[node] = find(parent[node]) + } + return parent[node] + } + + func union(_ u: Int, _ v: Int) -> Bool { + let pu = find(u) + let pv = find(v) + if pu == pv { + return false + } + if size[pu] < size[pv] { + parent[pu] = pv + size[pv] += size[pu] + } else { + parent[pv] = pu + size[pu] += size[pv] + } + return true + } + + func connected(_ u: Int, _ v: Int) -> Bool { + return find(u) == find(v) + } +} + +class Solution { + func swimInWater(_ grid: [[Int]]) -> Int { + let N = grid.count + let dsu = DSU(N * N) + var positions = [(Int, Int, Int)]() + let directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] + + for r in 0..= 0, nc >= 0, nr < N, nc < N, grid[nr][nc] <= t { + dsu.union(r * N + c, nr * N + nc) + } + } + if dsu.connected(0, N * N - 1) { + return t + } + } + return -1 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/target-sum.md b/articles/target-sum.md index 819f11b56..71c10c0c2 100644 --- a/articles/target-sum.md +++ b/articles/target-sum.md @@ -120,6 +120,20 @@ class Solution { } ``` +```swift +class Solution { + func findTargetSumWays(_ nums: [Int], _ target: Int) -> Int { + func backtrack(_ i: Int, _ total: Int) -> Int { + if i == nums.count { + return total == target ? 1 : 0 + } + return backtrack(i + 1, total + nums[i]) + backtrack(i + 1, total - nums[i]) + } + return backtrack(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -331,6 +345,29 @@ class Solution { } ``` +```swift +class Solution { + func findTargetSumWays(_ nums: [Int], _ target: Int) -> Int { + let totalSum = nums.reduce(0, +) + var dp = Array(repeating: Array(repeating: Int.min, count: 2 * totalSum + 1), count: nums.count) + + func backtrack(_ i: Int, _ total: Int) -> Int { + if i == nums.count { + return total == target ? 1 : 0 + } + if dp[i][total + totalSum] != Int.min { + return dp[i][total + totalSum] + } + dp[i][total + totalSum] = backtrack(i + 1, total + nums[i]) + + backtrack(i + 1, total - nums[i]) + return dp[i][total + totalSum] + } + + return backtrack(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -502,6 +539,24 @@ class Solution { } ``` +```swift +class Solution { + func findTargetSumWays(_ nums: [Int], _ target: Int) -> Int { + let n = nums.count + var dp = Array(repeating: [Int: Int](), count: n + 1) + dp[0][0] = 1 + + for i in 0.. Int { + var dp = [0: 1] + + for num in nums { + var nextDp = [Int: Int]() + for (total, count) in dp { + nextDp[total + num, default: 0] += count + nextDp[total - num, default: 0] += count + } + dp = nextDp + } + return dp[target, default: 0] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/task-scheduling.md b/articles/task-scheduling.md index d6718ba3f..03e752212 100644 --- a/articles/task-scheduling.md +++ b/articles/task-scheduling.md @@ -330,6 +330,50 @@ class Solution { } ``` +```swift +class Solution { + func leastInterval(_ tasks: [Character], _ n: Int) -> Int { + var count = [Int](repeating: 0, count: 26) + for task in tasks { + count[Int(task.asciiValue! - Character("A").asciiValue!)] += 1 + } + + var arr = [(Int, Int)]() + for i in 0..<26 { + if count[i] > 0 { + arr.append((count[i], i)) + } + } + + var time = 0 + var processed = [Int]() + + while !arr.isEmpty { + var maxi = -1 + for i in 0.. Int { + var count = [Character: Int]() + for task in tasks { + count[task, default: 0] += 1 + } + + var maxHeap = Heap(Array(count.values)) + var time = 0 + var queue = Deque<(Int, Int)>() + + while !maxHeap.isEmpty || !queue.isEmpty { + time += 1 + if maxHeap.isEmpty { + time = queue.first!.1 + } else { + let cnt = maxHeap.popMax()! - 1 + if cnt > 0 { + queue.append((cnt, time + n)) + } + } + if let front = queue.first, front.1 == time { + maxHeap.insert(front.0) + queue.removeFirst() + } + } + + return time + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -775,6 +852,27 @@ class Solution { } ``` +```swift +class Solution { + func leastInterval(_ tasks: [Character], _ n: Int) -> Int { + var count = [Int](repeating: 0, count: 26) + for task in tasks { + count[Int(task.asciiValue! - Character("A").asciiValue!)] += 1 + } + + count.sort() + let maxf = count[25] + var idle = (maxf - 1) * n + + for i in stride(from: 24, through: 0, by: -1) { + idle -= min(maxf - 1, count[i]) + } + + return max(0, idle) + tasks.count + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -951,6 +1049,28 @@ class Solution { } ``` +```swift +class Solution { + func leastInterval(_ tasks: [Character], _ n: Int) -> Int { + var count = [Int](repeating: 0, count: 26) + for task in tasks { + count[Int(task.asciiValue! - Character("A").asciiValue!)] += 1 + } + + let maxf = count.max()! + var maxCount = 0 + for i in count { + if i == maxf { + maxCount += 1 + } + } + + let time = (maxf - 1) * (n + 1) + maxCount + return max(tasks.count, time) + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/three-integer-sum.md b/articles/three-integer-sum.md index 74afca85c..18b4b76b7 100644 --- a/articles/three-integer-sum.md +++ b/articles/three-integer-sum.md @@ -145,6 +145,27 @@ class Solution { } ``` +```swift +class Solution { + func threeSum(_ nums: [Int]) -> [[Int]] { + var res = Set<[Int]>() + let nums = nums.sorted() + + for i in 0.. [[Int]] { + var nums = nums.sorted() + var count = [Int: Int]() + for num in nums { + count[num, default: 0] += 1 + } + + var res = [[Int]]() + for i in 0.. 0 && nums[i] == nums[i - 1] { + continue + } + + for j in (i + 1).. i + 1 && nums[j] == nums[j - 1] { + continue + } + let target = -(nums[i] + nums[j]) + if let cnt = count[target], cnt > 0 { + res.append([nums[i], nums[j], target]) + } + } + + for j in (i + 1).. [[Int]] { + var res = [[Int]]() + var nums = nums.sorted() + + for i in 0.. 0 { + break + } + if i > 0 && a == nums[i - 1] { + continue + } + + var l = i + 1, r = nums.count - 1 + while l < r { + let threeSum = a + nums[l] + nums[r] + if threeSum > 0 { + r -= 1 + } else if threeSum < 0 { + l += 1 + } else { + res.append([a, nums[l], nums[r]]) + l += 1 + r -= 1 + while l < r && nums[l] == nums[l - 1] { + l += 1 + } + } + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity * Time complexity: $O(n ^ 2)$ -* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. \ No newline at end of file +* Space complexity: + * $O(1)$ or $O(n)$ extra space depending on the sorting algorithm. + * $O(m)$ space for the output list. + +> Where $m$ is the number of triplets and $n$ is the length of the given array. \ No newline at end of file diff --git a/articles/time-based-key-value-store.md b/articles/time-based-key-value-store.md index bfdc75b3e..8fc87e0e5 100644 --- a/articles/time-based-key-value-store.md +++ b/articles/time-based-key-value-store.md @@ -244,6 +244,40 @@ class TimeMap() { } ``` +```swift +class TimeMap { + private var keyStore: [String: [Int: [String]]] + + init() { + self.keyStore = [:] + } + + func set(_ key: String, _ value: String, _ timestamp: Int) { + if keyStore[key] == nil { + keyStore[key] = [:] + } + if keyStore[key]![timestamp] == nil { + keyStore[key]![timestamp] = [] + } + keyStore[key]![timestamp]!.append(value) + } + + func get(_ key: String, _ timestamp: Int) -> String { + guard let timeMap = keyStore[key] else { + return "" + } + + var seen = 0 + for time in timeMap.keys { + if time <= timestamp { + seen = max(seen, time) + } + } + return seen == 0 ? "" : timeMap[seen]!.last! + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -458,6 +492,44 @@ class TimeMap() { } ``` +```swift +class TimeMap { + private var m: [String: [(Int, String)]] + + init() { + self.m = [:] + } + + func set(_ key: String, _ value: String, _ timestamp: Int) { + if m[key] == nil { + m[key] = [] + } + m[key]!.append((timestamp, value)) + } + + func get(_ key: String, _ timestamp: Int) -> String { + guard let timestamps = m[key] else { + return "" + } + + var l = 0, r = timestamps.count - 1 + var res = "" + + while l <= r { + let mid = (l + r) / 2 + if timestamps[mid].0 <= timestamp { + res = timestamps[mid].1 + l = mid + 1 + } else { + r = mid - 1 + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -739,6 +811,44 @@ class TimeMap() { } ``` +```swift +class TimeMap { + private var keyStore: [String: [(String, Int)]] + + init() { + self.keyStore = [:] + } + + func set(_ key: String, _ value: String, _ timestamp: Int) { + if keyStore[key] == nil { + keyStore[key] = [] + } + keyStore[key]!.append((value, timestamp)) + } + + func get(_ key: String, _ timestamp: Int) -> String { + guard let values = keyStore[key] else { + return "" + } + + var res = "" + var l = 0, r = values.count - 1 + + while l <= r { + let m = (l + r) / 2 + if values[m].1 <= timestamp { + res = values[m].0 + l = m + 1 + } else { + r = m - 1 + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/top-k-elements-in-list.md b/articles/top-k-elements-in-list.md index ae16871e1..7bca2df74 100644 --- a/articles/top-k-elements-in-list.md +++ b/articles/top-k-elements-in-list.md @@ -156,6 +156,30 @@ class Solution { } ``` +```swift +class Solution { + func topKFrequent(_ nums: [Int], _ k: Int) -> [Int] { + var count = [Int: Int]() + for num in nums { + count[num, default: 0] += 1 + } + + var arr = [(Int, Int)]() + for (num, cnt) in count { + arr.append((cnt, num)) + } + arr.sort { $0.0 < $1.0 } + + var res = [Int]() + while res.count < k { + res.append(arr.removeLast().1) + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -165,7 +189,7 @@ class Solution { --- -## 2. Heap +## 2. Min-Heap ::tabs-start @@ -352,6 +376,41 @@ class Solution { } ``` +```swift +struct NumFreq: Comparable { + let num: Int + let freq: Int + + static func < (lhs: NumFreq, rhs: NumFreq) -> Bool { + return lhs.freq < rhs.freq + } +} + +class Solution { + func topKFrequent(_ nums: [Int], _ k: Int) -> [Int] { + var count = [Int: Int]() + for num in nums { + count[num, default: 0] += 1 + } + + var heap: Heap = [] + for (num, freq) in count { + heap.insert(NumFreq(num: num, freq: freq)) + if heap.count > k { + heap.removeMin() + } + } + + var res = [Int]() + while !heap.isEmpty { + res.append(heap.removeMin().num) + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -564,6 +623,35 @@ class Solution { } ``` +```swift +class Solution { + func topKFrequent(_ nums: [Int], _ k: Int) -> [Int] { + var count = [Int: Int]() + var freq = [[Int]](repeating: [], count: nums.count + 1) + + for num in nums { + count[num, default: 0] += 1 + } + + for (num, cnt) in count { + freq[cnt].append(num) + } + + var res = [Int]() + for i in stride(from: freq.count - 1, through: 1, by: -1) { + for num in freq[i] { + res.append(num) + if res.count == k { + return res + } + } + } + + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/trapping-rain-water.md b/articles/trapping-rain-water.md index 73635a85d..4e8f600b8 100644 --- a/articles/trapping-rain-water.md +++ b/articles/trapping-rain-water.md @@ -197,6 +197,33 @@ class Solution { } ``` +```swift +class Solution { + func trap(_ height: [Int]) -> Int { + if height.isEmpty { + return 0 + } + let n = height.count + var res = 0 + + for i in 0.. Int { + let n = height.count + if n == 0 { + return 0 + } + + var leftMax = [Int](repeating: 0, count: n) + var rightMax = [Int](repeating: 0, count: n) + + leftMax[0] = height[0] + for i in 1.. Int { + if height.isEmpty { + return 0 + } + var stack = [Int]() + var res = 0 + + for i in 0..= height[stack.last!] { + let mid = height[stack.removeLast()] + if !stack.isEmpty { + let right = height[i] + let left = height[stack.last!] + let h = min(right, left) - mid + let w = i - stack.last! - 1 + res += h * w + } + } + stack.append(i) + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -852,6 +936,33 @@ class Solution { } ``` +```swift +class Solution { + func trap(_ height: [Int]) -> Int { + if height.isEmpty { + return 0 + } + + var l = 0, r = height.count - 1 + var leftMax = height[l], rightMax = height[r] + var res = 0 + + while l < r { + if leftMax < rightMax { + l += 1 + leftMax = max(leftMax, height[l]) + res += leftMax - height[l] + } else { + r -= 1 + rightMax = max(rightMax, height[r]) + res += rightMax - height[r] + } + } + return res + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/two-integer-sum-ii.md b/articles/two-integer-sum-ii.md index 8aea74e9d..f63e71a60 100644 --- a/articles/two-integer-sum-ii.md +++ b/articles/two-integer-sum-ii.md @@ -106,6 +106,21 @@ class Solution { } ``` +```swift +class Solution { + func twoSum(_ numbers: [Int], _ target: Int) -> [Int] { + for i in 0.. [Int] { + for i in 0.. [Int] { + var mp = [Int: Int]() + + for i in 0.. [Int] { + var l = 0, r = numbers.count - 1 + + while l < r { + let curSum = numbers[l] + numbers[r] + + if curSum > target { + r -= 1 + } else if curSum < target { + l += 1 + } else { + return [l + 1, r + 1] + } + } + return [] + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/two-integer-sum.md b/articles/two-integer-sum.md index 5b08e079d..9fba0afdc 100644 --- a/articles/two-integer-sum.md +++ b/articles/two-integer-sum.md @@ -106,6 +106,21 @@ class Solution { } ``` +```swift +class Solution { + func twoSum(_ nums: [Int], _ target: Int) -> [Int] { + for i in 0.. [Int] { + var A = [(Int, Int)]() + for (i, num) in nums.enumerated() { + A.append((num, i)) + } + + A.sort { $0.0 < $1.0 } + var i = 0 + var j = nums.count - 1 + + while i < j { + let cur = A[i].0 + A[j].0 + if cur == target { + return [min(A[i].1, A[j].1), + max(A[i].1, A[j].1)] + } else if cur < target { + i += 1 + } else { + j -= 1 + } + } + return [] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -469,6 +512,27 @@ class Solution { } ``` +```swift +class Solution { + func twoSum(_ nums: [Int], _ target: Int) -> [Int] { + var indices = [Int: Int]() // val -> index + + for (i, n) in nums.enumerated() { + indices[n] = i + } + + for (i, n) in nums.enumerated() { + let diff = target - n + if let j = indices[diff], j != i { + return [i, j] + } + } + + return [] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -607,6 +671,24 @@ class Solution { } ``` +```swift +class Solution { + func twoSum(_ nums: [Int], _ target: Int) -> [Int] { + var prevMap = [Int: Int]() // val -> index + + for (i, n) in nums.enumerated() { + let diff = target - n + if let index = prevMap[diff] { + return [index, i] + } + prevMap[n] = i + } + + return [] + } +} +``` + ::tabs-end ### Time & Space Complexity 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/valid-binary-search-tree.md b/articles/valid-binary-search-tree.md index fd885ddfc..3b076e3c7 100644 --- a/articles/valid-binary-search-tree.md +++ b/articles/valid-binary-search-tree.md @@ -316,6 +316,44 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func isValidBST(_ root: TreeNode?) -> Bool { + guard let root = root else { return true } + if !isValid(root.left, root.val, { $0 < $1 }) || + !isValid(root.right, root.val, { $0 > $1 }) { + return false + } + + return isValidBST(root.left) && isValidBST(root.right) + } + + private func isValid(_ root: TreeNode?, _ limit: Int, _ check: (Int, Int) -> Bool) -> Bool { + guard let root = root else { return true } + if !check(root.val, limit) { + return false + } + + return isValid(root.left, limit, check) && isValid(root.right, limit, check) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -550,6 +588,37 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func isValidBST(_ root: TreeNode?) -> Bool { + return valid(root, Int.min, Int.max) + } + + private func valid(_ node: TreeNode?, _ left: Int, _ right: Int) -> Bool { + guard let node = node else { return true } + if !(left < node.val && node.val < right) { + return false + } + return valid(node.left, left, node.val) && valid(node.right, node.val, right) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -858,6 +927,48 @@ class Solution { } ``` +```swift +/** + * Definition for a binary tree node. + * public class TreeNode { + * public var val: Int + * public var left: TreeNode? + * public var right: TreeNode? + * public init() { self.val = 0; self.left = nil; self.right = nil; } + * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } + * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { + * self.val = val + * self.left = left + * self.right = right + * } + * } + */ +class Solution { + func isValidBST(_ root: TreeNode?) -> Bool { + guard let root = root else { return true } + + var q = Deque<(TreeNode, Int, Int)>() + q.append((root, Int.min, Int.max)) + + while !q.isEmpty { + let (node, left, right) = q.popFirst()! + + if !(left < node.val && node.val < right) { + return false + } + + if let leftNode = node.left { + q.append((leftNode, left, node.val)) + } + if let rightNode = node.right { + q.append((rightNode, node.val, right)) + } + } + return true + } +} +``` + ::tabs-end ### Time & Space Complexity 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-parenthesis-string.md b/articles/valid-parenthesis-string.md index 84c0422d8..c412ad605 100644 --- a/articles/valid-parenthesis-string.md +++ b/articles/valid-parenthesis-string.md @@ -148,7 +148,52 @@ func checkValidString(s string) bool { ``` ```kotlin +class Solution { + fun checkValidString(s: String): Boolean { + + fun dfs(i: Int, open: Int): Boolean { + if (open < 0) { + return false + } + if (i == s.length) { + return open == 0 + } + + return when (s[i]) { + '(' -> dfs(i + 1, open + 1) + ')' -> dfs(i + 1, open - 1) + else -> dfs(i + 1, open) || dfs(i + 1, open + 1) || dfs(i + 1, open - 1) + } + } + + return dfs(0, 0) + } +} +``` + +```swift +class Solution { + func checkValidString(_ s: String) -> Bool { + let chars = Array(s) + + func dfs(_ i: Int, _ open: Int) -> Bool { + if open < 0 { return false } + if i == chars.count { return open == 0 } + + if chars[i] == "(" { + return dfs(i + 1, open + 1) + } else if chars[i] == ")" { + return dfs(i + 1, open - 1) + } else { + return dfs(i + 1, open) || + dfs(i + 1, open + 1) || + dfs(i + 1, open - 1) + } + } + return dfs(0, 0) + } +} ``` ::tabs-end @@ -397,6 +442,47 @@ class Solution { } ``` +```swift +class Solution { + func checkValidString(_ s: String) -> Bool { + let n = s.count + let sArr = Array(s) + var memo = Array( + repeating: Array(repeating: nil, count: n + 1), + count: n + 1 + ) + + func dfs(_ i: Int, _ open: Int) -> Bool { + if open < 0 { + return false + } + if i == n { + return open == 0 + } + if let memoized = memo[i][open] { + return memoized + } + + let result: Bool + if sArr[i] == "(" { + result = dfs(i + 1, open + 1) + } else if sArr[i] == ")" { + result = dfs(i + 1, open - 1) + } else { + result = dfs(i + 1, open) || + dfs(i + 1, open + 1) || + dfs(i + 1, open - 1) + } + + memo[i][open] = result + return result + } + + return dfs(0, 0) + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -620,6 +706,40 @@ class Solution { } ``` +```swift +class Solution { + func checkValidString(_ s: String) -> Bool { + let n = s.count + var dp = Array(repeating: Array(repeating: false, count: n + 1), count: n + 1) + dp[n][0] = true + + let chars = Array(s) + + for i in stride(from: n - 1, through: 0, by: -1) { + for open in 0.. 0 { + res = res || dp[i + 1][open - 1] + } + res = res || dp[i + 1][open] + } else { + if chars[i] == "(" { + res = res || dp[i + 1][open + 1] + } else if open > 0 { + res = res || dp[i + 1][open - 1] + } + } + dp[i][open] = res + } + } + + return dp[0][0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -815,6 +935,34 @@ class Solution { } ``` +```swift +class Solution { + func checkValidString(_ s: String) -> Bool { + let n = s.count + var dp = Array(repeating: false, count: n + 1) + dp[0] = true + + let chars = Array(s) + + for i in stride(from: n - 1, through: 0, by: -1) { + var new_dp = Array(repeating: false, count: n + 1) + for open in 0.. 0 && dp[open - 1]) || dp[open] + } else if chars[i] == "(" { + new_dp[open] = dp[open + 1] + } else if open > 0 { + new_dp[open] = dp[open - 1] + } + } + dp = new_dp + } + + return dp[0] + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1034,6 +1182,44 @@ class Solution { } ``` +```swift +class Solution { + func checkValidString(_ s: String) -> Bool { + var left = [Int]() + var star = [Int]() + + let chars = Array(s) + + for (i, ch) in chars.enumerated() { + if ch == "(" { + left.append(i) + } else if ch == "*" { + star.append(i) + } else { + if left.isEmpty && star.isEmpty { + return false + } + if !left.isEmpty { + left.popLast() + } else { + star.popLast() + } + } + } + + while !left.isEmpty && !star.isEmpty { + if left.last! > star.last! { + return false + } + left.popLast() + star.popLast() + } + + return left.isEmpty + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -1236,6 +1422,35 @@ class Solution { } ``` +```swift +class Solution { + func checkValidString(_ s: String) -> Bool { + var leftMin = 0 + var leftMax = 0 + + for c in s { + if c == "(" { + leftMin += 1 + leftMax += 1 + } else if c == ")" { + leftMin -= 1 + leftMax -= 1 + } else { + leftMin -= 1 + leftMax += 1 + } + if leftMax < 0 { + return false + } + if leftMin < 0 { + leftMin = 0 + } + } + return leftMin == 0 + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/valid-sudoku.md b/articles/valid-sudoku.md index 14c8dc735..74fb5deda 100644 --- a/articles/valid-sudoku.md +++ b/articles/valid-sudoku.md @@ -284,6 +284,45 @@ class Solution { } ``` +```swift +class Solution { + func isValidSudoku(_ board: [[Character]]) -> Bool { + for row in 0..<9 { + var seen = Set() + for i in 0..<9 { + if board[row][i] == "." { continue } + if seen.contains(board[row][i]) { return false } + seen.insert(board[row][i]) + } + } + + for col in 0..<9 { + var seen = Set() + for i in 0..<9 { + if board[i][col] == "." { continue } + if seen.contains(board[i][col]) { return false } + seen.insert(board[i][col]) + } + } + + for square in 0..<9 { + var seen = Set() + for i in 0..<3 { + for j in 0..<3 { + let row = (square / 3) * 3 + i + let col = (square % 3) * 3 + j + if board[row][col] == "." { continue } + if seen.contains(board[row][col]) { return false } + seen.insert(board[row][col]) + } + } + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -510,6 +549,36 @@ class Solution { } ``` +```swift +class Solution { + func isValidSudoku(_ board: [[Character]]) -> Bool { + var cols = [Int: Set]() + var rows = [Int: Set]() + var squares = [String: Set]() + + for r in 0..<9 { + for c in 0..<9 { + if board[r][c] == "." { continue } + + let squareKey = "\(r / 3),\(c / 3)" + + if rows[r]?.contains(board[r][c]) == true || + cols[c]?.contains(board[r][c]) == true || + squares[squareKey]?.contains(board[r][c]) == true { + return false + } + + rows[r, default: []].insert(board[r][c]) + cols[c, default: []].insert(board[r][c]) + squares[squareKey, default: []].insert(board[r][c]) + } + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -725,6 +794,35 @@ class Solution { } ``` +```swift +class Solution { + func isValidSudoku(_ board: [[Character]]) -> Bool { + var rows = [Int](repeating: 0, count: 9) + var cols = [Int](repeating: 0, count: 9) + var squares = [Int](repeating: 0, count: 9) + + for r in 0..<9 { + for c in 0..<9 { + if board[r][c] == "." { continue } + + let val = Int(board[r][c].asciiValue! - Character("0").asciiValue!) + let bitmask = 1 << (val - 1) + + if (rows[r] & bitmask) != 0 { return false } + if (cols[c] & bitmask) != 0 { return false } + if (squares[(r / 3) * 3 + (c / 3)] & bitmask) != 0 { return false } + + rows[r] |= bitmask + cols[c] |= bitmask + squares[(r / 3) * 3 + (c / 3)] |= bitmask + } + } + + return true + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/valid-tree.md b/articles/valid-tree.md index a343b676e..7266d9836 100644 --- a/articles/valid-tree.md +++ b/articles/valid-tree.md @@ -266,6 +266,44 @@ class Solution { } ``` +```swift +class Solution { + func validTree(_ n: Int, _ edges: [[Int]]) -> Bool { + if edges.count > (n - 1) { + return false + } + + var adj = Array(repeating: [Int](), count: n) + for edge in edges { + let u = edge[0] + let v = edge[1] + adj[u].append(v) + adj[v].append(u) + } + + var visited = Set() + + func dfs(_ node: Int, _ parent: Int) -> Bool { + if visited.contains(node) { + return false + } + visited.insert(node) + for nei in adj[node] { + if nei == parent { + continue + } + if !dfs(nei, node) { + return false + } + } + return true + } + + return dfs(0, -1) && visited.count == n + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -537,6 +575,45 @@ class Solution { } ``` +```swift +class Solution { + func validTree(_ n: Int, _ edges: [[Int]]) -> Bool { + if edges.count > n - 1 { + return false + } + + var adj = [[Int]](repeating: [], count: n) + for edge in edges { + let u = edge[0] + let v = edge[1] + adj[u].append(v) + adj[v].append(u) + } + + var visit = Set() + var q = Deque<(Int, Int)>() // (current node, parent node) + q.append((0, -1)) + visit.insert(0) + + while !q.isEmpty { + let (node, parent) = q.removeFirst() + for nei in adj[node] { + if nei == parent { + continue + } + if visit.contains(nei) { + return false + } + visit.insert(nei) + q.append((nei, node)) + } + } + + return visit.count == n + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -593,7 +670,7 @@ class Solution: ``` ```java -public class DSU { +class DSU { int[] Parent, Size; int comps; @@ -932,6 +1009,65 @@ class Solution { } ``` +```swift +class DSU { + var comps: Int + var parent: [Int] + var size: [Int] + + init(_ n: Int) { + comps = n + parent = Array(0.. Int { + if parent[node] != node { + parent[node] = find(parent[node]) + } + return parent[node] + } + + func union(_ u: Int, _ v: Int) -> Bool { + let pu = find(u) + let pv = find(v) + if pu == pv { + return false + } + comps -= 1 + if size[pu] < size[pv] { + parent[pu] = pv + size[pv] += size[pu] + } else { + parent[pv] = pu + size[pu] += size[pv] + } + return true + } + + func components() -> Int { + return comps + } +} + +class Solution { + func validTree(_ n: Int, _ edges: [[Int]]) -> Bool { + if edges.count > n - 1 { + return false + } + + let dsu = DSU(n) + for edge in edges { + let u = edge[0], v = edge[1] + if !dsu.union(u, v) { + return false + } + } + return dsu.components() == 1 + } +} +``` + ::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 diff --git a/articles/validate-parentheses.md b/articles/validate-parentheses.md index fc97eac24..a7e649a78 100644 --- a/articles/validate-parentheses.md +++ b/articles/validate-parentheses.md @@ -105,6 +105,20 @@ class Solution { } ``` +```swift +class Solution { + func isValid(_ s: String) -> Bool { + var str = s + while str.contains("()") || str.contains("{}") || str.contains("[]") { + str = str.replacingOccurrences(of: "()", with: "") + str = str.replacingOccurrences(of: "{}", with: "") + str = str.replacingOccurrences(of: "[]", with: "") + } + return str.isEmpty + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -291,6 +305,29 @@ class Solution { } ``` +```swift +class Solution { + func isValid(_ s: String) -> Bool { + var stack = [Character]() + let closeToOpen: [Character: Character] = [")": "(", "]": "[", "}": "{"] + + for c in s { + if let open = closeToOpen[c] { + if !stack.isEmpty && stack.last! == open { + stack.popLast() + } else { + return false + } + } else { + stack.append(c) + } + } + + return stack.isEmpty + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/verifying-an-alien-dictionary.md b/articles/verifying-an-alien-dictionary.md index 7ab6ac58d..86694cf0a 100644 --- a/articles/verifying-an-alien-dictionary.md +++ b/articles/verifying-an-alien-dictionary.md @@ -84,6 +84,35 @@ class Solution { } ``` +```csharp +public class Solution { + public bool IsAlienSorted(string[] words, string order) { + int[] orderIndex = new int[26]; + for (int i = 0; i < order.Length; i++) { + orderIndex[order[i] - 'a'] = i; + } + + string[] sortedWords = (string[])words.Clone(); + Array.Sort(sortedWords, (w1, w2) => { + for (int i = 0; i < Math.Min(w1.Length, w2.Length); i++) { + if (w1[i] != w2[i]) { + return orderIndex[w1[i] - 'a'] - orderIndex[w2[i] - 'a']; + } + } + return w1.Length - w2.Length; + }); + + for (int i = 0; i < words.Length; i++) { + if (!words[i].Equals(sortedWords[i])) { + return false; + } + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -201,6 +230,37 @@ class Solution { } ``` +```csharp +public class Solution { + public bool IsAlienSorted(string[] words, string order) { + Dictionary orderIndex = new Dictionary(); + for (int i = 0; i < order.Length; i++) { + orderIndex[order[i]] = i; + } + + for (int i = 0; i < words.Length - 1; i++) { + string w1 = words[i]; + string w2 = words[i + 1]; + + for (int j = 0; j < w1.Length; j++) { + if (j == w2.Length) { + return false; + } + + if (w1[j] != w2[j]) { + if (orderIndex[w1[j]] > orderIndex[w2[j]]) { + return false; + } + break; + } + } + } + + return true; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/word-break-ii.md b/articles/word-break-ii.md index c075d2b67..45660e5f9 100644 --- a/articles/word-break-ii.md +++ b/articles/word-break-ii.md @@ -131,6 +131,35 @@ class Solution { } ``` +```csharp +public class Solution { + public List WordBreak(string s, List wordDict) { + HashSet wordSet = new HashSet(wordDict); + List res = new List(); + List cur = new List(); + + void Backtrack(int i) { + if (i == s.Length) { + res.Add(string.Join(" ", cur)); + return; + } + + for (int j = i; j < s.Length; j++) { + string word = s.Substring(i, j - i + 1); + if (wordSet.Contains(word)) { + cur.Add(word); + Backtrack(j + 1); + cur.RemoveAt(cur.Count - 1); + } + } + } + + Backtrack(0); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -401,6 +430,66 @@ class Solution { } ``` +```csharp +public class TrieNode { + public Dictionary children = new Dictionary(); + public bool isWord = false; +} + +public class Trie { + public TrieNode root = new TrieNode(); + + public void AddWord(string word) { + TrieNode curr = root; + foreach (char c in word) { + if (!curr.children.ContainsKey(c)) { + curr.children[c] = new TrieNode(); + } + curr = curr.children[c]; + } + curr.isWord = true; + } +} + +public class Solution { + public List WordBreak(string s, List wordDict) { + Trie trie = new Trie(); + foreach (string word in wordDict) { + trie.AddWord(word); + } + + List res = new List(); + + void Backtrack(int index, List path) { + if (index == s.Length) { + res.Add(string.Join(" ", path)); + return; + } + + TrieNode node = trie.root; + StringBuilder word = new StringBuilder(); + + for (int i = index; i < s.Length; i++) { + char c = s[i]; + if (!node.children.ContainsKey(c)) break; + + word.Append(c); + node = node.children[c]; + + if (node.isWord) { + path.Add(word.ToString()); + Backtrack(i + 1, path); + path.RemoveAt(path.Count - 1); + } + } + } + + Backtrack(0, new List()); + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -561,6 +650,40 @@ class Solution { } ``` +```csharp +public class Solution { + public List WordBreak(string s, List wordDictList) { + HashSet wordDict = new HashSet(wordDictList); + Dictionary> cache = new Dictionary>(); + + List Backtrack(int i) { + if (i == s.Length) return new List { "" }; + if (cache.ContainsKey(i)) return cache[i]; + + List res = new List(); + for (int j = i; j < s.Length; j++) { + string w = s.Substring(i, j - i + 1); + if (!wordDict.Contains(w)) continue; + + List substrings = Backtrack(j + 1); + foreach (string substr in substrings) { + string sentence = w; + if (!string.IsNullOrEmpty(substr)) { + sentence += " " + substr; + } + res.Add(sentence); + } + } + + cache[i] = res; + return res; + } + + return Backtrack(0); + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -676,6 +799,34 @@ class Solution { } ``` +```csharp +public class Solution { + public List WordBreak(string s, List wordDictList) { + HashSet wordSet = new HashSet(wordDictList); + int n = s.Length; + List[] dp = new List[n + 1]; + for (int i = 0; i <= n; i++) { + dp[i] = new List(); + } + dp[0].Add(""); + + for (int i = 1; i <= n; i++) { + for (int j = 0; j < i; j++) { + string word = s.Substring(j, i - j); + if (wordSet.Contains(word)) { + foreach (string sentence in dp[j]) { + string space = string.IsNullOrEmpty(sentence) ? "" : " "; + dp[i].Add(sentence + space + word); + } + } + } + } + + return dp[n]; + } +} +``` + ::tabs-end ### Time & Space Complexity @@ -965,6 +1116,68 @@ class Solution { } ``` +```csharp +public class TrieNode { + public Dictionary Children = new Dictionary(); + public bool IsWord = false; +} + +public class Trie { + public TrieNode Root = new TrieNode(); + + public void AddWord(string word) { + TrieNode curr = Root; + foreach (char c in word) { + if (!curr.Children.ContainsKey(c)) { + curr.Children[c] = new TrieNode(); + } + curr = curr.Children[c]; + } + curr.IsWord = true; + } +} + +public class Solution { + private Dictionary> cache = new Dictionary>(); + + public List WordBreak(string s, List wordDict) { + Trie trie = new Trie(); + foreach (string word in wordDict) { + trie.AddWord(word); + } + return Backtrack(0, s, trie.Root, trie); + } + + private List Backtrack(int index, string s, TrieNode root, Trie trie) { + if (index == s.Length) return new List { "" }; + if (cache.ContainsKey(index)) return cache[index]; + + List res = new List(); + TrieNode curr = root; + + for (int i = index; i < s.Length; i++) { + char c = s[i]; + if (!curr.Children.ContainsKey(c)) break; + + curr = curr.Children[c]; + if (curr.IsWord) { + List suffixes = Backtrack(i + 1, s, root, trie); + foreach (string suffix in suffixes) { + if (suffix == "") { + res.Add(s.Substring(index, i - index + 1)); + } else { + res.Add(s.Substring(index, i - index + 1) + " " + suffix); + } + } + } + } + + cache[index] = res; + return res; + } +} +``` + ::tabs-end ### Time & Space Complexity diff --git a/articles/word-break.md b/articles/word-break.md index 908708670..acc8366d3 100644 --- a/articles/word-break.md +++ b/articles/word-break.md @@ -176,6 +176,32 @@ class Solution { } ``` +```swift +class Solution { + func wordBreak(_ s: String, _ wordDict: [String]) -> Bool { + let chars = Array(s) + + func dfs(_ i: Int) -> Bool { + if i == chars.count { + return true + } + + for w in wordDict { + if i + w.count <= chars.count, + String(chars[i.. Bool { + let wordSet = Set(wordDict) + let chars = Array(s) + + func dfs(_ i: Int) -> Bool { + if i == chars.count { + return true + } + + for j in i.. Bool { + var memo = [Int: Bool]() + memo[s.count] = true + let chars = Array(s) + + func dfs(_ i: Int) -> Bool { + if let cached = memo[i] { + return cached + } + + for w in wordDict { + if i + w.count <= chars.count, + String(chars[i.. Bool { + let wordSet = Set(wordDict) + var maxLen = 0 + for w in wordDict { + maxLen = max(maxLen, w.count) + } + + var memo = [Int: Bool]() + let chars = Array(s) + + func dfs(_ i: Int) -> Bool { + if let cached = memo[i] { + return cached + } + if i == chars.count { + return true + } + for j in i.. Bool { + var dp = Array(repeating: false, count: s.count + 1) + dp[s.count] = true + let chars = Array(s) + + for i in stride(from: s.count - 1, through: 0, by: -1) { + for w in wordDict { + if i + w.count <= chars.count, String(chars[i.. children; boolean isWord; @@ -1096,7 +1237,7 @@ public class TrieNode { } } -public class Trie { +class Trie { TrieNode root; public Trie() { @@ -1497,6 +1638,70 @@ class Solution { } ``` +```swift +class TrieNode { + var children = [Character: TrieNode]() + var isWord = false +} + +class Trie { + private let root = TrieNode() + + func insert(_ word: String) { + var node = root + for char in word { + if node.children[char] == nil { + node.children[char] = TrieNode() + } + node = node.children[char]! + } + node.isWord = true + } + + func search(_ s: [Character], _ i: Int, _ j: Int) -> Bool { + var node = root + for idx in i...j { + if node.children[s[idx]] == nil { + return false + } + node = node.children[s[idx]]! + } + return node.isWord + } +} + +class Solution { + func wordBreak(_ s: String, _ wordDict: [String]) -> Bool { + let trie = Trie() + for word in wordDict { + trie.insert(word) + } + + var dp = Array(repeating: false, count: s.count + 1) + dp[s.count] = true + let chars = Array(s) + + var maxLen = 0 + for word in wordDict { + maxLen = max(maxLen, word.count) + } + + for i in stride(from: s.count, through: 0, by: -1) { + for j in i.. Int { + if !wordList.contains(endWord) || beginWord == endWord { + return 0 + } + + let n = wordList.count + let m = wordList[0].count + var adj = [[Int]](repeating: [], count: n) + var mp = [String: Int]() + + for i in 0..() + var res = 1 + var visit = Set() + let beginChars = Array(beginWord) + + for i in 0.. Int { + if !wordList.contains(endWord) || beginWord == endWord { + return 0 + } + + var words = Set(wordList) + var queue = Deque() + queue.append(beginWord) + var res = 0 + + while !queue.isEmpty { + res += 1 + for _ in 0.. Int { + if !wordList.contains(endWord) { + return 0 + } + + var nei = [String: [String]]() + var wordList = wordList + wordList.append(beginWord) + + for word in wordList { + let wordArray = Array(word) + for j in 0.. = [beginWord] + var queue = Deque() + queue.append(beginWord) + var res = 1 + + while !queue.isEmpty { + for _ in 0.. Int { + if !wordList.contains(endWord) || beginWord == endWord { + return 0 + } + + let m = wordList[0].count + var wordSet = Set(wordList) + var qb = Deque([beginWord]) + var qe = Deque([endWord]) + var fromBegin = [beginWord: 1] + var fromEnd = [endWord: 1] + + while !qb.isEmpty && !qe.isEmpty { + if qb.count > qe.count { + swap(&qb, &qe) + swap(&fromBegin, &fromEnd) + } + + for _ in 0.. 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 diff --git a/hints/burst-balloons.md b/hints/burst-balloons.md new file mode 100644 index 000000000..c553a4f8e --- /dev/null +++ b/hints/burst-balloons.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n ^ 3) time and O(n ^ 2) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ Try to simulate the process recursively by passing the array to the recursive function. At each step, iterate through the array, pop an element, and recursively apply the same process to the two subarrays on both sides of the popped element, returning the maximum result from all recursive paths. This approach is exponential. Can you think of a way to optimize it? Maybe you should consider observing the subproblems instead of modifying the array. +

+
+ +
+
+ Hint 2 +

+ Instead of passing the array, we can pass the range of indices l and r that need to be processed. We pad the input array with 1s on both sides for easier computation, but l and r represent the first and last indices of the original input array. Can you think of a reverse engineering approach for popping elements? +

+
+ +
+
+ Hint 3 +

+ We determine the result by considering each element as the last one to be popped in the current range. For each element, we calculate its value by multiplying it with the elements at l - 1 and r + 1, then recursively solve the subproblems for the ranges (l, i - 1) and (i + 1, r), where i is the current element in the given range. Can you think of a way to optimize and avoid redundant calculations? +

+
+ +
+
+ Hint 4 +

+ We can use memoization to cache the results of recursive calls and avoid redundant calculations. A hash map or a 2D array can be used to store results since the recursive function parameters l and r are within the range of the input array size. +

+
\ No newline at end of file diff --git a/hints/buy-and-sell-crypto-with-cooldown.md b/hints/buy-and-sell-crypto-with-cooldown.md new file mode 100644 index 000000000..84988bd54 --- /dev/null +++ b/hints/buy-and-sell-crypto-with-cooldown.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(n) time and O(n) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ Try to think in terms of recursion and visualize it as a decision tree. Can you determine the possible decisions at each recursion step? Also, can you identify the base cases and the essential information that needs to be tracked during recursion? +

+
+ +
+
+ Hint 2 +

+ At each recursion step, we can buy only if we haven't already bought a coin, or we can sell if we own one. When buying, we subtract the coin value, and when selling, we add it. We explore all possible buying and selling options recursively, iterating through the coins from left to right using index i. For the cooldown condition, if we buy a coin, we increment the index i by two. +

+
+ +
+
+ Hint 3 +

+ We can use a boolean variable canBuy to indicate whether buying is allowed at the current recursive step. If we go out of bounds, we return 0. This approach is exponential. Can you think of a way to optimize it? +

+
+ +
+
+ Hint 4 +

+ We can use memoization to cache the results of recursive calls and avoid recalculations. A hash map or a 2D array can be used to store these results. +

+
\ No newline at end of file diff --git a/hints/coin-change-ii.md b/hints/coin-change-ii.md new file mode 100644 index 000000000..3f18a6318 --- /dev/null +++ b/hints/coin-change-ii.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(n * a) time and O(n * a) space, where n is the number of coins and a is the given amount. +

+
+ +
+
+ Hint 1 +

+ As we need to find the total number of combinations, think in terms of recursion and visualize it as a decision tree where multiple coin choices are available at each recursion step. Can you determine a way to allow picking the same coin multiple times? Maybe you should consider the decisions made at each recursion step. +

+
+ +
+
+ Hint 2 +

+ The given coins are unique. We recursively iterate through the coins array using index i, tracking the collected amount along the current path. At each step, we can either skip the current coin or pick it, ensuring the total does not exceed the target. To allow picking the same coin multiple times, we recurse with the same index but an updated amount, generating different combinations. +

+
+ +
+
+ Hint 3 +

+ If we reach the target amount, we return 1. The recursion stops if the index goes out of bounds. We count all possible ways and return the total. This approach is exponential. Can you think of a way to optimize it? Maybe you should consider an approach to avoid redundant computations. +

+
+ +
+
+ Hint 4 +

+ We can use memoization to cache the results of recursive calls and avoid redundant computations. A hash map or a 2D array can be used to store these results. +

+
\ No newline at end of file diff --git a/hints/count-paths.md b/hints/count-paths.md new file mode 100644 index 000000000..299793547 --- /dev/null +++ b/hints/count-paths.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(m * n) time and O(m * n) space, where m is the number of rows and n is the number of columns in the grid. +

+
+ +
+
+ Hint 1 +

+ Try to think in terms of recursion and visualize it as a decision tree, where we have two choices at each step. Can you determine the base condition and recurrence relation? +

+
+ +
+
+ Hint 2 +

+ We recursively traverse the grid using row i and column j. At each step, we explore both possibilities: moving down or moving right, ensuring we do not go out of bounds. If we reach the bottom-right cell, we return 1. +

+
+ +
+
+ Hint 3 +

+ This approach has exponential complexity. Can you think of a way to optimize the recursion? Maybe you should consider using a dynamic programming approach. +

+
+ +
+
+ Hint 4 +

+ We can use memoization to cache the results of recursive calls and avoid recalculations. A hash map or a 2D array can be used to store these results. +

+
\ No newline at end of file diff --git a/hints/count-squares.md b/hints/count-squares.md new file mode 100644 index 000000000..69b289bdb --- /dev/null +++ b/hints/count-squares.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(1) time for each add() call, O(n) time for each count() call, and O(n) space, where n is the total number of points. +

+
+ +
+
+ Hint 1 +

+ Initially, we can store the points in a global list for the add() call. For the count() call, a brute force approach would use three nested loops to check other points except for the query point, resulting in an O(n^3) time solution. Can you think of a better way? Maybe you should consider the observation that can be drawn from the diagonal of a square. +

+
+ +
+
+ Hint 2 +

+ In a square's diagonal, the absolute difference between the x-coordinates is equal to the absolute difference between the y-coordinates of the two endpoints, and neither difference can be zero. Using these two points, we can determine the other diagonal endpoints. +

+
+ +
+
+ Hint 3 +

+ We store points in a hash map instead of a list for O(1) lookups, treating duplicate points as one while tracking their frequencies. For the count() function, we iterate through points that, along with the query point, can form a diagonal. Let the query point be (qx, qy) and the other point be (x, y), ensuring they form a diagonal. What could be the other two points? Maybe you should consider the points forming a right-to-left diagonal, treating (qx, qy) as the top-right corner. +

+
+ +
+
+ Hint 4 +

+ The other two points are point1 (x, qy) and point2 (qx, y). For counting, we simply add count of point1 * count of point2 to the result res. +

+
\ No newline at end of file diff --git a/hints/count-subsequences.md b/hints/count-subsequences.md new file mode 100644 index 000000000..53a37dcee --- /dev/null +++ b/hints/count-subsequences.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(m * n) time and O(m * n) space, where m is the length of the string s and n is the length of the string t. +

+
+ +
+
+ Hint 1 +

+ Try to think in terms of recursion and visualize it as a decision tree, as we need to explore all subsequences of s. Can you determine the possible decisions at each recursion step? +

+
+ +
+
+ Hint 2 +

+ We recursively iterate through the strings using indices i and j for s and t, respectively. At each recursion step, we can either skip the current character of s or include it in the current path if it matches the current character of t. Can you determine the base conditions for this recursive function? +

+
+ +
+
+ Hint 3 +

+ If index j goes out of bounds, we return 1 as a valid subsequence is found. If index i goes out of bounds first, we return 0. At each recursion step, we return the sum of both paths. This approach is exponential. Can you think of a way to optimize it? +

+
+ +
+
+ Hint 4 +

+ We can use memoization to cache the results of recursive calls and avoid redundant computations. A hash map or a 2D array can be used to store these results. +

+
\ No newline at end of file diff --git a/hints/counting-bits.md b/hints/counting-bits.md new file mode 100644 index 000000000..45188a165 --- /dev/null +++ b/hints/counting-bits.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(n) space, where n is the given integer. +

+
+ +
+
+ Hint 1 +

+ A straightforward approach would be to iterate from 0 to n using i, and for each i, iterate through its bits to count the number of set bits. This would result in an O(n \log n) approach. Can you think of a better way? Maybe you should try identifying a pattern by observing the bitwise representation of consecutive numbers. +

+
+ +
+
+ Hint 2 +

+ For example, to compute set bits for 7, add 1 to the count of set bits in 3, which was previously computed by adding 1 to the count of set bits in 1. Observing the pattern, for numbers less than 4, add 1 to the count from two positions before. For numbers less than 8, add 1 to the count from four positions before. Can you derive a dynamic programming relation from this? +

+
+ +
+
+ Hint 3 +

+ We find an offset for the current number based on the number before offset positions. The dynamic programming relation is dp[i] = 1 + dp[i - offset], where dp[i] represents the number of set bits in i. The offset starts at 1 and updates when encountering a power of 2. To simplify the power of 2 check, if offset * 2 equals the current number, we update offset to the current number. +

+
\ No newline at end of file diff --git a/hints/edit-distance.md b/hints/edit-distance.md new file mode 100644 index 000000000..277fa3cbe --- /dev/null +++ b/hints/edit-distance.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(m * n) time and O(m * n) space, where m and n are the lengths of the strings word1 and word2, respectively. +

+
+ +
+
+ Hint 1 +

+ Try to think in terms of recursion and visualize it as a decision tree, as we have choices at each recursion step. Can you determine the recurrence relation and base cases? +

+
+ +
+
+ Hint 2 +

+ We recursively iterate through the strings using indices i and j for word1 and word2, respectively. If the characters at the current indices match, we increment both indices without counting an operation. Otherwise, we have three choices: insert the character at the current index of word1 (increment j), delete the current character of word1 (increment i), or replace the character at index i in word1 (increment both i and j). +

+
+ +
+
+ Hint 3 +

+ If index i goes out of bounds, we return the number of remaining characters in word2 (using insert operations). If index j goes out of bounds, we return the number of remaining characters in word1 (using delete operations). At each step, we return the minimum operation path. This approach is exponential. Can you think of a way to optimize it? +

+
+ +
+
+ Hint 4 +

+ We can use memoization to cache the results and avoid redundant calculations. A hash map or a 2D array can be used to store these results. +

+
\ No newline at end of file diff --git a/hints/gas-station.md b/hints/gas-station.md new file mode 100644 index 000000000..52464072d --- /dev/null +++ b/hints/gas-station.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would be to start at each gas station, simulate the process, and return the index where completing the circuit is possible. This would be an O(n^2) time solution. Can you think of a better way? Maybe a greedy approach works. +

+
+ +
+
+ Hint 2 +

+ We can immediately return -1 if sum(gas) < sum(cost), as completing the circuit is impossible due to insufficient gas. Otherwise, a solution always exists because the total gas is sufficient to cover the total cost, meaning there must be a valid starting point that allows completing the circuit. +

+
+ +
+
+ Hint 3 +

+ We start with a variable total to track the gas balance and initialize the result index to 0. As we iterate through the array with index i, we accumulate the difference (gas[i] - cost[i]). If total becomes negative at any index, we reset it to 0 and update the result index to (i + 1). +

+
\ No newline at end of file diff --git a/hints/hand-of-straights.md b/hints/hand-of-straights.md new file mode 100644 index 000000000..1a35e0287 --- /dev/null +++ b/hints/hand-of-straights.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(nlogn) time and O(n) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ It is observed that to form a group, the minimum value should be the starting value of the group. Additionally, the minimum value in the array serves as the starting value for one or more groups based on its frequency. Can you think of an efficient way to determine the frequencies of array elements? Maybe a specific data structure can be useful here. +

+
+ +
+
+ Hint 2 +

+ We can use a hash map to store the elements along with their frequencies. Additionally, we sort the given array. Then, we iterate through the sorted array and try to form groups by decrementing the frequency count. If we fail to form a group at any step, we immediately return false. Can you think why this works? +

+
+ +
+
+ Hint 3 +

+ Sorting ensures we start with the smallest available value, while the hash map helps track element availability using frequency counts. At each step, we pick the smallest available value x and attempt to form a group from x to x + groupSize - 1. If all elements are present based on their frequency counts, we decrement their counts as we iterate. If we successfully form all groups, we return true; otherwise, we return false. +

+
\ No newline at end of file diff --git a/hints/insert-new-interval.md b/hints/insert-new-interval.md new file mode 100644 index 000000000..a807b4c61 --- /dev/null +++ b/hints/insert-new-interval.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) extra space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ The given intervals are non-overlapping and sorted in ascending order based on the start value. Try to visualize them as line segments and consider how a new interval can be inserted. Maybe you should analyze different cases of inserting a new interval. +

+
+ +
+
+ Hint 2 +

+ First, we append all intervals to the output list that have an end value smaller than the start value of the new interval. Then, we encounter one of three cases: we have appended all intervals, we reach an interval whose start value is greater than the new interval’s end, or we find an overlapping interval. Can you think of a way to handle these cases efficiently? +

+
+ +
+
+ Hint 3 +

+ We iterate through the remaining intervals, updating the new interval if its end value is greater than or equal to the current interval's start value. We adjust the start and end of the new interval to the minimum and maximum values, respectively. After this, any remaining intervals are appended to the output list, and we return the result. +

+
\ No newline at end of file diff --git a/hints/interleaving-string.md b/hints/interleaving-string.md new file mode 100644 index 000000000..16a8c100a --- /dev/null +++ b/hints/interleaving-string.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(m * n) time and O(m * n) space, where m is the length of the string s1 and n is the length of the string s2. +

+
+ +
+
+ Hint 1 +

+ If the sum of the characters in s1 and s2 does not equal s3, we return false. Think in terms of recursion and visualize it as a decision tree, where we explore different combinations of portions from both strings. Can you determine the possible decisions at each recursion step? +

+
+ +
+
+ Hint 2 +

+ We recursively iterate through the strings using indices i, j, and k for s1, s2, and s3, respectively. At each step, we extend the current path in two directions based on whether the k-th character of s3 matches the current character of s1 or s2. If any path returns true, we immediately return true. If k goes out of bounds, it means we have successfully formed the interleaved string, so we return true. +

+
+ +
+
+ Hint 3 +

+ This approach is exponential. Can you think of a way to optimize it? Since k depends on i and j, it can be treated as a constant, as we can derive k using i + j. +

+
+ +
+
+ Hint 4 +

+ We can use memoization to cache the results of recursive calls and avoid redundant computations. Treating i and j as states, we can use a hash map or a 2D array to store the results. +

+
\ No newline at end of file diff --git a/hints/jump-game-ii.md b/hints/jump-game-ii.md new file mode 100644 index 000000000..4c7c41e30 --- /dev/null +++ b/hints/jump-game-ii.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would be to recursively explore all paths from index 0 to its reachable indices, then process those indices similarly and return the minimum steps to reach the last index. This would be an exponential approach. Can you think of a better way? Maybe a greedy approach works. +

+
+ +
+
+ Hint 2 +

+ We maintain two pointers, l and r, initially set to 0, representing the range of reachable indices. At each step, we iterate through the indices in the range l to r and determine the farthest index that can be reached from the current range. +

+
+ +
+
+ Hint 3 +

+ We then update the pointers l and r to the next range, setting l to r + 1 and r to the farthest index reachable from the current range. We continue this process until the pointers go out of bounds. +

+
+ +
+
+ Hint 4 +

+ The number of steps taken represents the minimum steps required to reach the last index, as it is guaranteed that we can reach it. +

+
\ No newline at end of file diff --git a/hints/jump-game.md b/hints/jump-game.md new file mode 100644 index 000000000..91e7092c9 --- /dev/null +++ b/hints/jump-game.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) space, where n is the size of input array. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would be to recursively explore all paths from index 0 to its reachable indices, then process those indices similarly, returning true if we reach the last index. This would be an exponential approach. Can you think of a better way? Maybe a greedy approach works. +

+
+ +
+
+ Hint 2 +

+ Instead of processing the array from index 0, start from the last index. Let the target index be goal = n - 1. Iterate in reverse from index n - 2. +

+
+ +
+
+ Hint 3 +

+ At each iteration, we check whether the current index can reach goal. If it can, we update goal to the current index, as reaching the current index means we can also reach the goal. +

+
+ +
+
+ Hint 4 +

+ To determine if we can reach the last index, the goal should be 0 after the iteration. Otherwise, reaching the last index is not possible. +

+
\ No newline at end of file diff --git a/hints/longest-common-subsequence.md b/hints/longest-common-subsequence.md new file mode 100644 index 000000000..d25df25e5 --- /dev/null +++ b/hints/longest-common-subsequence.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(m * n) time and O(m * n) space, where m is the length of the string text1 and n is the length of the string text2. +

+
+ +
+
+ Hint 1 +

+ Try to think in terms of recursion and visualize it as a decision tree. Can you determine the possible decisions at each step? Maybe you should consider iterating through both strings recursively at the same time. +

+
+ +
+
+ Hint 2 +

+ At each recursion step, we have two choices: if the characters at the current indices of both strings match, we move both indices forward and extend the subsequence. Otherwise, we explore two paths by advancing one index at a time and recursively finding the longest subsequence. We return the maximum length between these two choices. This approach is exponential. Can you think of a way to optimize it? +

+
+ +
+
+ Hint 3 +

+ We return 0 if either index goes out of bounds. To optimize, we can use memoization to cache recursive call results and avoid redundant calculations. A hash map or a 2D array can be used to store these results. +

+
\ No newline at end of file diff --git a/hints/longest-increasing-path-in-matrix.md b/hints/longest-increasing-path-in-matrix.md new file mode 100644 index 000000000..8008fe73f --- /dev/null +++ b/hints/longest-increasing-path-in-matrix.md @@ -0,0 +1,23 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(m * n) time and O(m * n) space, where m is the number of rows and n is the number of columns in the given matrix. +

+
+ +
+
+ Hint 1 +

+ If we move from one cell to an adjacent cell with a greater value, we won't revisit a cell, as the path is strictly increasing. A brute force approach would be to run a dfs from every cell and return the longest path found. This approach is exponential. Can you think of a way to optimize it to avoid redundant calculations? +

+
+ +
+
+ Hint 2 +

+ We can use memoization to cache the results of recursive calls and avoid redundant computations. A hash map or a 2D array can be used to store these results. +

+
\ No newline at end of file diff --git a/hints/longest-increasing-subsequence.md b/hints/longest-increasing-subsequence.md new file mode 100644 index 000000000..36a4e3e78 --- /dev/null +++ b/hints/longest-increasing-subsequence.md @@ -0,0 +1,47 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(n ^ 2) time and O(n ^ 2) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ A subsequence is formed by selecting elements while maintaining their order. Using recursion, we can generate all subsequences. The recursive function returns the length of the longest increasing subsequence up to index i, processing from left to right. At each step, we decide whether to include or exclude the current element. +

+
+ +
+
+ Hint 2 +

+ Since the sequence must be increasing, we represent choices by adding 1 when including an element and 0 when excluding it. In recursion, how can we ensure the current element is greater than the previous one? Perhaps additional information is needed to process it. +

+
+ +
+
+ Hint 3 +

+ We can store the index of the previously chosen element as j, making it easier to process the current element at index i. If and only if j == -1 or nums[i] > nums[j], we include the current element and extend the recursive path. Can you determine the recurrence relation? At most, two recursive calls are made at each recursion step. +

+
+ +
+
+ Hint 4 +

+ We stop the recursion when index i goes out of bounds and return 0 since no more elements can be added. The initial recursion call starts with j = -1. At each step, we include the current element if it is greater than the previous one and continue the recursion, or we exclude it and explore the next possibility. We return the maximum value obtained from both paths. +

+
+ +
+
+ Hint 5 +

+ The time complexity of this approach is exponential. We can use memoization to store results of recursive calls and avoid recalculations. A hash map or a 2D array can be used to cache these results. +

+
\ No newline at end of file diff --git a/hints/maximum-product-subarray.md b/hints/maximum-product-subarray.md new file mode 100644 index 000000000..d46997d32 --- /dev/null +++ b/hints/maximum-product-subarray.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ A brute force solution would be to find the product for every subarray and then return the maximum among all the products. This would be an O(n ^ 2) approach. Can you think of a better way? Maybe you should think of a dynamic programming approach. +

+
+ +
+
+ Hint 2 +

+ Try to identify a pattern by finding the maximum product for an array with two elements and determining what values are needed when increasing the array size to three. Perhaps you only need two values when introducing a new element. +

+
+ +
+
+ Hint 3 +

+ We maintain both the minimum and maximum product values and update them when introducing a new element by considering three cases: starting a new subarray, multiplying with the previous max product, or multiplying with the previous min product. The max product is updated to the maximum of these three, while the min product is updated to the minimum. We also track a global max product for the result. This approach is known as Kadane's algorithm. +

+
\ No newline at end of file diff --git a/hints/maximum-subarray.md b/hints/maximum-subarray.md new file mode 100644 index 000000000..f8071b628 --- /dev/null +++ b/hints/maximum-subarray.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would be to compute the sum of every subarray and return the maximum among them. This would be an O(n^2) approach. Can you think of a better way? Maybe you should consider a dynamic programming-based approach. +

+
+ +
+
+ Hint 2 +

+ Instead of calculating the sum for every subarray, try maintaining a running sum. Maybe you should consider whether extending the previous sum or starting fresh with the current element gives a better result. Can you think of a way to track this efficiently? +

+
+ +
+
+ Hint 3 +

+ We use a variable curSum to track the sum of the elements. At each index, we have two choices: either add the current element to curSum or start a new subarray by resetting curSum to the current element. Maybe you should track the maximum sum at each step and update the global maximum accordingly. +

+
+ +
+
+ Hint 4 +

+ This algorithm is known as Kadane's algorithm. +

+
\ No newline at end of file diff --git a/hints/meeting-schedule-ii.md b/hints/meeting-schedule-ii.md new file mode 100644 index 000000000..1342e260f --- /dev/null +++ b/hints/meeting-schedule-ii.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(nlogn) time and O(n) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ Try to visualize the meetings as line segments on a number line representing start and end times. The number of rooms required is the maximum number of overlapping meetings at any point on the number line. Can you think of a way to determine this efficiently? +

+
+ +
+
+ Hint 2 +

+ We create two arrays, start and end, containing the start and end times of all meetings, respectively. After sorting both arrays, we use a two-pointer based approach. How do you implement this? +

+
+ +
+
+ Hint 3 +

+ We use two pointers, s and e, for the start and end arrays, respectively. We also maintain a variable count to track the current number of active meetings. At each iteration, we increment s while the start time is less than the current end time and increase count, as these meetings must begin before the earliest ongoing meeting ends. +

+
+ +
+
+ Hint 4 +

+ Then, we increment e and decrement count as a meeting has ended. At each step, we update the result with the maximum value of active meetings stored in count. +

+
\ No newline at end of file diff --git a/hints/meeting-schedule.md b/hints/meeting-schedule.md new file mode 100644 index 000000000..0216b7b66 --- /dev/null +++ b/hints/meeting-schedule.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(nlogn) time and O(n) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ If two intervals are sorted in ascending order by their start values, they overlap if the start value of the second interval is less than the end value of the first interval. And these are called overlapping intervals. +

+
+ +
+
+ Hint 2 +

+ A brute force approach would be to check every pair of intervals and return false if any overlap is found. This would be an O(n^2) solution. Can you think of a better way? Maybe you should visualize the given intervals as line segments. +

+
+ +
+
+ Hint 3 +

+ We should sort the given intervals based on their start values, as this makes it easier to check for overlaps by comparing adjacent intervals. We then iterate through the intervals from left to right and return false if any adjacent intervals overlap. +

+
\ No newline at end of file diff --git a/hints/merge-intervals.md b/hints/merge-intervals.md new file mode 100644 index 000000000..89af36fe5 --- /dev/null +++ b/hints/merge-intervals.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(nlogn) time and O(n) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ Sorting the given intervals in ascending order based on their start values is beneficial, as it helps in identifying overlapping intervals efficiently. How can you determine if two intervals overlap? +

+
+ +
+
+ Hint 2 +

+ If two intervals are sorted in ascending order by their start values, they overlap if the start value of the second interval is less than or equal to the end value of the first interval. +

+
+ +
+
+ Hint 3 +

+ We iterate through the sorted intervals from left to right, starting with the first interval in the output list. From the second interval onward, we compare each interval with the last appended interval. Can you determine the possible cases for this comparison? +

+
+ +
+
+ Hint 4 +

+ The two cases are: if the current interval overlaps with the last appended interval, we update its end value to the maximum of both intervals' end values and continue. Otherwise, we append the current interval and proceed. +

+
\ No newline at end of file diff --git a/hints/merge-triplets-to-form-target.md b/hints/merge-triplets-to-form-target.md new file mode 100644 index 000000000..fd475aa48 --- /dev/null +++ b/hints/merge-triplets-to-form-target.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ An important observation is that we can ignore triplets with values greater than the target triplet. +

+
+ +
+
+ Hint 2 +

+ Specifically, if a triplet t has any element greater than the corresponding value in target (i.e., t[0] > target[0], t[1] > target[1], or t[2] > target[2]), we can discard it. This is because using such a triplet in operations would exceed the target values, making it invalid. +

+
+ +
+
+ Hint 3 +

+ Now, from the remaining valid triplets, we only need to check whether the target triplet values exist. Since all values in the valid triplets are less than or equal to the corresponding values in the target triplet, finding the target triplet among them guarantees that we can achieve it. +

+
\ No newline at end of file diff --git a/hints/minimum-interval-including-query.md b/hints/minimum-interval-including-query.md new file mode 100644 index 000000000..9b56faba2 --- /dev/null +++ b/hints/minimum-interval-including-query.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(nlogn + mlogm) time and O(n + m) space, where m is the size of the array queries and n is the size of the array intervals. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would be to iterate through each query and, for each query, check all intervals to find the result. This would be an O(m * n) solution. Can you think of a better way? Maybe processing the queries in sorted order could help. +

+
+ +
+
+ Hint 2 +

+ We sort the intervals by start value and process the queries in ascending order. Using a pointer i, we add intervals to a min-heap while their start values are less than or equal to the query, storing their end values and sizes. +

+
+ +
+
+ Hint 3 +

+ The min-heap is ordered by interval size. We remove elements from the heap while the top element’s end value is less than the current query. The result for the query is the top element’s size if the heap is non-empty; otherwise, it is -1. +

+
\ No newline at end of file diff --git a/hints/missing-number.md b/hints/missing-number.md new file mode 100644 index 000000000..2d5f6908b --- /dev/null +++ b/hints/missing-number.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would iterate through the range of numbers from 0 to n, checking if each number is present in the given array. If a number is missing, it is returned. This results in an O(n^2) solution. Can you think of a better way? Maybe a data structure could help optimize this process. +

+
+ +
+
+ Hint 2 +

+ We can use a hash set by inserting the given array elements into it. Then, we iterate through the range of numbers from 0 to n and use the hash set for O(1) lookups to find the missing number. Can you think of a way to further optimize this? Maybe a bitwise operator could be useful. +

+
+ +
+
+ Hint 3 +

+ We can use bitwise XOR. When two identical numbers are XORed, the result is 0. Using this property, we can efficiently find the missing number. +

+
+ +
+
+ Hint 4 +

+ We first compute the bitwise XOR of numbers from 0 to n. Then, we iterate through the array and XOR its elements as well. The missing number remains in the final XOR result since all other numbers appear twice—once in the range and once in the array—while the missing number is XORed only once. +

+
\ No newline at end of file diff --git a/hints/multiply-strings.md b/hints/multiply-strings.md new file mode 100644 index 000000000..193cc4c27 --- /dev/null +++ b/hints/multiply-strings.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(m*n) time and O(m+n) space, where m is the length of the string num1 and n is the length of the string num2. +

+
+ +
+
+ Hint 1 +

+ Implement a helper function that takes two number strings and returns their sum. Ensure that the length of num1 is greater than num2, swapping them if necessary. Can you think of a way to multiply the strings? Maybe you should first consider basic multiplication, where num1 is multiplied by each digit of num2. +

+
+ +
+
+ Hint 2 +

+ When multiplying num1 with each digit of num2, we iterate through num2 in reverse order. Based on the digit's position, we pad zeros to the multiplication result accordingly—no padding for the last digit, one zero for the second last, and so on. What should be the next step after each multiplication? Maybe you should implement a helper function to handle this. +

+
+ +
+
+ Hint 3 +

+ We implement a helper function that takes num1, a digit, and a variable zeroes, returning the multiplication result with zeroes padded at the end. A global string res stores the final result. +

+
+ +
+
+ Hint 4 +

+ In the main function, we iterate through num2 in reverse order, calling the helper function to multiply num1 with the current digit and append the appropriate number of padding zeros. We then call another helper function that takes this multiplication result and the global result string res, adds them, and updates res. +

+
\ No newline at end of file diff --git a/hints/non-cyclical-number.md b/hints/non-cyclical-number.md new file mode 100644 index 000000000..6672425b9 --- /dev/null +++ b/hints/non-cyclical-number.md @@ -0,0 +1,23 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(logn) time and O(logn) space, where n is the given integer. +

+
+ +
+
+ Hint 1 +

+ Create a helper function that returns the sum of the squares of a number's digits. Then, simulate the given process. If we reach 1, return true. However, we may get stuck in a cycle if a number is processed more than once. What data structure can be used to detect if a number has already been processed? +

+
+ +
+
+ Hint 2 +

+ We can use a hash set to detect if a number has already been processed. At each step, we update n with the return value of the helper function. If the result is 1, we return true. If n is already in the set, we return false. Otherwise, we add n to the hash set and continue. +

+
\ No newline at end of file diff --git a/hints/non-overlapping-intervals.md b/hints/non-overlapping-intervals.md new file mode 100644 index 000000000..1e07a9c0b --- /dev/null +++ b/hints/non-overlapping-intervals.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(nlogn) time and O(n) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ If two intervals are sorted in ascending order by their start values, they overlap if the start value of the second interval is less than the end value of the first interval. And these are called overlapping intervals. +

+
+ +
+
+ Hint 2 +

+ A brute force approach would be to sort the given intervals in ascending order based on their start values and recursively explore all possibilities. This would be an exponential approach. Can you think of a better way? Maybe a greedy approach works here. +

+
+ +
+
+ Hint 3 +

+ We first sort the given intervals based on their start values to efficiently check for overlaps by comparing adjacent intervals. We then iterate through the sorted intervals from left to right, keeping track of the previous interval’s end value as prevEnd, initially set to the end value of the first interval. +

+
+ +
+
+ Hint 4 +

+ We then iterate from the second interval. If the current interval doesn't overlap, we update prevEnd to the current interval's end and continue. Otherwise, we set prevEnd to the minimum of prevEnd and the current interval’s end, greedily removing the interval that ends last to retain as many intervals as possible. +

+
\ No newline at end of file diff --git a/hints/number-of-one-bits.md b/hints/number-of-one-bits.md new file mode 100644 index 000000000..788499e2b --- /dev/null +++ b/hints/number-of-one-bits.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(1) time and O(1) space. +

+
+ +
+
+ Hint 1 +

+ The given integer is a 32-bit integer. Can you think of using bitwise operators to iterate through its bits? Maybe you should consider iterating 32 times. +

+
+ +
+
+ Hint 2 +

+ We iterate 32 times (0 to 31) using index i. The expression (1 << i) creates a bitmask with a set bit at the i-th position. How can you check whether the i-th bit is set in the given number? Maybe you should consider using the bitwise-AND ("&"). +

+
+ +
+
+ Hint 3 +

+ Since the mask has a set bit at the i-th position and all 0s elsewhere, we can perform a bitwise-AND with n. If n has a set bit at the i-th position, the result is positive; otherwise, it is 0. We increment the global count if the result is positive and return it after the iteration. +

+
\ No newline at end of file diff --git a/hints/partition-equal-subset-sum.md b/hints/partition-equal-subset-sum.md new file mode 100644 index 000000000..6dfc98881 --- /dev/null +++ b/hints/partition-equal-subset-sum.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(n * t) time and O(n * t) space, where n is the size of the input array and t is half the sum of the array elements. +

+
+ +
+
+ Hint 1 +

+ If the sum of the array elements is not even, we can immediately return false. Think in terms of recursion, where we try to build a subset with a sum equal to half of the total sum. If we find such a subset, the remaining elements will automatically form another subset with the same sum. The entire array can also be considered as one subset, with the other being empty. Can you visualize this as a decision tree to process the array recursively? +

+
+ +
+
+ Hint 2 +

+ We recursively iterate through the array with index i. At each step, we decide whether to include the current element in the subset or not. Instead of forming the subset explicitly, can you think of a better approach? Maybe you only need to track the subset sum rather than generating the subset itself. +

+
+ +
+
+ Hint 3 +

+ We can track the subset sum using a variable curSum. At each step, we make two recursive calls. If adding the current element does not exceed the target, we include it. If either path leads to a solution, we immediately return true. Can you determine the base case for this recursion? All elements in the array are positive. +

+
+ +
+
+ Hint 4 +

+ If curSum equals half the sum of the array elements, we return true. If index i goes out of bounds, we return false. This solution is exponential, but we can use memoization to cache recursive call results and avoid redundant computations. We can use a hash map or a 2D array with dimensions n * t, where n is the size of the input array and t is half the sum of the input array elements. +

+
\ No newline at end of file diff --git a/hints/partition-labels.md b/hints/partition-labels.md new file mode 100644 index 000000000..c5e3551bb --- /dev/null +++ b/hints/partition-labels.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(m) space, where n is the length of the string s and m is the number of unique characters in the string s. +

+
+ +
+
+ Hint 1 +

+ A character has a first and last index in the given string. Can you think of a greedy approach to solve this problem? Maybe you should try iterating over one of these two indices. +

+
+ +
+
+ Hint 2 +

+ We store the last index of each character in a hash map or an array. As we iterate through the string, treating each index as a potential start of a partition, we track the end of the partition using the maximum last index of the characters seen so far in the current partition. Additionally, we maintain the size of the current partition using a variable, say size. +

+
+ +
+
+ Hint 3 +

+ We update the end of the current partition based on the maximum last index of the characters, extending the partition as needed. When the current index reaches the partition’s end, we finalize the partition, append its size to the output list, reset the size to 0, and continue the same process for the remaining string. +

+
\ No newline at end of file diff --git a/hints/plus-one.md b/hints/plus-one.md new file mode 100644 index 000000000..ec62b78c9 --- /dev/null +++ b/hints/plus-one.md @@ -0,0 +1,23 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(n) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ There are two cases when adding 1 to a number. If the rightmost digit is less than 9, we simply increment it. Otherwise, we set it to 0 and apply the same process to the preceding digit. +

+
+ +
+
+ Hint 2 +

+ We iterate through the given digits from right to left using index i. If the current digit is less than 9, we increment it and return the array. Otherwise, we set the digit to 0 and continue. If the loop completes without returning, we insert 1 at the beginning of the array and return it. +

+
\ No newline at end of file diff --git a/hints/pow-x-n.md b/hints/pow-x-n.md new file mode 100644 index 000000000..de42350f0 --- /dev/null +++ b/hints/pow-x-n.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(logn) time and O(logn) space, where n is the given integer. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would be to iterate linearly up to n, multiplying by x each time to find (x^n). If n is negative, return (1 / (x^n)); otherwise, return (x^n). Can you think of a better way? Maybe a recursive approach would be more efficient. +

+
+ +
+
+ Hint 2 +

+ For example, to calculate 2^6, instead of multiplying 2 six times, we compute 2^3 and square the result. The same logic applies recursively to find 2^3 and further break down the multiplication. What should be the base case for this recursion? Maybe you should consider the term that cannot be further broken down. +

+
+ +
+
+ Hint 3 +

+ In (x^n), if x is 0, we return 0. If n is 0, we return 1, as any number raised to the power of 0 is 1. Otherwise, we compute (x^(n/2)) recursively and square the result. If n is odd, we multiply the final result by x. What should be the logic if n is negative? +

+
+ +
+
+ Hint 4 +

+ We start the recursion with the absolute value of n. After computing the result as res, we return res if n is non-negative; otherwise, we return (1 / res). +

+
\ No newline at end of file diff --git a/hints/regular-expression-matching.md b/hints/regular-expression-matching.md new file mode 100644 index 000000000..e17c78964 --- /dev/null +++ b/hints/regular-expression-matching.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(m * n) time and O(m * n) space, where m is the length of the string s and n is the length of the string p. +

+
+ +
+
+ Hint 1 +

+ Try to think in terms of recursion and visualize it as a decision tree, where we explore different combinations to match the strings when encountering *. Multiple decisions are made at each step to find a valid matching path. Can you determine the possible decisions at each recursion step? +

+
+ +
+
+ Hint 2 +

+ We recursively iterate through the strings using indices i and j for s and p, respectively. If the characters match or p[j] is '.', we increment both i and j to process the remaining strings. When the next character of string p is '*', we have two choices: skip it (treating it as zero occurrences) or match one or more characters (if s[i] matches p[j]), incrementing i accordingly. +

+
+ +
+
+ Hint 3 +

+ If both indices go out of bounds, we return true; otherwise, we return false. If any recursive path returns true, we immediately return true. This approach is exponential. Can you think of a way to optimize it? +

+
+ +
+
+ Hint 4 +

+ We can use memoization to cache the results of recursive calls and avoid redundant calculations. A hash map or a 2D array can be used to store these results. +

+
\ No newline at end of file diff --git a/hints/reverse-bits.md b/hints/reverse-bits.md new file mode 100644 index 000000000..0eb364ce9 --- /dev/null +++ b/hints/reverse-bits.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(1) time and O(1) space. +

+
+ +
+
+ Hint 1 +

+ Given a 32-bit integer, what is the position of bit i after reversing the bits? Maybe you should observe the bit positions before and after reversal to find a pattern. +

+
+ +
+
+ Hint 2 +

+ After reversing the bits, the bit at position i moves to position 31 - i. Can you use this observation to construct the reversed number efficiently? +

+
+ +
+
+ Hint 3 +

+ We initialize res to 0 and iterate through the bits of the given integer n. We extract the bit at the i-th position using ((n >> i) & 1). If it is 1, we set the corresponding bit in res at position (31 - i) using (res |= (1 << (31 - i))). +

+
\ No newline at end of file diff --git a/hints/reverse-integer.md b/hints/reverse-integer.md new file mode 100644 index 000000000..23b4d9c75 --- /dev/null +++ b/hints/reverse-integer.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(1) time and O(1) space. +

+
+ +
+
+ Hint 1 +

+ A straightforward approach would be to convert the given integer to a string, reverse it, convert it back to an integer using a long type, and return 0 if the result exceeds the integer range. Can you think of a better way? +

+
+ +
+
+ Hint 2 +

+ We initially declare the result res as an int with a value of 0. We iterate through the given integer, extracting digits one by one. Before appending a digit to res, we consider multiple cases. Can you determine them? Maybe you should think about overflow. +

+
+ +
+
+ Hint 3 +

+ Let MAX be the maximum positive integer and MIN be the minimum negative integer. We iterate through each digit and check for overflow before updating res. If res > MAX / 10 or res < MIN / 10, return 0. If res == MAX / 10 and the current digit is greater than MAX % 10, return 0. If res == MIN / 10 and the current digit is less than MIN % 10, return 0. Otherwise, append the digit to res and continue. +

+
\ No newline at end of file diff --git a/hints/rotate-matrix.md b/hints/rotate-matrix.md new file mode 100644 index 000000000..3f5528d0f --- /dev/null +++ b/hints/rotate-matrix.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n^2) time and O(1) space, where n is the length of the side of the given square matrix. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would use O(n^2) extra space to solve the problem. Can you think of a way to avoid using extra space? Maybe you should consider observing the positions of the elements before rotating and after rotating of the matrix. +

+
+ +
+
+ Hint 2 +

+ We can rotate the matrix in two steps. First, we reverse the matrix vertically, meaning the first row becomes the last, the second row becomes the second last, and so on. Next, we transpose the reversed matrix, meaning rows become columns and columns become rows. How would you transpose the matrix? +

+
+ +
+
+ Hint 3 +

+ Since the given matrix is a square matrix, we only need to iterate over the upper triangular part, meaning the right upper portion of the main diagonal. In this way, we can transpose a matrix. +

+
\ No newline at end of file diff --git a/hints/set-zeroes-in-matrix.md b/hints/set-zeroes-in-matrix.md new file mode 100644 index 000000000..663ff919e --- /dev/null +++ b/hints/set-zeroes-in-matrix.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(m*n) time and O(1) space, where m is the number of rows and n is the number of columns in the given matrix. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would iterate through the given matrix and update the corresponding row and column in a new matrix on the fly. This would result in an O((m*n)*(m+n)) time and O(m*n) space solution. Can you think of a better way? Maybe you should consider using a single variable for a row and a single variable for a column instead of updating entire row and column. +

+
+ +
+
+ Hint 2 +

+ A better approach is to use O(m+n) boolean arrays. We iterate through the matrix, and when encountering a zero, we mark the respective row and column as true. In the second iteration, we set a cell to 0 if its corresponding row or column is marked true. Can you think of a way to optimize the space further? +

+
+ +
+
+ Hint 3 +

+ We can use the topmost row and leftmost column of the matrix as boolean arrays by marking 0 instead of true. However, since they overlap at one cell, we use a single variable to track the top row separately. We then iterate through the matrix and mark zeros accordingly. +

+
+ +
+
+ Hint 4 +

+ In the second iteration, we update all cells that are not part of the top row or left column accordingly. After making the necessary changes, we check the top-leftmost cell and update the corresponding column. Finally, we check the extra variable and update the top row accordingly. +

+
\ No newline at end of file diff --git a/hints/single-number.md b/hints/single-number.md new file mode 100644 index 000000000..6aab0485f --- /dev/null +++ b/hints/single-number.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would iterate through the array, checking each element using a nested loop. If a duplicate is found, we continue to the next element; otherwise, the current element is the required number. This results in an O(n^2) solution. Can you think of a better way? Maybe a data structure can help detect duplicates efficiently. +

+
+ +
+
+ Hint 2 +

+ We use a hash set, iterating through the array and adding elements that are not in the set while removing those that are already present. After the iteration, the required number remains in the hash set. This results in an O(n) space solution. Can you further optimize it? Maybe a bitwise operator could be useful here. +

+
+ +
+
+ Hint 3 +

+ Think about the bitwise XOR ("^"). What is the result when two identical numbers are XORed? +

+
+ +
+
+ Hint 4 +

+ When two identical numbers are XORed, they cancel out, resulting in zero. Since every number appears twice except for one, the XOR of the entire array gives the number that appears only once. +

+
\ No newline at end of file diff --git a/hints/spiral-matrix.md b/hints/spiral-matrix.md new file mode 100644 index 000000000..2b8eced0a --- /dev/null +++ b/hints/spiral-matrix.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(m*n) time and O(1) extra space, where m is the number of rows and n is the number of columns in the given matrix. +

+
+ +
+
+ Hint 1 +

+ Try to simulate the process as described in the problem. Think in terms of matrix layers, starting from the outermost boundaries and moving inward. Can you determine an efficient way to implement this? +

+
+ +
+
+ Hint 2 +

+ Each boundary consists of four parts: the top row, right column, bottom row, and left column, which follow the spiral order and act as four pointers. For each layer, the top pointer increments by one, the right pointer decrements by one, the left pointer increments by one, and the bottom pointer decrements by one. +

+
+ +
+
+ Hint 3 +

+ At each layer, four loops traverse the matrix: one moves left to right along the top row, another moves top to bottom along the right column, the next moves right to left along the bottom row, and the last moves bottom to top along the left column. This process generates the spiral order. +

+
\ No newline at end of file diff --git a/hints/string-encode-and-decode.md b/hints/string-encode-and-decode.md index 39083d5be..82bc8fbcb 100644 --- a/hints/string-encode-and-decode.md +++ b/hints/string-encode-and-decode.md @@ -2,7 +2,7 @@
Recommended Time & Space Complexity

- You should aim for a solution with O(m) time and O(1) space for each encode() and decode() call, where m is the sum of lengths of all the strings. + You should aim for a solution with O(m) time for each encode() and decode() call and O(m+n) space, where m is the sum of lengths of all the strings and n is the number of strings.

diff --git a/hints/sum-of-two-integers.md b/hints/sum-of-two-integers.md new file mode 100644 index 000000000..340f197d0 --- /dev/null +++ b/hints/sum-of-two-integers.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution with O(1) time and O(1) space. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would use the addition operator. Can you think of a way to perform addition without using it? Maybe you should consider solving this using bit manipulation. +

+
+ +
+
+ Hint 2 +

+ We can use the bitwise XOR operator to perform addition. If both a and b have 1 at the same bit position, the sum at that position is 0, and a carry of 1 is generated. If the bits are different, the sum at that position is 1. Additionally, we account for the carry from the previous step in the next iteration. +

+
+ +
+
+ Hint 3 +

+ We iterate bit by bit from 0 to 31 since the given integers are 32-bit. We track the carry, initially set to 0, and initialize the result as res. During iteration, the XOR of the bits at the i-th position of both integers and the carry determines the current bit of res. How can you handle negative numbers? +

+
+ +
+
+ Hint 4 +

+ To handle negative numbers, if the final result exceeds the maximum positive 32-bit integer, it means the number should be negative. We adjust it using bitwise operations: flipping the bits with res ^ ((2 ^ 32) - 1) and applying ~ to restore the correct two’s complement representation. This ensures the result correctly represents signed 32-bit integers. +

+
\ No newline at end of file diff --git a/hints/target-sum.md b/hints/target-sum.md new file mode 100644 index 000000000..06e9e9a3e --- /dev/null +++ b/hints/target-sum.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(n * m) time and O(n * m) space, where n is the size of the input array and m is the sum of all the elements in the array. +

+
+ +
+
+ Hint 1 +

+ Try to think in terms of recursion and visualize it as a decision tree, where we have two choices at each recursion step: assigning a positive or negative sign. +

+
+ +
+
+ Hint 2 +

+ We recursively iterate through the array using index i, tracking the current sum along the recursive path. Each step branches into two paths, and we sum the number of ways to reach the target. If the index i goes out of bounds, we return 1 if the current sum equals the target; otherwise, we return 0. +

+
+ +
+
+ Hint 3 +

+ This approach is exponential. We can use memoization to cache recursive call results and avoid redundant calculations. A hash map or a 2D array with modifications can be used for caching. If using a 2D array, the dimensions can be (n * (2m + 1)), where n is the array size and m represents the sum of the array elements. +

+
\ No newline at end of file diff --git a/hints/valid-parenthesis-string.md b/hints/valid-parenthesis-string.md new file mode 100644 index 000000000..29baed7d5 --- /dev/null +++ b/hints/valid-parenthesis-string.md @@ -0,0 +1,39 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(n) time and O(n) space, where n is the length of the input string. +

+
+ +
+
+ Hint 1 +

+ A brute force approach would try all possibilities when encountering a '*' and recursively solve the problem, leading to an exponential approach. Can you think of a better way? Maybe a data structure commonly used in parenthesis problems could be useful. +

+
+ +
+
+ Hint 2 +

+ We can solve the problem using a stack-based approach. We maintain two stacks: one for tracking the indices of left parentheses and another for star indices. As we iterate through the string from left to right, we push indices onto their respective stacks when encountering a left parenthesis '(' or a star '*'. Can you determine the logic for the right parentesis case? +

+
+ +
+
+ Hint 3 +

+ If the left parenthesis stack is not empty, we pop from it. Otherwise, we pop from the star stack, treating the star as a left parenthesis to keep the string valid. After iterating the string, the stacks might be non-empty? Can you determine the logic for this case? +

+
+ +
+
+ Hint 4 +

+ Now, we try to match the remaining left parentheses with stars, ensuring the stars appear after the left parentheses in the string. We simultaneously pop from both stacks, and if the index of a left parenthesis is greater than that of a star, the string is invalid as there is no matching right parenthesis. In this case, we return false. +

+
\ No newline at end of file diff --git a/hints/word-break.md b/hints/word-break.md new file mode 100644 index 000000000..cb850a49c --- /dev/null +++ b/hints/word-break.md @@ -0,0 +1,31 @@ +
+
+ Recommended Time & Space Complexity +

+ You should aim for a solution as good or better than O(n * m * t) time and O(n) space, where n is the length of the string s, m is the number of words in wordDict, and t is the maximum length of any word in wordDict. +

+
+ +
+
+ Hint 1 +

+ Try to think of this problem in terms of recursion, where we explore all possibilities. We iterate through the given string s, attempting to pick a word from wordDict that matches a portion of s, and then recursively continue processing the remaining string. Can you determine the recurrence relation and base condition? +

+
+ +
+
+ Hint 2 +

+ The base condition is to return true if we reach the end of the string s. At each recursive call with index i iterating through s, we check all words in wordDict and recursively process the remaining string by incrementing i by the length of the matched word. If any recursive path returns true, we immediately return true. However, this solution is exponential. Can you think of an optimization? Maybe you should consider an approach that avoids repeated work. +

+
+ +
+
+ Hint 3 +

+ We can avoid recalculating results for recursive calls by using memoization. Since we iterate with index i, we can use a hash map or an array of the same length as s to cache the results of recursive calls and prevent redundant computations. +

+
\ No newline at end of file diff --git a/python/0020-valid-parentheses.py b/python/0020-valid-parentheses.py index 4d0ae3424..ce3bf39cd 100644 --- a/python/0020-valid-parentheses.py +++ b/python/0020-valid-parentheses.py @@ -1,13 +1,13 @@ class Solution: def isValid(self, s: str) -> bool: - Map = {")": "(", "]": "[", "}": "{"} + bracketMap = {")": "(", "]": "[", "}": "{"} stack = [] for c in s: - if c not in Map: + if c not in bracketMap: stack.append(c) continue - if not stack or stack[-1] != Map[c]: + if not stack or stack[-1] != bracketMap[c]: return False stack.pop()