From 0294dc262bd2fdf0231d63bf5605e4fcc0e35952 Mon Sep 17 00:00:00 2001
From: Thuan Le
Date: Thu, 12 Jan 2023 19:36:32 -0800
Subject: [PATCH 01/67] create 0344-reverse-string-csharp
---
csharp/0344-reverse-string.cs | 14 ++++++++++++++
1 file changed, 14 insertions(+)
create mode 100644 csharp/0344-reverse-string.cs
diff --git a/csharp/0344-reverse-string.cs b/csharp/0344-reverse-string.cs
new file mode 100644
index 000000000..4b8abc569
--- /dev/null
+++ b/csharp/0344-reverse-string.cs
@@ -0,0 +1,14 @@
+class Solution
+{
+ public void ReverseString(char[] s)
+ {
+ int leftPointer = 0;
+ int rightPointer = s.Length - 1;
+ while (leftPointer < rightPointer)
+ {
+ char temp = s[leftPointer];
+ s[leftPointer++] = s[rightPointer];
+ s[rightPointer--] = temp;
+ }
+ }
+}
\ No newline at end of file
From 4ad94c8d144a9daa9b4268d13bd9de654fe4f124 Mon Sep 17 00:00:00 2001
From: jelonmusk
Date: Sun, 10 Nov 2024 23:30:46 +0530
Subject: [PATCH 02/67] Added solution 1203-Sort Items by Groups Respecting
Dependencies
---
...items-by-groups-respecting-dependencies.py | 63 +++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 python/1203-sort-items-by-groups-respecting-dependencies.py
diff --git a/python/1203-sort-items-by-groups-respecting-dependencies.py b/python/1203-sort-items-by-groups-respecting-dependencies.py
new file mode 100644
index 000000000..7da80aed8
--- /dev/null
+++ b/python/1203-sort-items-by-groups-respecting-dependencies.py
@@ -0,0 +1,63 @@
+from collections import defaultdict, deque
+from typing import List
+class Solution:
+ # This function performs topological sort on a directed graph represented by successors and predecessors_count arrays.
+ def topologicalSort(self, successors: List[List[int]], predecessors_count: List[int], num_nodes: int) -> List[int]:
+ order = [] # To store the topologically sorted nodes
+ # Initialize a deque with all nodes that have no predecessors (i.e., in-degree of 0)
+ nodes_with_no_predecessors = deque(node for node in range(num_nodes) if not predecessors_count[node])
+
+ while nodes_with_no_predecessors: # Process nodes while there are nodes without predecessors
+ node = nodes_with_no_predecessors.popleft() # Get the node with no predecessors
+ order.append(node) # Add the node to the sorted order
+ for successor in successors[node]: # For each successor of the current node
+ predecessors_count[successor] -= 1 # Decrement the in-degree of the successor
+ if not predecessors_count[successor]: # If the successor now has no predecessors
+ nodes_with_no_predecessors.append(successor) # Add it to the queue for processing
+
+ # If the number of nodes in the order is less than the total number of nodes, a cycle was detected
+ return order if len(order) == num_nodes else [] # Return the order if all nodes were sorted, else return empty list
+
+ def sortItems(self, n: int, m: int, group: List[int], beforeItems: List[List[int]]) -> List[int]:
+ # Step 1: Assign unique group IDs to items that don't belong to any group
+ for item in range(n):
+ if group[item] == -1: # If the item doesn't belong to any group
+ group[item] = m # Assign a new group ID
+ m += 1 # Increment the group ID for the next item
+
+ # Step 2: Initialize graphs for item dependencies and group dependencies
+ successors_group, successors_item = [[] for _ in range(m)], [[] for _ in range(n)] # Graphs for group and item dependencies
+ predecessors_count_group, predecessors_count_item = [0] * m, [0] * n # Count of incoming edges (predecessors) for each group and item
+
+ # Step 3: Build the dependency graphs based on beforeItems
+ for item in range(n):
+ current_group = group[item] # Get the group of the current item
+ for before in beforeItems[item]: # Process each item that should come before the current item
+ before_group = group[before] # Get the group of the item that should come before
+
+ if current_group == before_group: # If the two items belong to the same group
+ successors_item[before].append(item) # Add a dependency from 'before' to the current item
+ predecessors_count_item[item] += 1 # Increment the in-degree of the current item
+ else: # If the items belong to different groups
+ successors_group[before_group].append(current_group) # Add a group dependency
+ predecessors_count_group[current_group] += 1 # Increment the in-degree of the current group
+
+ # Step 4: Perform topological sort on both the group dependencies and item dependencies
+ groups_order = self.topologicalSort(successors_group, predecessors_count_group, m) # Topological sort of groups
+ items_order = self.topologicalSort(successors_item, predecessors_count_item, n) # Topological sort of items
+
+ # Step 5: If there was a cycle detected in either group or item sorting, return an empty list
+ if not groups_order or not items_order:
+ return [] # Return an empty list if either the group or item topological sort failed
+
+ # Step 6: Group the items based on the group IDs
+ items_grouped = [[] for _ in range(m)] # Create an empty list for each group to store its items
+ for item in items_order: # Process each item in topologically sorted order
+ items_grouped[group[item]].append(item) # Add the item to the appropriate group
+
+ # Step 7: Combine the groups in topologically sorted order
+ result = [] # The final result list to store the sorted items
+ for grp in groups_order: # For each group in topologically sorted order
+ result.extend(items_grouped[grp]) # Add the items of the group to the result
+
+ return result # Return the final sorted list of items respecting both item and group dependencies
From fc47ab5cf585794da1bb8cea969120f5ce3c2a9e Mon Sep 17 00:00:00 2001
From: "David M."
Date: Tue, 12 Nov 2024 00:41:04 +0100
Subject: [PATCH 03/67] Create 2626-array-reduce-transformation.js
---
javascript/2626-array-reduce-transformation.js | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 javascript/2626-array-reduce-transformation.js
diff --git a/javascript/2626-array-reduce-transformation.js b/javascript/2626-array-reduce-transformation.js
new file mode 100644
index 000000000..f695fe046
--- /dev/null
+++ b/javascript/2626-array-reduce-transformation.js
@@ -0,0 +1,12 @@
+/**
+ * @param {number[]} nums
+ * @param {Function} fn
+ * @param {number} init
+ * @return {number}
+ */
+var reduce = function (nums, fn, init) {
+ ans = init;
+ for (let n of nums)
+ ans = fn(ans, n);
+ return ans;
+};
From 07c3c1410e2b5ee242d8866f52ef4003827d7662 Mon Sep 17 00:00:00 2001
From: "David M."
Date: Tue, 12 Nov 2024 00:46:50 +0100
Subject: [PATCH 04/67] Create 2629-function-composition.js
---
javascript/2629-function-composition.js | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 javascript/2629-function-composition.js
diff --git a/javascript/2629-function-composition.js b/javascript/2629-function-composition.js
new file mode 100644
index 000000000..6899a5d4e
--- /dev/null
+++ b/javascript/2629-function-composition.js
@@ -0,0 +1,17 @@
+/**
+ * @param {Function[]} functions
+ * @return {Function}
+ */
+var compose = function (functions) {
+ return function (x) {
+ let ans = x;
+ for (fn of functions.reverse())
+ ans = fn(ans);
+ return ans;
+ }
+};
+
+/**
+ * const fn = compose([x => x + 1, x => 2 * x])
+ * fn(4) // 9
+ */
From 726b00e3d70eafb4ccde23d3b82e858712a70793 Mon Sep 17 00:00:00 2001
From: "David M."
Date: Tue, 12 Nov 2024 00:54:01 +0100
Subject: [PATCH 05/67] Create 2666-allow-one-function-call.js
---
javascript/2666-allow-one-function-call.js | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 javascript/2666-allow-one-function-call.js
diff --git a/javascript/2666-allow-one-function-call.js b/javascript/2666-allow-one-function-call.js
new file mode 100644
index 000000000..34afa8fba
--- /dev/null
+++ b/javascript/2666-allow-one-function-call.js
@@ -0,0 +1,21 @@
+/**
+ * @param {Function} fn
+ * @return {Function}
+ */
+var once = function (fn) {
+ let called = false;
+ return function (...args) {
+ if (!called) {
+ called = true;
+ return fn(...args);
+ }
+ }
+};
+
+/**
+ * let fn = (a,b,c) => (a + b + c)
+ * let onceFn = once(fn)
+ *
+ * onceFn(1,2,3); // 6
+ * onceFn(2,3,6); // returns undefined without calling fn
+ */
From 05470317fc13853b7f2c33a268cec668915affa5 Mon Sep 17 00:00:00 2001
From: "David M."
Date: Tue, 12 Nov 2024 00:57:43 +0100
Subject: [PATCH 06/67] Create 2623-memoize.js
---
javascript/2623-memoize.js | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 javascript/2623-memoize.js
diff --git a/javascript/2623-memoize.js b/javascript/2623-memoize.js
new file mode 100644
index 000000000..9fd662e49
--- /dev/null
+++ b/javascript/2623-memoize.js
@@ -0,0 +1,24 @@
+/**
+ * @param {Function} fn
+ * @return {Function}
+ */
+function memoize(fn) {
+ let memo = {};
+ return function (...args) {
+ let argsjson = JSON.stringify(args);
+ if (memo.hasOwnProperty(argsjson))
+ return memo[argsjson];
+ return memo[argsjson] = fn(...args);
+ }
+}
+
+/**
+ * let callCount = 0;
+ * const memoizedFn = memoize(function (a, b) {
+ * callCount += 1;
+ * return a + b;
+ * })
+ * memoizedFn(2, 3) // 5
+ * memoizedFn(2, 3) // 5
+ * console.log(callCount) // 1
+ */
From 2a1072bd62ce7bb766aae8ecd0d8fc0c691b6830 Mon Sep 17 00:00:00 2001
From: "David M."
Date: Tue, 12 Nov 2024 01:03:03 +0100
Subject: [PATCH 07/67] Create 2632-curry.js
---
javascript/2632-curry.js | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 javascript/2632-curry.js
diff --git a/javascript/2632-curry.js b/javascript/2632-curry.js
new file mode 100644
index 000000000..ed6ee86bb
--- /dev/null
+++ b/javascript/2632-curry.js
@@ -0,0 +1,20 @@
+/**
+ * @param {Function} fn
+ * @return {Function}
+ */
+var curry = function (fn) {
+ let accum = [];
+ return function curried(...args) {
+ for (let arg of args)
+ accum.push(arg);
+ if (accum.length === fn.length)
+ return fn(...accum);
+ return curried;
+ }
+};
+
+/**
+ * function sum(a, b) { return a + b; }
+ * const csum = curry(sum);
+ * csum(1)(2) // 3
+ */
From 923eb60dbae0aeb1dc84252cc64165f232e1812a Mon Sep 17 00:00:00 2001
From: "David M."
Date: Tue, 12 Nov 2024 01:08:58 +0100
Subject: [PATCH 08/67] Create 2621-sleep.js
---
javascript/2621-sleep.js | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 javascript/2621-sleep.js
diff --git a/javascript/2621-sleep.js b/javascript/2621-sleep.js
new file mode 100644
index 000000000..3e79979bf
--- /dev/null
+++ b/javascript/2621-sleep.js
@@ -0,0 +1,12 @@
+/**
+ * @param {number} millis
+ * @return {Promise}
+ */
+async function sleep(millis) {
+ return new Promise(resolve => setTimeout(() => resolve("Completed!"), millis));
+}
+
+/**
+ * let t = Date.now()
+ * sleep(100).then(() => console.log(Date.now() - t)) // 100
+ */
From 48bba06c897d226180dddb1bb7b693fa06882d80 Mon Sep 17 00:00:00 2001
From: "David M."
Date: Wed, 13 Nov 2024 07:54:53 +0100
Subject: [PATCH 09/67] Create 2634-filter-elements-from-array.js (#3731)
---
javascript/2634-filter-elements-from-array.js | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 javascript/2634-filter-elements-from-array.js
diff --git a/javascript/2634-filter-elements-from-array.js b/javascript/2634-filter-elements-from-array.js
new file mode 100644
index 000000000..57ff4277c
--- /dev/null
+++ b/javascript/2634-filter-elements-from-array.js
@@ -0,0 +1,12 @@
+/**
+ * @param {number[]} arr
+ * @param {Function} fn
+ * @return {number[]}
+ */
+var filter = function (arr, fn) {
+ ans = [];
+ for (let i = 0; i < arr.length; i++)
+ if (fn(arr[i], i))
+ ans.push(arr[i]);
+ return ans;
+};
From f2facdccdc46110440397b45959eba0e4b14b9e9 Mon Sep 17 00:00:00 2001
From: Bot-A0 <71089234+Ahmad-A0@users.noreply.github.com>
Date: Wed, 13 Nov 2024 07:06:23 +0000
Subject: [PATCH 10/67] =?UTF-8?q?=F0=9F=93=9C=20Update=20README=20table=20?=
=?UTF-8?q?(=F0=9F=9B=A0=EF=B8=8F=20from=20Github=20Actions)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index c338b6ace..47165a764 100644
--- a/README.md
+++ b/README.md
@@ -542,7 +542,7 @@ If you would like to have collaborator permissions on the repo to merge your own
[2620 - Counter](https://leetcode.com/problems/counter/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2620-counter.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](typescript%2F2620-counter.ts)
[2665 - Counter II](https://leetcode.com/problems/counter-ii/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2665-counter-ii.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2635 - Apply Transform over each Element in Array](https://leetcode.com/problems/apply-transform-over-each-element-in-array/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2635-apply-transform-over-each-element-in-array.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[2634 - Filter Elements from Array](https://leetcode.com/problems/filter-elements-from-array/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
+[2634 - Filter Elements from Array](https://leetcode.com/problems/filter-elements-from-array/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2634-filter-elements-from-array.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2626 - Array Reduce Transformation](https://leetcode.com/problems/array-reduce-transformation/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2629 - Function Composition](https://leetcode.com/problems/function-composition/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2666 - Allow One Function Call](https://leetcode.com/problems/allow-one-function-call/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
From cbf4fb27f80be744f2c387cfed99c87451d7fba2 Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Thu, 14 Nov 2024 02:46:29 +0530
Subject: [PATCH 11/67] Sri Hari: Batch-3/Neetcode-150/Added Golang, Kotlin
(#3739)
* Added Golang, Kotlin
* Added Golang, Kotlin
---
articles/count-connected-components.md | 236 ++++++++++++++++++++++
articles/counting-bits.md | 138 ++++++++++++-
articles/foreign-dictionary.md | 248 +++++++++++++++++++++++
articles/islands-and-treasure.md | 267 +++++++++++++++++++++++++
articles/meeting-schedule-ii.md | 261 ++++++++++++++++++++++++
articles/meeting-schedule.md | 104 ++++++++++
articles/missing-number.md | 105 ++++++++++
articles/reverse-integer.md | 139 +++++++++++++
articles/string-encode-and-decode.md | 119 +++++++++++
articles/sum-of-two-integers.md | 112 +++++++++++
articles/valid-tree.md | 232 +++++++++++++++++++++
11 files changed, 1960 insertions(+), 1 deletion(-)
diff --git a/articles/count-connected-components.md b/articles/count-connected-components.md
index 2b57b16dd..0f0dc28ba 100644
--- a/articles/count-connected-components.md
+++ b/articles/count-connected-components.md
@@ -165,6 +165,70 @@ public class Solution {
}
```
+```go
+func countComponents(n int, edges [][]int) int {
+ adj := make([][]int, n)
+ visit := make([]bool, n)
+ for _, edge := range edges {
+ u, v := edge[0], edge[1]
+ adj[u] = append(adj[u], v)
+ adj[v] = append(adj[v], u)
+ }
+
+ var dfs func(int)
+ dfs = func(node int) {
+ for _, nei := range adj[node] {
+ if !visit[nei] {
+ visit[nei] = true
+ dfs(nei)
+ }
+ }
+ }
+
+ res := 0
+ for node := 0; node < n; node++ {
+ if !visit[node] {
+ visit[node] = true
+ dfs(node)
+ res++
+ }
+ }
+ return res
+}
+```
+
+```kotlin
+class Solution {
+ fun countComponents(n: Int, edges: Array): Int {
+ val adj = Array(n) { mutableListOf() }
+ val visit = BooleanArray(n)
+ for ((u, v) in edges) {
+ adj[u].add(v)
+ adj[v].add(u)
+ }
+
+ fun dfs(node: Int) {
+ for (nei in adj[node]) {
+ if (!visit[nei]) {
+ visit[nei] = true
+ dfs(nei)
+ }
+ }
+ }
+
+ var res = 0
+ for (node in 0 until n) {
+ if (!visit[node]) {
+ visit[node] = true
+ dfs(node)
+ res++
+ }
+ }
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -369,6 +433,79 @@ public class Solution {
}
```
+```go
+func countComponents(n int, edges [][]int) int {
+ adj := make([][]int, n)
+ visit := make([]bool, n)
+ for _, edge := range edges {
+ u, v := edge[0], edge[1]
+ adj[u] = append(adj[u], v)
+ adj[v] = append(adj[v], u)
+ }
+
+ bfs := func(node int) {
+ q := []int{node}
+ visit[node] = true
+ for len(q) > 0 {
+ cur := q[0]
+ q = q[1:]
+ for _, nei := range adj[cur] {
+ if !visit[nei] {
+ visit[nei] = true
+ q = append(q, nei)
+ }
+ }
+ }
+ }
+
+ res := 0
+ for node := 0; node < n; node++ {
+ if !visit[node] {
+ bfs(node)
+ res++
+ }
+ }
+ return res
+}
+```
+
+```kotlin
+class Solution {
+ fun countComponents(n: Int, edges: Array): Int {
+ val adj = Array(n) { mutableListOf() }
+ val visit = BooleanArray(n)
+ for ((u, v) in edges) {
+ adj[u].add(v)
+ adj[v].add(u)
+ }
+
+ fun bfs(node: Int) {
+ val q: Queue = LinkedList()
+ q.offer(node)
+ visit[node] = true
+ while (q.isNotEmpty()) {
+ val cur = q.poll()
+ for (nei in adj[cur]) {
+ if (!visit[nei]) {
+ visit[nei] = true
+ q.offer(nei)
+ }
+ }
+ }
+ }
+
+ var res = 0
+ for (node in 0 until n) {
+ if (!visit[node]) {
+ bfs(node)
+ res++
+ }
+ }
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -641,6 +778,105 @@ public class Solution {
}
```
+```go
+type DSU struct {
+ parent []int
+ rank []int
+}
+
+func NewDSU(n int) *DSU {
+ dsu := &DSU{
+ parent: make([]int, n),
+ rank: make([]int, n),
+ }
+ for i := 0; i < n; i++ {
+ dsu.parent[i] = i
+ dsu.rank[i] = 1
+ }
+ return dsu
+}
+
+func (dsu *DSU) Find(node int) int {
+ cur := node
+ for cur != dsu.parent[cur] {
+ dsu.parent[cur] = dsu.parent[dsu.parent[cur]]
+ cur = dsu.parent[cur]
+ }
+ return cur
+}
+
+func (dsu *DSU) Union(u, v int) bool {
+ pu := dsu.Find(u)
+ pv := dsu.Find(v)
+ if pu == pv {
+ return false
+ }
+ if dsu.rank[pv] > dsu.rank[pu] {
+ pu, pv = pv, pu
+ }
+ dsu.parent[pv] = pu
+ dsu.rank[pu] += dsu.rank[pv]
+ return true
+}
+
+func countComponents(n int, edges [][]int) int {
+ dsu := NewDSU(n)
+ res := n
+ for _, edge := range edges {
+ u, v := edge[0], edge[1]
+ if dsu.Union(u, v) {
+ res--
+ }
+ }
+ return res
+}
+```
+
+```kotlin
+class DSU(n: Int) {
+ val parent = IntArray(n) { it }
+ val rank = IntArray(n) { 1 }
+
+ fun find(node: Int): Int {
+ var cur = node
+ while (cur != parent[cur]) {
+ parent[cur] = parent[parent[cur]]
+ cur = parent[cur]
+ }
+ return cur
+ }
+
+ fun union(u: Int, v: Int): Boolean {
+ val pu = find(u)
+ val pv = find(v)
+ if (pu == pv) {
+ return false
+ }
+ if (rank[pv] > rank[pu]) {
+ parent[pu] = pv
+ } else {
+ parent[pv] = pu
+ rank[pu] += rank[pv]
+ }
+ return true
+ }
+}
+
+class Solution {
+ fun countComponents(n: Int, edges: Array): Int {
+ val dsu = DSU(n)
+ var res = n
+ for (edge in edges) {
+ val (u, v) = edge
+ if (dsu.union(u, v)) {
+ res--
+ }
+ }
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/counting-bits.md b/articles/counting-bits.md
index a4135ebae..514bef953 100644
--- a/articles/counting-bits.md
+++ b/articles/counting-bits.md
@@ -86,6 +86,40 @@ public class Solution {
}
```
+```go
+func countBits(n int) []int {
+ res := make([]int, n+1)
+ for num := 0; num <= n; num++ {
+ one := 0
+ for i := 0; i < 32; i++ {
+ if num&(1<> 1] + (i & 1)
- return dp
+ return dp
```
```java
@@ -426,6 +540,28 @@ public class Solution {
}
```
+```go
+func countBits(n int) []int {
+ dp := make([]int, n+1)
+ for i := 1; i <= n; i++ {
+ dp[i] = dp[i >> 1] + (i&1);
+ }
+ return dp
+}
+```
+
+```kotlin
+class Solution {
+ fun countBits(n: Int): IntArray {
+ val dp = IntArray(n + 1)
+ for (i in 1..n) {
+ dp[i] = dp[i shr 1] + (i and 1)
+ }
+ return dp
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/foreign-dictionary.md b/articles/foreign-dictionary.md
index 199b0b642..f1353b74a 100644
--- a/articles/foreign-dictionary.md
+++ b/articles/foreign-dictionary.md
@@ -282,6 +282,129 @@ public class Solution {
}
```
+```go
+func foreignDictionary(words []string) string {
+ adj := make(map[rune]map[rune]struct{})
+ for _, w := range words {
+ for _, c := range w {
+ if _, exists := adj[c]; !exists {
+ adj[c] = make(map[rune]struct{})
+ }
+ }
+ }
+
+ for i := 0; i < len(words)-1; i++ {
+ w1, w2 := words[i], words[i+1]
+ minLen := len(w1)
+ if len(w2) < minLen {
+ minLen = len(w2)
+ }
+ if len(w1) > len(w2) && w1[:minLen] == w2[:minLen] {
+ return ""
+ }
+ for j := 0; j < minLen; j++ {
+ if w1[j] != w2[j] {
+ adj[rune(w1[j])][rune(w2[j])] = struct{}{}
+ break
+ }
+ }
+ }
+
+ visited := make(map[rune]int)
+ var res []rune
+
+ var dfs func(char rune) bool
+ dfs = func(char rune) bool {
+ if status, exists := visited[char]; exists {
+ return status == 1
+ }
+
+ visited[char] = 1
+
+ for neighChar := range adj[char] {
+ if dfs(neighChar) {
+ return true
+ }
+ }
+
+ visited[char] = -1
+ res = append(res, char)
+ return false
+ }
+
+ for char := range adj {
+ if dfs(char) {
+ return ""
+ }
+ }
+
+ var result []byte
+ for i := len(res) - 1; i >= 0; i-- {
+ result = append(result, byte(res[i]))
+ }
+
+ return string(result)
+}
+```
+
+```kotlin
+class Solution {
+ fun foreignDictionary(words: Array): String {
+ val adj = HashMap>()
+ for (w in words) {
+ for (c in w) {
+ adj.putIfAbsent(c, hashSetOf())
+ }
+ }
+
+ for (i in 0 until words.size - 1) {
+ val w1 = words[i]
+ val w2 = words[i + 1]
+ val minLen = minOf(w1.length, w2.length)
+ if (w1.length > w2.length &&
+ w1.substring(0, minLen) == w2.substring(0, minLen)) {
+ return ""
+ }
+ for (j in 0 until minLen) {
+ if (w1[j] != w2[j]) {
+ adj[w1[j]]?.add(w2[j])
+ break
+ }
+ }
+ }
+
+ val visited = HashMap()
+ val res = mutableListOf()
+
+ fun dfs(char: Char): Boolean {
+ if (char in visited) {
+ return visited[char] == 1
+ }
+
+ visited[char] = 1
+
+ for (neighChar in adj[char] ?: emptySet()) {
+ if (dfs(neighChar)) {
+ return true
+ }
+ }
+
+ visited[char] = -1
+ res.add(char)
+ return false
+ }
+
+ for (char in adj.keys) {
+ if (dfs(char)) {
+ return ""
+ }
+ }
+
+ return res.reversed().joinToString("")
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -575,6 +698,131 @@ public class Solution {
}
```
+```go
+func foreignDictionary(words []string) string {
+ adj := make(map[byte]map[byte]struct{})
+ indegree := make(map[byte]int)
+
+ for _, word := range words {
+ for i := 0; i < len(word); i++ {
+ char := word[i]
+ if _, exists := adj[char]; !exists {
+ adj[char] = make(map[byte]struct{})
+ }
+ indegree[char] = 0
+ }
+ }
+
+ for i := 0; i < len(words)-1; i++ {
+ w1, w2 := words[i], words[i+1]
+ minLen := len(w1)
+ if len(w2) < minLen {
+ minLen = len(w2)
+ }
+
+ if len(w1) > len(w2) && w1[:minLen] == w2[:minLen] {
+ return ""
+ }
+
+ for j := 0; j < minLen; j++ {
+ if w1[j] != w2[j] {
+ if _, exists := adj[w1[j]][w2[j]]; !exists {
+ adj[w1[j]][w2[j]] = struct{}{}
+ indegree[w2[j]]++
+ }
+ break
+ }
+ }
+ }
+
+ q := []byte{}
+ for char := range indegree {
+ if indegree[char] == 0 {
+ q = append(q, char)
+ }
+ }
+
+ res := []byte{}
+ for len(q) > 0 {
+ char := q[0]
+ q = q[1:]
+ res = append(res, char)
+
+ for neighbor := range adj[char] {
+ indegree[neighbor]--
+ if indegree[neighbor] == 0 {
+ q = append(q, neighbor)
+ }
+ }
+ }
+
+ if len(res) != len(indegree) {
+ return ""
+ }
+
+ return string(res)
+}
+```
+
+```kotlin
+class Solution {
+ fun foreignDictionary(words: Array): String {
+ val adj = HashMap>()
+ val indegree = HashMap()
+
+ for (word in words) {
+ for (c in word) {
+ adj.computeIfAbsent(c) { hashSetOf() }
+ indegree[c] = 0
+ }
+ }
+
+ for (i in 0 until words.size - 1) {
+ val w1 = words[i]
+ val w2 = words[i + 1]
+ val minLen = minOf(w1.length, w2.length)
+
+ if (w1.length > w2.length &&
+ w1.substring(0, minLen) == w2.substring(0, minLen)) {
+ return ""
+ }
+
+ for (j in 0 until minLen) {
+ if (w1[j] != w2[j]) {
+ if (w2[j] !in adj[w1[j]]!!) {
+ adj[w1[j]]!!.add(w2[j])
+ indegree[w2[j]] = indegree[w2[j]]!! + 1
+ }
+ break
+ }
+ }
+ }
+
+ val q: Queue = LinkedList()
+ for ((char, degree) in indegree) {
+ if (degree == 0) {
+ q.add(char)
+ }
+ }
+
+ val res = StringBuilder()
+ while (q.isNotEmpty()) {
+ val char = q.poll()
+ res.append(char)
+
+ for (neighbor in adj[char]!!) {
+ indegree[neighbor] = indegree[neighbor]!! - 1
+ if (indegree[neighbor] == 0) {
+ q.add(neighbor)
+ }
+ }
+ }
+
+ return if (res.length != indegree.size) "" else res.toString()
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/islands-and-treasure.md b/articles/islands-and-treasure.md
index 69eae6e57..ff99ef107 100644
--- a/articles/islands-and-treasure.md
+++ b/articles/islands-and-treasure.md
@@ -208,6 +208,100 @@ public class Solution {
}
```
+```go
+func islandsAndTreasure(grid [][]int) {
+ rows, cols := len(grid), len(grid[0])
+ directions := [][]int{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}
+ INF := 2147483647
+ visit := make([][]bool, rows)
+ for i := range visit {
+ visit[i] = make([]bool, cols)
+ }
+
+ var dfs func(r, c int) int
+ dfs = func(r, 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
+ res := INF
+ for _, d := range directions {
+ dx, dy := d[0], d[1]
+ res = min(res, 1+dfs(r+dx, c+dy))
+ }
+ visit[r][c] = false
+ return res
+ }
+
+ for r := 0; r < rows; r++ {
+ for c := 0; c < cols; c++ {
+ if grid[r][c] == INF {
+ grid[r][c] = dfs(r, c)
+ }
+ }
+ }
+}
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+```
+
+```kotlin
+class Solution {
+ private val directions = arrayOf(
+ intArrayOf(1, 0), intArrayOf(-1, 0),
+ intArrayOf(0, 1), intArrayOf(0, -1)
+ )
+ private val INF = 2147483647
+ private lateinit var visit: Array
+ private var rows = 0
+ private var cols = 0
+
+ private fun dfs(grid: Array, 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 (dir in directions) {
+ val cur = dfs(grid, r + dir[0], c + dir[1])
+ if (cur != INF) {
+ res = minOf(res, 1 + cur)
+ }
+ }
+ visit[r][c] = false
+ return res
+ }
+
+ fun islandsAndTreasure(grid: Array): Unit {
+ rows = grid.size
+ cols = grid[0].size
+ visit = Array(rows) { BooleanArray(cols) }
+
+ for (r in 0 until rows) {
+ for (c in 0 until cols) {
+ if (grid[r][c] == INF) {
+ grid[r][c] = dfs(grid, r, c)
+ }
+ }
+ }
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -458,6 +552,105 @@ public class Solution {
}
```
+```go
+func islandsAndTreasure(grid [][]int) {
+ rows, cols := len(grid), len(grid[0])
+ directions := [][]int{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}
+ INF := 2147483647
+
+ bfs := func(r, c int) int {
+ q := [][2]int{{r, c}}
+ visit := make([][]bool, rows)
+ for i := range visit {
+ visit[i] = make([]bool, cols)
+ }
+ visit[r][c] = true
+ steps := 0
+
+ for len(q) > 0 {
+ size := len(q)
+ for i := 0; i < size; i++ {
+ current := q[0]
+ q = q[1:]
+ row, col := current[0], current[1]
+ if grid[row][col] == 0 {
+ return steps
+ }
+ for _, dir := range directions {
+ nr, nc := row+dir[0], col+dir[1]
+ if nr >= 0 && nc >= 0 && nr < rows && nc < cols &&
+ !visit[nr][nc] && grid[nr][nc] != -1 {
+ visit[nr][nc] = true
+ q = append(q, [2]int{nr, nc})
+ }
+ }
+ }
+ steps++
+ }
+ return INF
+ }
+
+ for r := 0; r < rows; r++ {
+ for c := 0; c < cols; c++ {
+ if grid[r][c] == INF {
+ grid[r][c] = bfs(r, c)
+ }
+ }
+ }
+}
+```
+
+```kotlin
+class Solution {
+ private val directions = arrayOf(
+ intArrayOf(1, 0), intArrayOf(-1, 0),
+ intArrayOf(0, 1), intArrayOf(0, -1)
+ )
+ private val INF = 2147483647
+
+ fun islandsAndTreasure(grid: Array): Unit {
+ val rows = grid.size
+ val cols = grid[0].size
+
+ fun bfs(r: Int, c: Int): Int {
+ val q = ArrayDeque>()
+ q.add(Pair(r, c))
+ val visit = Array(rows) { BooleanArray(cols) }
+ visit[r][c] = true
+ var steps = 0
+
+ while (q.isNotEmpty()) {
+ repeat(q.size) {
+ val (row, col) = q.removeFirst()
+ if (grid[row][col] == 0) {
+ return steps
+ }
+ for (dir in directions) {
+ val nr = row + dir[0]
+ val nc = col + dir[1]
+ if (nr in 0 until rows && nc in 0 until cols &&
+ !visit[nr][nc] && grid[nr][nc] != -1) {
+ visit[nr][nc] = true
+ q.add(Pair(nr, nc))
+ }
+ }
+ }
+ steps++
+ }
+ return INF
+ }
+
+ for (r in 0 until rows) {
+ for (c in 0 until cols) {
+ if (grid[r][c] == INF) {
+ grid[r][c] = bfs(r, c)
+ }
+ }
+ }
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -671,6 +864,80 @@ public class Solution {
}
```
+```go
+func islandsAndTreasure(grid [][]int) {
+ m, n := len(grid), len(grid[0])
+ q := [][2]int{}
+
+ for i := 0; i < m; i++ {
+ for j := 0; j < n; j++ {
+ if grid[i][j] == 0 {
+ q = append(q, [2]int{i, j})
+ }
+ }
+ }
+ if len(q) == 0 {
+ return
+ }
+
+ dirs := [][]int{{-1, 0}, {0, -1}, {1, 0}, {0, 1}}
+
+ for len(q) > 0 {
+ node := q[0]
+ q = q[1:]
+ row, col := node[0], node[1]
+
+ for _, dir := range dirs {
+ r, c := row+dir[0], col+dir[1]
+ if r >= m || c >= n || r < 0 || c < 0 ||
+ grid[r][c] != 2147483647 {
+ continue
+ }
+ q = append(q, [2]int{r, c})
+ grid[r][c] = grid[row][col] + 1
+ }
+ }
+}
+```
+
+```kotlin
+class Solution {
+ fun islandsAndTreasure(grid: Array): Unit {
+ val m = grid.size
+ val n = grid[0].size
+ val q: Queue> = LinkedList()
+
+ for (i in 0 until m) {
+ for (j in 0 until n) {
+ if (grid[i][j] == 0) {
+ q.add(Pair(i, j))
+ }
+ }
+ }
+ if (q.isEmpty()) return
+
+ val dirs = arrayOf(
+ intArrayOf(-1, 0), intArrayOf(0, -1),
+ intArrayOf(1, 0), intArrayOf(0, 1)
+ )
+
+ while (q.isNotEmpty()) {
+ val (row, col) = q.poll()
+ for (dir in dirs) {
+ val r = row + dir[0]
+ val c = col + dir[1]
+ if (r !in 0 until m || c !in 0 until n ||
+ grid[r][c] != Int.MAX_VALUE) {
+ continue
+ }
+ q.add(Pair(r, c))
+ grid[r][c] = grid[row][col] + 1
+ }
+ }
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/meeting-schedule-ii.md b/articles/meeting-schedule-ii.md
index 1d41af505..ce53b1e92 100644
--- a/articles/meeting-schedule-ii.md
+++ b/articles/meeting-schedule-ii.md
@@ -141,6 +141,58 @@ public class Solution {
}
```
+```go
+/**
+ * Definition of Interval:
+ * type Interval struct {
+ * start int
+ * end int
+ * }
+ */
+
+func minMeetingRooms(intervals []Interval) int {
+ sort.Slice(intervals, func(i, j int) bool {
+ return intervals[i].start < intervals[j].start
+ })
+
+ pq := priorityqueue.NewWith(utils.IntComparator)
+
+ for _, interval := range intervals {
+ if pq.Size() > 0 {
+ if top, _ := pq.Peek(); top.(int) <= interval.start {
+ pq.Dequeue()
+ }
+ }
+ pq.Enqueue(interval.end)
+ }
+
+ return pq.Size()
+}
+```
+
+```kotlin
+/**
+ * Definition of Interval:
+ * class Interval(var start: Int, var end: Int) {}
+ */
+
+class Solution {
+ fun minMeetingRooms(intervals: List): Int {
+ intervals.sortBy { it.start }
+
+ val minHeap = PriorityQueue()
+ for (interval in intervals) {
+ if (minHeap.isNotEmpty() && minHeap.peek() <= interval.start) {
+ minHeap.poll()
+ }
+ minHeap.add(interval.end)
+ }
+
+ return minHeap.size
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -302,6 +354,66 @@ public class Solution {
}
```
+```go
+/**
+ * Definition of Interval:
+ * type Interval struct {
+ * start int
+ * end int
+ * }
+ */
+
+func minMeetingRooms(intervals []Interval) int {
+ mp := make(map[int]int)
+ for _, i := range intervals {
+ mp[i.start]++
+ mp[i.end]--
+ }
+
+ keys := make([]int, 0, len(mp))
+ for k := range mp {
+ keys = append(keys, k)
+ }
+ sort.Ints(keys)
+
+ prev := 0
+ res := 0
+ for _, k := range keys {
+ prev += mp[k]
+ if prev > res {
+ res = prev
+ }
+ }
+ return res
+}
+```
+
+```kotlin
+/**
+ * Definition of Interval:
+ * class Interval(var start: Int, var end: Int) {}
+ */
+
+class Solution {
+ fun minMeetingRooms(intervals: List): Int {
+ val mp = HashMap()
+ for (i in intervals) {
+ mp[i.start] = mp.getOrDefault(i.start, 0) + 1
+ mp[i.end] = mp.getOrDefault(i.end, 0) - 1
+ }
+
+ val keys = mp.keys.sorted()
+ var prev = 0
+ var res = 0
+ for (k in keys) {
+ prev += mp[k]!!
+ res = maxOf(res, prev)
+ }
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -504,6 +616,79 @@ public class Solution {
}
```
+```go
+/**
+ * Definition of Interval:
+ * type Interval struct {
+ * start int
+ * end int
+ * }
+ */
+
+func minMeetingRooms(intervals []Interval) int {
+ start := make([]int, len(intervals))
+ end := make([]int, len(intervals))
+
+ for i, interval := range intervals {
+ start[i] = interval.start
+ end[i] = interval.end
+ }
+
+ sort.Ints(start)
+ sort.Ints(end)
+
+ res, count := 0, 0
+ s, e := 0, 0
+
+ for s < len(intervals) {
+ if start[s] < end[e] {
+ s++
+ count++
+ } else {
+ e++
+ count--
+ }
+ if count > res {
+ res = count
+ }
+ }
+
+ return res
+}
+```
+
+```kotlin
+/**
+ * Definition of Interval:
+ * class Interval(var start: Int, var end: Int) {}
+ */
+
+class Solution {
+ fun minMeetingRooms(intervals: List): Int {
+ val start = intervals.map { it.start }.sorted()
+ val end = intervals.map { it.end }.sorted()
+
+ var res = 0
+ var count = 0
+ var s = 0
+ var e = 0
+
+ while (s < intervals.size) {
+ if (start[s] < end[e]) {
+ s++
+ count++
+ } else {
+ e++
+ count--
+ }
+ res = maxOf(res, count)
+ }
+
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -543,6 +728,17 @@ class Solution:
```
```java
+/**
+ * Definition of Interval:
+ * public class Interval {
+ * public int start, end;
+ * public Interval(int start, int end) {
+ * this.start = start;
+ * this.end = end;
+ * }
+ * }
+ */
+
public class Solution {
public int minMeetingRooms(List intervals) {
List time = new ArrayList<>();
@@ -668,6 +864,71 @@ public class Solution {
}
```
+```go
+/**
+ * Definition of Interval:
+ * type Interval struct {
+ * start int
+ * end int
+ * }
+ */
+
+func minMeetingRooms(intervals []Interval) int {
+ var time [][]int
+ for _, i := range intervals {
+ time = append(time, []int{i.start, 1})
+ time = append(time, []int{i.end, -1})
+ }
+
+ sort.Slice(time, func(i, j int) bool {
+ if time[i][0] == time[j][0] {
+ return time[i][1] < time[j][1]
+ }
+ return time[i][0] < time[j][0]
+ })
+
+ res, count := 0, 0
+ for _, t := range time {
+ count += t[1]
+ if count > res {
+ res = count
+ }
+ }
+ return res
+}
+```
+
+```kotlin
+/**
+ * Definition of Interval:
+ * class Interval(var start: Int, var end: Int) {}
+ */
+
+class Solution {
+ fun minMeetingRooms(intervals: Array): Int {
+ val time = mutableListOf>()
+
+ for (i in intervals) {
+ time.add(Pair(i.start, 1))
+ time.add(Pair(i.end, -1))
+ }
+
+ time.sortWith(compareBy> { it.first }
+ .thenBy { it.second })
+
+ var res = 0
+ var count = 0
+
+ for (t in time) {
+ count += t.second
+ res = maxOf(res, count)
+ }
+
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/meeting-schedule.md b/articles/meeting-schedule.md
index b4e32f6fc..735df876a 100644
--- a/articles/meeting-schedule.md
+++ b/articles/meeting-schedule.md
@@ -144,6 +144,67 @@ public class Solution {
}
```
+```go
+/**
+ * Definition of Interval:
+ * type Interval struct {
+ * start int
+ * end int
+ * }
+ */
+
+func canAttendMeetings(intervals []Interval) bool {
+ n := len(intervals)
+ for i := 0; i < n; i++ {
+ A := intervals[i]
+ for j := i + 1; j < n; j++ {
+ B := intervals[j]
+ if min(A.end, B.end) > max(A.start, B.start) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+```
+
+```kotlin
+/**
+ * Definition of Interval:
+ * class Interval(var start: Int, var end: Int) {}
+ */
+
+class Solution {
+ fun canAttendMeetings(intervals: List): Boolean {
+ val n = intervals.size
+ for (i in 0 until n) {
+ val A = intervals[i]
+ for (j in i + 1 until n) {
+ val B = intervals[j]
+ if (minOf(A.end, B.end) > maxOf(A.start, B.start)) {
+ return false
+ }
+ }
+ }
+ return true
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -296,6 +357,49 @@ public class Solution {
}
```
+```go
+/**
+* Definition of Interval:
+* type Interval struct {
+* start int
+* end int
+* }
+*/
+
+func canAttendMeetings(intervals []Interval) bool {
+ sort.Slice(intervals, func(i, j int) bool {
+ return intervals[i].start < intervals[j].start
+ })
+
+ for i := 1; i < len(intervals); i++ {
+ if intervals[i-1].end > intervals[i].start {
+ return false
+ }
+ }
+ return true
+}
+```
+
+```kotlin
+/**
+ * Definition of Interval:
+ * class Interval(var start: Int, var end: Int) {}
+ */
+
+class Solution {
+ fun canAttendMeetings(intervals: List): Boolean {
+ intervals.sortedBy { it.start }.let {
+ for (i in 1 until it.size) {
+ if (it[i - 1].end > it[i].start) {
+ return false
+ }
+ }
+ }
+ return true
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/missing-number.md b/articles/missing-number.md
index a1307153d..0ddb891db 100644
--- a/articles/missing-number.md
+++ b/articles/missing-number.md
@@ -78,6 +78,34 @@ public class Solution {
}
```
+```go
+func missingNumber(nums []int) int {
+ n := len(nums)
+ sort.Ints(nums)
+ for i := 0; i < n; i++ {
+ if nums[i] != i {
+ return i
+ }
+ }
+ return n
+}
+```
+
+```kotlin
+class Solution {
+ fun missingNumber(nums: IntArray): Int {
+ val n = nums.size
+ nums.sort()
+ for (i in 0 until n) {
+ if (nums[i] != i) {
+ return i
+ }
+ }
+ return n
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -168,6 +196,37 @@ public class Solution {
}
```
+```go
+func missingNumber(nums []int) int {
+ numSet := make(map[int]struct{})
+ for _, num := range nums {
+ numSet[num] = struct{}{}
+ }
+ n := len(nums)
+ for i := 0; i <= n; i++ {
+ if _, exists := numSet[i]; !exists {
+ return i
+ }
+ }
+ return -1
+}
+```
+
+```kotlin
+class Solution {
+ fun missingNumber(nums: IntArray): Int {
+ val numSet = nums.toSet()
+ val n = nums.size
+ for (i in 0..n) {
+ if (i !in numSet) {
+ return i
+ }
+ }
+ return -1
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -248,6 +307,30 @@ public class Solution {
}
```
+```go
+func missingNumber(nums []int) int {
+ n := len(nums)
+ xorr := n
+ for i := 0; i < n; i++ {
+ xorr ^= i ^ nums[i]
+ }
+ return xorr
+}
+```
+
+```kotlin
+class Solution {
+ fun missingNumber(nums: IntArray): Int {
+ val n = nums.size
+ var xorr = n
+ for (i in 0 until n) {
+ xorr = xorr xor i xor nums[i]
+ }
+ return xorr
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -328,6 +411,28 @@ public class Solution {
}
```
+```go
+func missingNumber(nums []int) int {
+ res := len(nums)
+ for i := 0; i < len(nums); i++ {
+ res += i - nums[i]
+ }
+ return res
+}
+```
+
+```kotlin
+class Solution {
+ fun missingNumber(nums: IntArray): Int {
+ var res = nums.size
+ for (i in nums.indices) {
+ res += i - nums[i]
+ }
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/reverse-integer.md b/articles/reverse-integer.md
index d5a9d306b..f6d060a33 100644
--- a/articles/reverse-integer.md
+++ b/articles/reverse-integer.md
@@ -96,6 +96,57 @@ public class Solution {
}
```
+```go
+func reverse(x int) int {
+ org := x
+ x = abs(x)
+ res := 0
+
+ for x > 0 {
+ res = res*10 + x%10
+ x /= 10
+ }
+
+ if org < 0 {
+ res = -res
+ }
+ if res < -(1 << 31) || res > (1<<31)-1 {
+ return 0
+ }
+ return res
+}
+
+func abs(x int) int {
+ if x < 0 {
+ return -x
+ }
+ return x
+}
+```
+
+```kotlin
+class Solution {
+ fun reverse(x: Int): Int {
+ val org = x
+ var num = Math.abs(x)
+ var res = 0
+
+ while (num > 0) {
+ if (res > (Int.MAX_VALUE - num % 10) / 10) {
+ return 0
+ }
+ res = res * 10 + num % 10
+ num /= 10
+ }
+
+ if (org < 0) {
+ res = -res
+ }
+ return if (res < Int.MIN_VALUE || res > Int.MAX_VALUE) 0 else res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -220,6 +271,45 @@ public class Solution {
}
```
+```go
+func reverse(x int) int {
+ var rec func(int, int) int
+ rec = func(n, rev int) int {
+ if n == 0 {
+ return rev
+ }
+ rev = rev*10 + n%10
+ return rec(n/10, rev)
+ }
+
+ sign := 1
+ if x < 0 {
+ sign = -1
+ x = -x
+ }
+
+ reversedNum := rec(x, 0) * sign
+ if reversedNum < -(1<<31) || reversedNum > (1<<31)-1 {
+ return 0
+ }
+ return reversedNum
+}
+```
+
+```kotlin
+class Solution {
+ fun reverse(x: Int): Int {
+ val res = rec(Math.abs(x), 0L) * if (x < 0) -1 else 1
+ return if (res < Int.MIN_VALUE || res > Int.MAX_VALUE) 0 else res.toInt()
+ }
+
+ private fun rec(n: Int, rev: Long): Long {
+ if (n == 0) return rev
+ return rec(n / 10, rev * 10 + n % 10)
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -350,6 +440,55 @@ public class Solution {
}
```
+```go
+func reverse(x int) int {
+ MIN := -2147483648 // -2^31
+ MAX := 2147483647 // 2^31 - 1
+
+ res := 0
+ for x != 0 {
+ digit := int(math.Mod(float64(x), 10))
+ x = int(float64(x) / 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
+}
+```
+
+```kotlin
+class Solution {
+ fun reverse(x: Int): Int {
+ val MIN = -2147483648 // -2^31
+ val MAX = 2147483647 // 2^31 - 1
+
+ var res = 0
+ var num = x
+ while (num != 0) {
+ val digit = (num % 10).toInt()
+ 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/string-encode-and-decode.md b/articles/string-encode-and-decode.md
index 8b02832fb..c0cad7e12 100644
--- a/articles/string-encode-and-decode.md
+++ b/articles/string-encode-and-decode.md
@@ -220,6 +220,68 @@ public class Solution {
}
```
+```go
+type Solution struct{}
+
+func (s *Solution) Encode(strs []string) string {
+ if len(strs) == 0 {
+ return ""
+ }
+ var sizes []string
+ for _, str := range strs {
+ sizes = append(sizes, strconv.Itoa(len(str)))
+ }
+ return strings.Join(sizes, ",") + "#" + strings.Join(strs, "")
+}
+
+func (s *Solution) Decode(encoded string) []string {
+ if encoded == "" {
+ return []string{}
+ }
+ parts := strings.SplitN(encoded, "#", 2)
+ sizes := strings.Split(parts[0], ",")
+ var res []string
+ i := 0
+ for _, sz := range sizes {
+ if sz == "" {
+ continue
+ }
+ length, _ := strconv.Atoi(sz)
+ res = append(res, parts[1][i:i+length])
+ i += length
+ }
+ return res
+}
+```
+
+```kotlin
+class Solution {
+ fun encode(strs: List): String {
+ if (strs.isEmpty()) return ""
+ val sizes = mutableListOf()
+ for (str in strs) {
+ sizes.add(str.length.toString())
+ }
+ return sizes.joinToString(",") + "#" + strs.joinToString("")
+ }
+
+ fun decode(encoded: String): List {
+ if (encoded.isEmpty()) return emptyList()
+ val parts = encoded.split("#", limit = 2)
+ val sizes = parts[0].split(",")
+ val res = mutableListOf()
+ var i = 0
+ for (sz in sizes) {
+ if (sz.isEmpty()) continue
+ val length = sz.toInt()
+ res.add(parts[1].substring(i, i + length))
+ i += length
+ }
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -387,6 +449,63 @@ public class Solution {
}
```
+```go
+type Solution struct{}
+
+func (s *Solution) Encode(strs []string) string {
+ res := ""
+ for _, str := range strs {
+ res += strconv.Itoa(len(str)) + "#" + str
+ }
+ return res
+}
+
+func (s *Solution) Decode(encoded string) []string {
+ res := []string{}
+ i := 0
+ for i < len(encoded) {
+ j := i
+ for encoded[j] != '#' {
+ j++
+ }
+ length, _ := strconv.Atoi(encoded[i:j])
+ i = j + 1
+ res = append(res, encoded[i:i+length])
+ i += length
+ }
+ return res
+}
+```
+
+```kotlin
+class Solution {
+
+ fun encode(strs: List): String {
+ val res = StringBuilder()
+ for (str in strs) {
+ res.append(str.length).append('#').append(str)
+ }
+ return res.toString()
+ }
+
+ fun decode(encoded: String): List {
+ val res = mutableListOf()
+ var i = 0
+ while (i < encoded.length) {
+ var j = i
+ while (encoded[j] != '#') {
+ j++
+ }
+ val length = encoded.substring(i, j).toInt()
+ i = j + 1
+ res.add(encoded.substring(i, i + length))
+ i += length
+ }
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/sum-of-two-integers.md b/articles/sum-of-two-integers.md
index 7212f1fc1..4fffcb35f 100644
--- a/articles/sum-of-two-integers.md
+++ b/articles/sum-of-two-integers.md
@@ -46,6 +46,20 @@ public class Solution {
}
```
+```go
+func getSum(a int, b int) int {
+ return a + b
+}
+```
+
+```kotlin
+class Solution {
+ fun getSum(a: Int, b: Int): Int {
+ return a + b
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -182,6 +196,60 @@ public class Solution {
}
```
+```go
+func getSum(a int, b int) int {
+ carry := 0
+ res := 0
+ mask := 0xFFFFFFFF
+
+ for i := 0; i < 32; i++ {
+ aBit := (a >> i) & 1
+ bBit := (b >> i) & 1
+ curBit := aBit ^ bBit ^ carry
+ if (aBit + bBit + carry) >= 2 {
+ carry = 1
+ } else {
+ carry = 0
+ }
+ if curBit == 1 {
+ res |= (1 << i)
+ }
+ }
+
+ if res > 0x7FFFFFFF {
+ res = ^(res ^ mask)
+ }
+
+ return res
+}
+```
+
+```kotlin
+class Solution {
+ fun getSum(a: Int, b: Int): Int {
+ var carry = 0
+ var res = 0
+ val mask = 0xFFFFFFFF.toInt()
+
+ for (i in 0 until 32) {
+ val aBit = (a shr i) and 1
+ val bBit = (b shr i) and 1
+ val curBit = aBit xor bBit xor carry
+ carry = if (aBit + bBit + carry >= 2) 1 else 0
+ if (curBit == 1) {
+ res = res or (1 shl i)
+ }
+ }
+
+ if (res > 0x7FFFFFFF) {
+ res = res.inv() xor mask
+ }
+
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -267,6 +335,50 @@ public class Solution {
}
```
+```go
+func getSum(a int, b int) int {
+ mask := 0xFFFFFFFF
+ maxInt := 0x7FFFFFFF
+
+ for b != 0 {
+ carry := (a & b) << 1
+ a = (a ^ b) & mask
+ b = carry & mask
+ }
+
+ if a <= maxInt {
+ return a
+ }
+ return ^(a ^ mask)
+}
+```
+
+```kotlin
+class Solution {
+ fun getSum(a: Int, b: Int): Int {
+ var carry = 0
+ var res = 0
+ val mask = 0xFFFFFFFF.toInt()
+
+ for (i in 0 until 32) {
+ val aBit = (a shr i) and 1
+ val bBit = (b shr i) and 1
+ val curBit = aBit xor bBit xor carry
+ carry = if (aBit + bBit + carry >= 2) 1 else 0
+ if (curBit == 1) {
+ res = res or (1 shl i)
+ }
+ }
+
+ if (res > 0x7FFFFFFF) {
+ res = res.inv() xor mask
+ }
+
+ return res
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
diff --git a/articles/valid-tree.md b/articles/valid-tree.md
index d4c8ea3c6..a343b676e 100644
--- a/articles/valid-tree.md
+++ b/articles/valid-tree.md
@@ -203,6 +203,69 @@ public class Solution {
}
```
+```go
+func validTree(n int, edges [][]int) bool {
+ if len(edges) > n-1 {
+ return false
+ }
+
+ adj := make([][]int, n)
+ for _, edge := range edges {
+ u, v := edge[0], edge[1]
+ adj[u] = append(adj[u], v)
+ adj[v] = append(adj[v], u)
+ }
+
+ visit := make(map[int]bool)
+ var dfs func(node, parent int) bool
+ dfs = func(node, parent int) bool {
+ if visit[node] {
+ return false
+ }
+ visit[node] = true
+ for _, nei := range adj[node] {
+ if nei == parent {
+ continue
+ }
+ if !dfs(nei, node) {
+ return false
+ }
+ }
+ return true
+ }
+
+ return dfs(0, -1) && len(visit) == n
+}
+```
+
+```kotlin
+class Solution {
+ fun validTree(n: Int, edges: Array): Boolean {
+ if (edges.size > n - 1) return false
+
+ val adj = Array(n) { mutableListOf() }
+ for ((u, v) in edges) {
+ adj[u].add(v)
+ adj[v].add(u)
+ }
+
+ val visit = HashSet()
+
+ fun dfs(node: Int, parent: Int): Boolean {
+ if (node in visit) return false
+ visit.add(node)
+ for (nei in adj[node]) {
+ if (nei == parent) continue
+ if (!dfs(nei, node)) return false
+ }
+ return true
+ }
+
+ return dfs(0, -1) && visit.size == n
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -405,6 +468,75 @@ public class Solution {
}
```
+```go
+func validTree(n int, edges [][]int) bool {
+ if len(edges) > n-1 {
+ return false
+ }
+
+ adj := make([][]int, n)
+ for _, edge := range edges {
+ u, v := edge[0], edge[1]
+ adj[u] = append(adj[u], v)
+ adj[v] = append(adj[v], u)
+ }
+
+ visit := make(map[int]bool)
+ q := [][2]int{{0, -1}} // (current node, parent node)
+ visit[0] = true
+
+ for len(q) > 0 {
+ node, parent := q[0][0], q[0][1]
+ q = q[1:]
+
+ for _, nei := range adj[node] {
+ if nei == parent {
+ continue
+ }
+ if visit[nei] {
+ return false
+ }
+ visit[nei] = true
+ q = append(q, [2]int{nei, node})
+ }
+ }
+
+ return len(visit) == n
+}
+```
+
+```kotlin
+class Solution {
+ fun validTree(n: Int, edges: Array): Boolean {
+ if (edges.size > n - 1) return false
+
+ val adj = Array(n) { mutableListOf() }
+ for ((u, v) in edges) {
+ adj[u].add(v)
+ adj[v].add(u)
+ }
+
+ val visit = mutableSetOf()
+ val q: Queue> = LinkedList() // Queue of (node, parent)
+ q.offer(0 to -1)
+ visit.add(0)
+
+ while (q.isNotEmpty()) {
+ val (node, parent) = q.poll()
+
+ for (nei in adj[node]) {
+ if (nei == parent) continue
+ if (nei in visit) return false
+ visit.add(nei)
+ q.offer(nei to node)
+ }
+ }
+
+ return visit.size == n
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
@@ -700,6 +832,106 @@ public class Solution {
}
```
+```go
+type DSU struct {
+ Parent []int
+ Size []int
+ Comps int
+}
+
+func NewDSU(n int) *DSU {
+ parent := make([]int, n+1)
+ size := make([]int, n+1)
+ for i := 0; i <= n; i++ {
+ parent[i] = i
+ size[i] = 1
+ }
+ return &DSU{Parent: parent, Size: size, Comps: n}
+}
+
+func (dsu *DSU) Find(node int) int {
+ if dsu.Parent[node] != node {
+ dsu.Parent[node] = dsu.Find(dsu.Parent[node])
+ }
+ return dsu.Parent[node]
+}
+
+func (dsu *DSU) Union(u, v int) bool {
+ pu, pv := dsu.Find(u), dsu.Find(v)
+ if pu == pv {
+ return false
+ }
+ dsu.Comps--
+ if dsu.Size[pu] < dsu.Size[pv] {
+ pu, pv = pv, pu
+ }
+ dsu.Size[pu] += dsu.Size[pv]
+ dsu.Parent[pv] = pu
+ return true
+}
+
+func (dsu *DSU) Components() int {
+ return dsu.Comps
+}
+
+func validTree(n int, edges [][]int) bool {
+ if len(edges) > n-1 {
+ return false
+ }
+ dsu := NewDSU(n)
+ for _, edge := range edges {
+ if !dsu.Union(edge[0], edge[1]) {
+ return false
+ }
+ }
+ return dsu.Components() == 1
+}
+```
+
+```kotlin
+class DSU(n: Int) {
+ private val parent = IntArray(n + 1) { it }
+ private val size = IntArray(n + 1) { 1 }
+ var comps = n
+ private set
+
+ fun find(node: Int): Int {
+ if (parent[node] != node) {
+ parent[node] = find(parent[node])
+ }
+ return parent[node]
+ }
+
+ fun union(u: Int, v: Int): Boolean {
+ val pu = find(u)
+ val pv = find(v)
+ if (pu == pv) return false
+
+ comps--
+ if (size[pu] < size[pv]) {
+ parent[pu] = pv
+ size[pv] += size[pu]
+ } else {
+ parent[pv] = pu
+ size[pu] += size[pv]
+ }
+ return true
+ }
+}
+
+class Solution {
+ fun validTree(n: Int, edges: Array): Boolean {
+ if (edges.size > n - 1) return false
+
+ val dsu = DSU(n)
+ for ((u, v) in edges) {
+ if (!dsu.union(u, v)) return false
+ }
+ return dsu.comps == 1
+ }
+}
+```
+
::tabs-end
### Time & Space Complexity
From 357b76bdbf123fa7e1d60a1e66e247027f76ef1e Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Fri, 15 Nov 2024 12:13:45 +0530
Subject: [PATCH 12/67] Sri Hari: Batch-3/Neetcode-150/Added hints (#3740)
* Batch-3/Neetcode-150/Added hints
* Batch-3/Neetcode-150/Added hints
* Batch-3/Neetcode-150/Added hints
---
articles/is-anagram.md | 16 +++++---
hints/anagram-groups.md | 31 ++++++++++++++
hints/duplicate-integer.md | 3 +-
hints/is-anagram.md | 31 ++++++++++++++
hints/is-palindrome.md | 31 ++++++++++++++
hints/longest-consecutive-sequence.md | 31 ++++++++++++++
hints/max-water-container.md | 39 ++++++++++++++++++
hints/products-of-array-discluding-self.md | 39 ++++++++++++++++++
hints/string-encode-and-decode.md | 31 ++++++++++++++
hints/three-integer-sum.md | 47 ++++++++++++++++++++++
hints/top-k-elements-in-list.md | 31 ++++++++++++++
hints/two-integer-sum-ii.md | 39 ++++++++++++++++++
hints/two-integer-sum.md | 31 ++++++++++++++
hints/valid-sudoku.md | 31 ++++++++++++++
14 files changed, 425 insertions(+), 6 deletions(-)
create mode 100644 hints/anagram-groups.md
create mode 100644 hints/is-anagram.md
create mode 100644 hints/is-palindrome.md
create mode 100644 hints/longest-consecutive-sequence.md
create mode 100644 hints/max-water-container.md
create mode 100644 hints/products-of-array-discluding-self.md
create mode 100644 hints/string-encode-and-decode.md
create mode 100644 hints/three-integer-sum.md
create mode 100644 hints/top-k-elements-in-list.md
create mode 100644 hints/two-integer-sum-ii.md
create mode 100644 hints/two-integer-sum.md
create mode 100644 hints/valid-sudoku.md
diff --git a/articles/is-anagram.md b/articles/is-anagram.md
index 56d322820..1460b56c7 100644
--- a/articles/is-anagram.md
+++ b/articles/is-anagram.md
@@ -116,8 +116,10 @@ class Solution {
### Time & Space Complexity
-* Time complexity: $O(n \log n)$
-* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm.
+* Time complexity: $O(n \log n + m \log m)$
+* Space complexity: $O(1)$ or $O(n + m)$ depending on the sorting algorithm.
+
+> Where $n$ is the length of string $s$ and $m$ is the length of string $t$.
---
@@ -268,9 +270,11 @@ class Solution {
### Time & Space Complexity
-* Time complexity: $O(n)$
+* Time complexity: $O(n + m)$
* Space complexity: $O(1)$
+> Where $n$ is the length of string $s$ and $m$ is the length of string $t$.
+
---
## 3. Hash Table (Optimal)
@@ -434,5 +438,7 @@ class Solution {
### Time & Space Complexity
-* Time complexity: $O(n)$
-* Space complexity: $O(1)$
\ No newline at end of file
+* Time complexity: $O(n + m)$
+* Space complexity: $O(1)$
+
+> 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/hints/anagram-groups.md b/hints/anagram-groups.md
new file mode 100644
index 000000000..b77b383f8
--- /dev/null
+++ b/hints/anagram-groups.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(m * n)
time and O(m)
space, where m
is the number of strings and n
is the length of the longest string.
+
+
+
+
+
+ Hint 1
+
+ A naive solution would be to sort each string and group them using a hash map. This would be an O(m * nlogn)
solution. Though this solution is acceptable, can you think of a better way without sorting the strings?
+
+
+
+
+
+ Hint 2
+
+ By the definition of an anagram, we only care about the frequency of each character in a string. How is this helpful in solving the problem?
+
+
+
+
+
+ Hint 3
+
+ We can simply use an array of size O(26)
, since the character set is a
through z
(26
continuous characters), to count the frequency of each character in a string. Then, we can use this array as the key in the hash map to group the strings.
+
+
\ No newline at end of file
diff --git a/hints/duplicate-integer.md b/hints/duplicate-integer.md
index 75d4b0bbe..7639cfb85 100644
--- a/hints/duplicate-integer.md
+++ b/hints/duplicate-integer.md
@@ -1,7 +1,8 @@
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.
+
+ You should aim for a solution with O(n)
time and O(n)
space, where n
is the size of the input array.
diff --git a/hints/is-anagram.md b/hints/is-anagram.md
new file mode 100644
index 000000000..8454011d2
--- /dev/null
+++ b/hints/is-anagram.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n + m)
time and O(1)
space, where n
is the length of the string s
and m
is the length of the string t
.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to sort the given strings and check for their equality. This would be an O(nlogn + mlogm)
solution. Though this solution is acceptable, can you think of a better way without sorting the given strings?
+
+
+
+
+
+ Hint 2
+
+ By the definition of the anagram, we can rearrange the characters. Does the order of characters matter in both the strings? Then what matters?
+
+
+
+
+
+ Hint 3
+
+ We can just consider maintaining the frequency of each character. We can do this by having two separate hash tables for the two strings. Then, we can check whether the frequency of each character in string s
is equal to that in string t
and vice versa.
+
+
\ No newline at end of file
diff --git a/hints/is-palindrome.md b/hints/is-palindrome.md
new file mode 100644
index 000000000..697108060
--- /dev/null
+++ b/hints/is-palindrome.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 length of the input string.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to create a copy of the string, reverse it, and then check for equality. This would be an O(n)
solution with extra space. Can you think of a way to do this without O(n)
space?
+
+
+
+
+
+ Hint 2
+
+ Can you find the logic by observing the definition of pallindrome or from the brute force solution?
+
+
+
+
+
+ Hint 3
+
+ A palindrome string is a string that is read the same from the start as well as from the end. This means the character at the start should match the character at the end at the same index. We can use the two pointer algorithm to do this efficiently.
+
+
\ No newline at end of file
diff --git a/hints/longest-consecutive-sequence.md b/hints/longest-consecutive-sequence.md
new file mode 100644
index 000000000..7065b8463
--- /dev/null
+++ b/hints/longest-consecutive-sequence.md
@@ -0,0 +1,31 @@
+
+
+ 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
+
+ A brute force solution would be to consider every element from the array as the start of the sequence and count the length of the sequence formed with that starting element. This would be an O(n^2)
solution. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ Is there any way to identify the start of a sequence? For example, in [1, 2, 3, 10, 11, 12]
, only 1
and 10
are the beginning of a sequence. Instead of trying to form a sequence for every number, we should only consider numbers like 1
and 10
.
+
+
+
+
+
+ Hint 3
+
+ We can consider a number num
as the start of a sequence if and only if num - 1
does not exist in the given array. We iterate through the array and only start building the sequence if it is the start of a sequence. This avoids repeated work. We can use a hash set for O(1)
lookups by converting the array to a hash set.
+
+
\ No newline at end of file
diff --git a/hints/max-water-container.md b/hints/max-water-container.md
new file mode 100644
index 000000000..02fb8859b
--- /dev/null
+++ b/hints/max-water-container.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 solution would be to try all pairs of bars in the array, compute the water for each pair, and return the maximum water among all pairs. This would be an O(n^2)
solution. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ Can you think of an algorithm that runs in linear time and is commonly used in problems that deal with pairs of numbers? Find a formula to calculate the amount of water when we fix two heights.
+
+
+
+
+
+ Hint 3
+
+ We can use the two pointer algorithm. One pointer is at the start and the other at the end. At each step, we calculate the amount of water using the formula (j - i) * min(heights[i], heights[j])
. Then, we move the pointer that has the smaller height value. Can you think why we only move the pointer at smaller height?
+
+
+
+
+
+ Hint 4
+
+ In the formula, the amount of water depends only on the minimum height. Therefore, it is appropriate to replace the smaller height value.
+
+
\ No newline at end of file
diff --git a/hints/products-of-array-discluding-self.md b/hints/products-of-array-discluding-self.md
new file mode 100644
index 000000000..bab9964c9
--- /dev/null
+++ b/hints/products-of-array-discluding-self.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
+
+ A brute-force solution would be to iterate through the array with index i
and compute the product of the array except for that index element. This would be an O(n^2)
solution. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ Is there a way to avoid the repeated work? Maybe we can store the results of the repeated work in an array.
+
+
+
+
+
+ Hint 3
+
+ We can use the prefix and suffix technique. First, we iterate from left to right and store the prefix products for each index in a prefix array, excluding the current index's number. Then, we iterate from right to left and store the suffix products for each index in a suffix array, also excluding the current index's number. Can you figure out the solution from here?
+
+
+
+
+
+ Hint 4
+
+ We can use the stored prefix and suffix products to compute the result array by iterating through the array and simply multiplying the prefix and suffix products at each index.
+
+
\ No newline at end of file
diff --git a/hints/string-encode-and-decode.md b/hints/string-encode-and-decode.md
new file mode 100644
index 000000000..39083d5be
--- /dev/null
+++ b/hints/string-encode-and-decode.md
@@ -0,0 +1,31 @@
+
+
+ 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.
+
+
+
+
+
+ Hint 1
+
+ A naive solution would be to use a non-ascii character as a delimiter. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ Try to encode and decode the strings using a smart approach based on the lengths of each string. How can you differentiate between the lengths and any numbers that might be present in the strings?
+
+
+
+
+
+ Hint 3
+
+ We can use an encoding approach where we start with a number representing the length of the string, followed by a separator character (let's use #
for simplicity), and then the string itself. To decode, we read the number until we reach a #
, then use that number to read the specified number of characters as the string.
+
+
\ No newline at end of file
diff --git a/hints/three-integer-sum.md b/hints/three-integer-sum.md
new file mode 100644
index 000000000..d5acceb5c
--- /dev/null
+++ b/hints/three-integer-sum.md
@@ -0,0 +1,47 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n^2)
time and O(1)
space, where n
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to check for every triplet in the array. This would be an O(n^3)
solution. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ Can you think of an algorithm after sorting the input array? What can we observe by rearranging the given equation in the problem?
+
+
+
+
+
+ Hint 3
+
+ we can iterate through nums with index i
and get nums[i] = -(nums[j] + nums[k])
after rearranging the equation, making -nums[i] = nums[j] + nums[k]
. For each index i
, we should efficiently calculate the j
and k
pairs without duplicates. Which algorithm is suitable to find j
and k
pairs?
+
+
+
+
+
+ Hint 4
+
+ To efficiently find the j
and k
pairs, we run the two pointer approach on the elements to the right of index i
as the array is sorted. When we run two pointer algorithm, consider j
and k
as pointers (j
is at left, k
is at right) and target = -nums[i]
, if the current sum num[j] + nums[k] < target
then we need to increase the value of current sum by incrementing j
pointer. Else if the current sum num[j] + nums[k] > target
then we should decrease the value of current sum by decrementing k
pointer. How do you deal with duplicates?
+
+
+
+
+
+ Hint 5
+
+ When the current sum nums[j] + nums[k] == target
add this pair to the result. We can move j
or k
pointer until j < k
and the pairs are repeated. This ensures that no duplicate pairs are added to the result.
+
+
diff --git a/hints/top-k-elements-in-list.md b/hints/top-k-elements-in-list.md
new file mode 100644
index 000000000..566ec05de
--- /dev/null
+++ b/hints/top-k-elements-in-list.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 size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A naive solution would be to count the frequency of each number and then sort the array based on each element’s frequency. After that, we would select the top k
frequent elements. This would be an O(nlogn)
solution. Though this solution is acceptable, can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ Can you think of an algorithm which involves grouping numbers based on their frequency?
+
+
+
+
+
+ Hint 3
+
+ Use the bucket sort algorithm to create n
buckets, grouping numbers based on their frequencies from 1
to n
. Then, pick the top k
numbers from the buckets, starting from n
down to 1
.
+
+
\ No newline at end of file
diff --git a/hints/two-integer-sum-ii.md b/hints/two-integer-sum-ii.md
new file mode 100644
index 000000000..a07baf4ac
--- /dev/null
+++ b/hints/two-integer-sum-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 solution would be to check every pair of numbers in the array. This would be an O(n^2)
solution. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ Can you think of an algorithm by taking the advantage of array being sorted?
+
+
+
+
+
+ Hint 3
+
+ We can use the two-pointer algorithm. If nums[0] + nums[n-1] > target
, then we know nums[n - 1]
can not possibly be included in any pairs. Why? Because nums[n - 1]
is the largest element in the array. Even by adding it with nums[0]
, which is the smallest element, we still exceed the target. You can think of the case when nums[0] + nums[n - 1] < target
.
+
+
+
+
+
+ Hint 4
+
+ We keep two pointers, one at the start and the other at the end of the array. If the sum of the numbers at the two pointers is greater than the target
, decrement the right pointer, else increment the left pointer. Repeat this process until you find a valid pair.
+
+
\ No newline at end of file
diff --git a/hints/two-integer-sum.md b/hints/two-integer-sum.md
new file mode 100644
index 000000000..948aae221
--- /dev/null
+++ b/hints/two-integer-sum.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 size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to check every pair of numbers in the array. This would be an O(n^2)
solution. Can you think of a better way? Maybe in terms of mathematical equation?
+
+
+
+
+
+ Hint 2
+
+ Given, We need to find indices i
and j
such that i != j
and nums[i] + nums[j] == target
. Can you rearrange the equation and try to fix any index to iterate on?
+
+
+
+
+
+ Hint 3
+
+ we can iterate through nums with index i
. Let difference = target - nums[i]
and check if difference
exists in the hash map as we iterate through the array, else store the current element in the hashmap with its index and continue. We use a hashmap for O(1)
lookups.
+
+
\ No newline at end of file
diff --git a/hints/valid-sudoku.md b/hints/valid-sudoku.md
new file mode 100644
index 000000000..51655ed8b
--- /dev/null
+++ b/hints/valid-sudoku.md
@@ -0,0 +1,31 @@
+
+
+ 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 number of rows in the square grid.
+
+
+
+
+
+ Hint 1
+
+ Which data structure would you prefer to use for checking duplicates?
+
+
+
+
+
+ Hint 2
+
+ You can use a hash set for every row and column to check duplicates. But how can you efficiently check for the squares?
+
+
+
+
+
+ Hint 3
+
+ We can find the index of each square by the equation (row / 3) * 3 + (col / 3)
. Then we use hash set for O(1)
lookups while inserting the number into its row, column and square it belongs to. We use separate hash maps for rows, columns, and squares.
+
+
\ No newline at end of file
From 65f2627c53f520dc835aaada10e4352fac20d53d Mon Sep 17 00:00:00 2001
From: Bot-A0 <71089234+Ahmad-A0@users.noreply.github.com>
Date: Fri, 15 Nov 2024 07:07:00 +0000
Subject: [PATCH 13/67] =?UTF-8?q?=F0=9F=93=9C=20Update=20README=20table=20?=
=?UTF-8?q?(=F0=9F=9B=A0=EF=B8=8F=20from=20Github=20Actions)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 47165a764..f495a37f6 100644
--- a/README.md
+++ b/README.md
@@ -543,16 +543,16 @@ If you would like to have collaborator permissions on the repo to merge your own
[2665 - Counter II](https://leetcode.com/problems/counter-ii/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2665-counter-ii.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2635 - Apply Transform over each Element in Array](https://leetcode.com/problems/apply-transform-over-each-element-in-array/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2635-apply-transform-over-each-element-in-array.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2634 - Filter Elements from Array](https://leetcode.com/problems/filter-elements-from-array/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2634-filter-elements-from-array.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[2626 - Array Reduce Transformation](https://leetcode.com/problems/array-reduce-transformation/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[2629 - Function Composition](https://leetcode.com/problems/function-composition/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[2666 - Allow One Function Call](https://leetcode.com/problems/allow-one-function-call/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[2623 - Memoize](https://leetcode.com/problems/memoize/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[2632 - Curry](https://leetcode.com/problems/curry/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[2621 - Sleep](https://leetcode.com/problems/sleep/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
+[2626 - Array Reduce Transformation](https://leetcode.com/problems/array-reduce-transformation/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2626-array-reduce-transformation.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
+[2629 - Function Composition](https://leetcode.com/problems/function-composition/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2629-function-composition.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
+[2666 - Allow One Function Call](https://leetcode.com/problems/allow-one-function-call/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2666-allow-one-function-call.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
+[2623 - Memoize](https://leetcode.com/problems/memoize/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2623-memoize.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
+[2632 - Curry](https://leetcode.com/problems/curry/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2632-curry.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
+[2621 - Sleep](https://leetcode.com/problems/sleep/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2621-sleep.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2637 - Promise Time Limit](https://leetcode.com/problems/promise-time-limit/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2636 - Promise Pool](https://leetcode.com/problems/promise-pool/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2622 - Cache With Time Limit](https://leetcode.com/problems/cache-with-time-limit/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[2627 - Debounce](https://leetcode.com/problems/debounce/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
+[2627 - Debounce](https://leetcode.com/problems/debounce/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2627-debounce.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2676 - Throttle](https://leetcode.com/problems/throttle/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2628 - JSON Deep Equal](https://leetcode.com/problems/json-deep-equal/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](javascript%2F2628-json-deep-equal.js)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[2633 - Convert Object to JSON String](https://leetcode.com/problems/convert-object-to-json-string/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
From 7222e1ea7021833c3cf301853a86935e7a04ef23 Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Mon, 18 Nov 2024 10:34:28 +0530
Subject: [PATCH 14/67] Sri Hari: Batch-3/Neetcode-150/Added hints (#3741)
* Batch-3/Neetcode-150/Added hints
* Batch-3/Neetcode-150/Added hints
* Batch-3/Neetcode-150/Added hints
* Batch-3/Neetcode-150/Added hints
* Batch-3/Neetcode-150/Added hints
* Batch-3/Neetcode-150/Added hints
---
hints/binary-search.md | 39 +++++++++++++++
hints/buy-and-sell-crypto.md | 39 +++++++++++++++
hints/car-fleet.md | 39 +++++++++++++++
hints/daily-temperatures.md | 39 +++++++++++++++
hints/eating-bananas.md | 47 +++++++++++++++++++
hints/evaluate-reverse-polish-notation.md | 31 ++++++++++++
hints/generate-parentheses.md | 31 ++++++++++++
hints/largest-rectangle-in-histogram.md | 39 +++++++++++++++
...st-repeating-substring-with-replacement.md | 39 +++++++++++++++
hints/longest-substring-without-duplicates.md | 31 ++++++++++++
hints/minimum-stack.md | 31 ++++++++++++
hints/minimum-window-with-characters.md | 39 +++++++++++++++
hints/permutation-string.md | 31 ++++++++++++
hints/search-2d-matrix.md | 39 +++++++++++++++
hints/sliding-window-maximum.md | 39 +++++++++++++++
hints/three-integer-sum.md | 2 +-
hints/trapping-rain-water.md | 39 +++++++++++++++
hints/validate-parentheses.md | 31 ++++++++++++
18 files changed, 624 insertions(+), 1 deletion(-)
create mode 100644 hints/binary-search.md
create mode 100644 hints/buy-and-sell-crypto.md
create mode 100644 hints/car-fleet.md
create mode 100644 hints/daily-temperatures.md
create mode 100644 hints/eating-bananas.md
create mode 100644 hints/evaluate-reverse-polish-notation.md
create mode 100644 hints/generate-parentheses.md
create mode 100644 hints/largest-rectangle-in-histogram.md
create mode 100644 hints/longest-repeating-substring-with-replacement.md
create mode 100644 hints/longest-substring-without-duplicates.md
create mode 100644 hints/minimum-stack.md
create mode 100644 hints/minimum-window-with-characters.md
create mode 100644 hints/permutation-string.md
create mode 100644 hints/search-2d-matrix.md
create mode 100644 hints/sliding-window-maximum.md
create mode 100644 hints/trapping-rain-water.md
create mode 100644 hints/validate-parentheses.md
diff --git a/hints/binary-search.md b/hints/binary-search.md
new file mode 100644
index 000000000..a1a01c8e2
--- /dev/null
+++ b/hints/binary-search.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(logn)
time and O(1)
space, where n
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ Can you find an algorithm that is useful when the array is sorted? Maybe other than linear seacrh.
+
+
+
+
+
+ Hint 2
+
+ The problem name is the name of the algorithm that we can use. We need to find a target value and if it does not exist in the array return -1
. We have l
and r
as the boundaries of the segment of the array in which we are searching. Try building conditions to eliminate half of the search segment at each step. Maybe sorted nature of the array can be helpful.
+
+
+
+
+
+ Hint 3
+
+ We compare the target value with the mid
of the segment. For example, consider the array [1, 2, 3, 4, 5]
and target = 4
. The mid
value is 3
, thus, on the next iteration we search to the right of mid
. The remaining segment is [4,5]
. Why?
+
+
+
+
+
+ Hint 4
+
+ Because the array is sorted, all elements to the left of mid
(including 3
) are guaranteed to be smaller than the target. Therefore, we can safely eliminate that half of the array from consideration, narrowing the search to the right half and repeat this search until we find the target.
+
+
\ No newline at end of file
diff --git a/hints/buy-and-sell-crypto.md b/hints/buy-and-sell-crypto.md
new file mode 100644
index 000000000..0597ae13a
--- /dev/null
+++ b/hints/buy-and-sell-crypto.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 solution would be to iterate through the array with index i
, considering it as the day to buy, and trying all possible options for selling it on the days to the right of index i
. This would be an O(n^2)
solution. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ You should buy at a price and always sell at a higher price. Can you iterate through the array with index i
, considering it as either the buying price or the selling price?
+
+
+
+
+
+ Hint 3
+
+ We can iterate through the array with index i
, considering it as the selling value. But what value will it be optimal to consider as buying point on the left of index i
?
+
+
+
+
+
+ Hint 4
+
+ We are trying to maximize profit = sell - buy
. If the current i
is the sell value, we want to choose the minimum buy value to the left of i
to maximize the profit. The result will be the maximum profit among all. However, if all profits are negative, we can return 0
since we are allowed to skip doing transaction.
+
+
\ No newline at end of file
diff --git a/hints/car-fleet.md b/hints/car-fleet.md
new file mode 100644
index 000000000..23c63e134
--- /dev/null
+++ b/hints/car-fleet.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
+
+ First draw a picture of all the points which represents the positions and respective speeds of the cars. It is appropriate to represent the position and speed of each car as an array, where each cell corresponds to a car. It is also logical to sort this array based on the positions in descending order. Why?
+
+
+
+
+
+ Hint 2
+
+ Because a car can only form a fleet with another car that is ahead of it, sorting the array in descending order ensures clarity about the final speed of each car. Sorting in ascending order would create ambiguity, as the next car might form a fleet with another car while reaching the target, making it difficult to determine its final speed.
+
+
+
+
+
+ Hint 3
+
+ Calculating the time for a car to reach the target is straightforward and can be done using the formula: time = (target - position) / speed
. Now, it becomes easy to identify that two cars will form a fleet if and only if the car ahead has a time that is greater than or equal to the time of the car behind it. How can we maintain the total number of fleets happened while going through the array? Maybe a data structure is helpful.
+
+
+
+
+
+ Hint 4
+
+ We can use a stack to maintain the times of the fleets. As we iterate through the array (sorted in descending order of positions), we compute the time for each car to reach the target and check if it can form a fleet with the car ahead. If the current car's time is less than or equal to the top of the stack, it joins the same fleet. Otherwise, it forms a new fleet, and we push its time onto the stack. The length of the stack at the end represents the total number of fleets formed.
+
+
\ No newline at end of file
diff --git a/hints/daily-temperatures.md b/hints/daily-temperatures.md
new file mode 100644
index 000000000..64c1a171e
--- /dev/null
+++ b/hints/daily-temperatures.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
+
+ A brute force solution would involve iterating through the array with index i
and checking how far is the next greater element to the right of i
. This would be an O(n^2)
solution. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ Can you consider a reverse approach? For example, in [2, 1, 1, 3]
, the next greater element for the numbers [2, 1, 1]
is 3
. Instead of checking for each element individually, can you think of a way where, by standing at the element 3
, you compute the result for the elements [2, 1, 1]
? Maybe there's a data structure that is useful here.
+
+
+
+
+
+ Hint 3
+
+ We can use a stack to maintain indices in a monotonically decreasing order, popping indices where the values are smaller than the current element. This helps us find the result by using the difference between indices while considering the values at those indices. Can you see how the stack is useful?
+
+
+
+
+
+ Hint 4
+
+ In the array [2, 1, 1, 3]
, we don't perform any pop operations while processing [2, 1, 1]
because these elements are already in decreasing order. However, when we reach 3
, we pop elements from the stack until the top element of the stack is no longer less than the current element. For each popped element, we compute the difference between the indices and store it in the position corresponding to the popped element.
+
+
\ No newline at end of file
diff --git a/hints/eating-bananas.md b/hints/eating-bananas.md
new file mode 100644
index 000000000..41bb76a40
--- /dev/null
+++ b/hints/eating-bananas.md
@@ -0,0 +1,47 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(nlogm)
time and O(1)
space, where n
is the size of the input array, and m
is the maximum value in the array.
+
+
+
+
+
+ Hint 1
+
+ Given h
is always greater than or equal to the length of piles, can you determine the upper bound for the answer? How much time does it take Koko to eat a pile with x
bananas?
+
+
+
+
+
+ Hint 2
+
+ It takes ceil(x / k)
time to finish the x
pile when Koko eats at a rate of k
bananas per hour. Our task is to determine the minimum possible value of k
. However, we must also ensure that at this rate, k
, Koko can finish eating all the piles within the given h
hours. Can you now think of the upper bound for k
?
+
+
+
+
+
+ Hint 3
+
+ The upper bound for k
is the maximum size of all the piles. Why? Because if Koko eats the largest pile in one hour, then it is straightforward that she can eat any other pile in an hour only.
+
+
+
+
+
+ Hint 4
+
+ Consider m
to be the largest pile and n
to be the number of piles. A brute force solution would be to linearly check all values from 1
to m
and find the minimum possible value at which Koko can complete the task. This approach would take O(n * m)
time. Can you think of a more efficient method? Perhaps an efficient searching algorithm could help.
+
+
+
+
+
+ Hint 5
+
+ Rather than linearly scanning, we can use binary search. The upper bound of k
is max(piles)
and since we are only dealing with positive values, the lower bound is 1
. The search space of our binary search is 1
through max(piles)
. This allows us to find the smallest possible k
using binary search.
+
+
\ No newline at end of file
diff --git a/hints/evaluate-reverse-polish-notation.md b/hints/evaluate-reverse-polish-notation.md
new file mode 100644
index 000000000..8e63e0dfd
--- /dev/null
+++ b/hints/evaluate-reverse-polish-notation.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 size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve repeatedly finding an operator + - * /
in the array and modifying the array by computing the result for that operator and two operands to its left. This would be an O(n^2)
solution. Can you think of a better way? Maybe we can use a data structure to handle operations efficiently.
+
+
+
+
+
+ Hint 2
+
+ We can use a stack. We iterate through the array, and if we encounter a number, we push it onto the stack. If we encounter an operator, we pop two elements from the stack, treat them as operands, and solve the equation using the current operator. Then, we push the result back onto the stack. Why does this work?
+
+
+
+
+
+ Hint 3
+
+ As the array has postfix expression, stack helps us to maintain the correct order of operations by ensuring that we always use the most recent operands (those closest to the operator) when performing the operation. After the iteration, the final result is left in the stack.
+
+
\ No newline at end of file
diff --git a/hints/generate-parentheses.md b/hints/generate-parentheses.md
new file mode 100644
index 000000000..454a10e81
--- /dev/null
+++ b/hints/generate-parentheses.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(4^n / sqrt(n))
time and O(n)
space, where n
is the number of parenthesis pairs in the string.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to generate all possible strings of size 2n
and add only the valid strings. This would be an O(n * 2 ^ (2n))
solution. Can you think of a better way? Maybe you can use pruning to avoid generating invalid strings.
+
+
+
+
+
+ Hint 2
+
+ We can use backtracking with pruning. But what makes a string invalid? Can you think of a condition for this?
+
+
+
+
+
+ Hint 3
+
+ When the count of closing brackets exceeds the count of opening brackets, the string becomes invalid. Therefore, we can maintain two variables, open
and close
, to track the number of opening and closing brackets. We avoid exploring paths where close > open
. Once the string length reaches 2n
, we add it to the result.
+
+
\ No newline at end of file
diff --git a/hints/largest-rectangle-in-histogram.md b/hints/largest-rectangle-in-histogram.md
new file mode 100644
index 000000000..35976b385
--- /dev/null
+++ b/hints/largest-rectangle-in-histogram.md
@@ -0,0 +1,39 @@
+
+
+ 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
+
+ A rectangle has a height and a width. Can you visualize how rectangles are formed in the given input? Considering one bar at a time might help. We can try to form rectangles by going through every bar and current bar's height will be the height of the rectangle. How can you determine the width of the rectangle for the current bar being the height of the rectangle? Extending the current bar to the left and right might help determine the rectangle's width.
+
+
+
+
+
+ Hint 2
+
+ For a bar with height h
, try extending it to the left and right. We can see that we can't extend further when we encounter a bar with a smaller height than h
. The width will be the number of bars within this extended range. A brute force solution would be to go through every bar and find the area of the rectangle it can form by extending towards the left and right. This would be an O(n^2)
solution. Can you think of a better way? Maybe precomputing the left and right boundaries might be helpful.
+
+
+
+
+
+ Hint 3
+
+ The left and right boundaries are the positions up to which we can extend the bar at index i
. The area of the rectangle will be height[i] * (right - left + 1)
, which is the general formula for height * width
. These boundaries are determined by the first smaller bars encountered to the left and right of the current bar. How can we find the left and right boundaries now? Maybe a data structure is helpful.
+
+
+
+
+
+ Hint 4
+
+ We can use a stack with a monotonically strictly increasing nature, but instead of storing values, we store indices in the stack and perform operations based on the values at those indices. The top of the stack will represent the smaller bar that we encounter while extending the current bar. To find the left and right boundaries, we perform this algorithm from left to right and vice versa, storing the boundaries. Then, we iterate through the array to find the area for each bar and return the maximum area we get.
+
+
\ No newline at end of file
diff --git a/hints/longest-repeating-substring-with-replacement.md b/hints/longest-repeating-substring-with-replacement.md
new file mode 100644
index 000000000..808ff742f
--- /dev/null
+++ b/hints/longest-repeating-substring-with-replacement.md
@@ -0,0 +1,39 @@
+
+
+ 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 given string and m
is the number of unique characters in the string.
+
+
+
+
+
+ Hint 1
+
+ Which characters would you replace in a string to make all its characters unique? Can you think with respect to the frequency of the characters?
+
+
+
+
+
+ Hint 2
+
+ It is always optimal to replace characters with the most frequent character in the string. Why? Because using the most frequent character minimizes the number of replacements required to make all characters in the string identical. How can you find the number of replacements now?
+
+
+
+
+
+ Hint 3
+
+ The number of replacements is equal to the difference between the length of the string and the frequency of the most frequent character in the string. A brute force solution would be to consider all substrings, use a hash map for frequency counting, and return the maximum length of the substring that has at most k
replacements. This would be an O(n^2)
solution. Can you think of a better way?
+
+
+
+
+
+ Hint 4
+
+ We can use the sliding window approach. The window size will be dynamic, and we will shrink the window when the number of replacements exceeds k
. The result will be the maximum window size observed at each iteration.
+
+
\ No newline at end of file
diff --git a/hints/longest-substring-without-duplicates.md b/hints/longest-substring-without-duplicates.md
new file mode 100644
index 000000000..42c7ca28a
--- /dev/null
+++ b/hints/longest-substring-without-duplicates.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 and m
is the number of unique characters in the string.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to try the substring starting at index i
and try to find the maximum length we can form without duplicates by starting at that index. we can use a hash set to detect duplicates in O(1)
time. Can you think of a better way?
+
+
+
+
+
+ Hint 2
+
+ We can use the sliding window algorithm. Since we only care about substrings without duplicate characters, the sliding window can help us maintain valid substring with its dynamic nature.
+
+
+
+
+
+ Hint 3
+
+ We can iterate through the given string with index r
as the right boundary and l
as the left boundary of the window. We use a hash set to check if the character is present in the window or not. When we encounter a character at index r
that is already present in the window, we shrink the window by incrementing the l
pointer until the window no longer contains any duplicates. Also, we remove characters from the hash set that are excluded from the window as the l
pointer moves. At each iteration, we update the result with the length of the current window, r - l + 1
, if this length is greater than the current result.
+
+
\ No newline at end of file
diff --git a/hints/minimum-stack.md b/hints/minimum-stack.md
new file mode 100644
index 000000000..411e300dd
--- /dev/null
+++ b/hints/minimum-stack.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(1)
time for each function call and O(n)
space, where n
is the maximum number of elements present in the stack.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to always check for the minimum element in the stack for the getMin()
function call. This would be an O(n)
appraoch. Can you think of a better way? Maybe O(n)
extra space to store some information.
+
+
+
+
+
+ Hint 2
+
+ We can use a stack to maintain the elements. But how can we find the minimum element at any given time? Perhaps we should consider a prefix approach.
+
+
+
+
+
+ Hint 3
+
+ We use an additional stack to maintain the prefix minimum element. When popping elements from the main stack, we should also pop from this extra stack. However, when pushing onto the extra stack, we should push the minimum of the top element of the extra stack and the current element onto this extra stack.
+
+
\ No newline at end of file
diff --git a/hints/minimum-window-with-characters.md b/hints/minimum-window-with-characters.md
new file mode 100644
index 000000000..3df37fff9
--- /dev/null
+++ b/hints/minimum-window-with-characters.md
@@ -0,0 +1,39 @@
+
+
+ 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 s
and t
.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve checking every substring of s
against t
and returning the minimum length valid substring. This would be an O(n^2)
solution. Can you think of a better way? Maybe you should think in terms of frequency of characters.
+
+
+
+
+
+ Hint 2
+
+ We need to find substrings in s
that should have atleast the characters of t
. We can use hash maps to maintain the frequencies of characters. It will be O(1)
for lookups. Can you think of an algorithm now?
+
+
+
+
+
+ Hint 3
+
+ We can use a dynamically sized sliding window approach on s
. We iterate through s
while maintaining a window. If the current window contains at least the frequency of characters from t
, we update the result and shrink the window until it is valid.
+
+
+
+
+
+ Hint 4
+
+ We should ensure that we maintain the result substring and only update it if we find a shorter valid substring. Additionally, we need to keep track of the result substring's length so that we can return an empty string if no valid substring is found.
+
+
\ No newline at end of file
diff --git a/hints/permutation-string.md b/hints/permutation-string.md
new file mode 100644
index 000000000..5abcaddf0
--- /dev/null
+++ b/hints/permutation-string.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 maximum of the lengths of the two strings.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to check every substring of s2
with s1
by sorting s1
as well as the substring of s2
. This would be an O(n^2)
solution. Can you think of a better way? Maybe we can use the freqency of the characters of both the strings as we did in checking anagrams.
+
+
+
+
+
+ Hint 2
+
+ We return false if the length of s1
is greater than the length of s2
. To count the frequency of each character in a string, we can simply use an array of size O(26)
, since the character set consists of a
through z
(26
continuous characters). Which algorithm can we use now?
+
+
+
+
+
+ Hint 3
+
+ We use a sliding window approach on s2
with a fixed window size equal to the length of s1
. To track the current window, we maintain a running frequency count of characters in s2
. This frequency count represents the characters in the current window. At each step, if the frequency count matches that of s1
, we return true
.
+
+
\ No newline at end of file
diff --git a/hints/search-2d-matrix.md b/hints/search-2d-matrix.md
new file mode 100644
index 000000000..53153f798
--- /dev/null
+++ b/hints/search-2d-matrix.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(log(m * n))
time and O(1)
space, where m
is the number of rows and n
is the number of columns in the matrix.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to do a linear search on the matrix. This would be an O(m * n)
solution. Can you think of a better way? Maybe an efficient searching algorithm, as the given matrix is sorted.
+
+
+
+
+
+ Hint 2
+
+ We can use binary search, which is particularly effective when we visualize a row as a range of numbers, [x, y]
where x
is the first cell and y
is the last cell of a row. Using this representation, it becomes straightforward to check if the target value falls within the range. How can you use binary search to solve the problem?
+
+
+
+
+
+ Hint 3
+
+ We perform a binary search on the rows to identify the row in which the target value might fall. This operation takes O(logm)
time, where m
is the number of rows. Now, when we find the potential row, can you find the best way to search the target in that row? The sorted nature of each row is the hint.
+
+
+
+
+
+ Hint 4
+
+ Once we identify the potential row where the target might exist, we can perform a binary search on that row which acts as a one dimensional array. It takes O(logn)
time, where n
is the number of columns in the row.
+
+
\ No newline at end of file
diff --git a/hints/sliding-window-maximum.md b/hints/sliding-window-maximum.md
new file mode 100644
index 000000000..3506407c3
--- /dev/null
+++ b/hints/sliding-window-maximum.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
+
+ A brute force solution would involve iterating through each window of size k
and finding the maximum element within the window by iterating through it. This would be an O(n * k)
solution. Can you think of a better way? Maybe think of a data structure that tells the current maximum element of the window in O(1)
time.
+
+
+
+
+
+ Hint 2
+
+ A heap is the best data structure to use when dealing with maximum or minimum values and it takes O(1)
time to get the max or min value. Here, we use a max-heap. But what should we do if the current maximum element is no longer part of the window? Can you think of a different way of adding values to the max-heap?
+
+
+
+
+
+ Hint 3
+
+ We process each window by adding elements to the heap along with their indices to track whether the maximum value is still within the current window. As we move from one window to the next, an element may go out of the window but still remain in the max-heap. Is there a way to handle this situation efficiently?
+
+
+
+
+
+ Hint 4
+
+ We can ignore those elements that are no longer part of the current window, except when the maximum value is outside the window. In that case, we remove elements from the max-heap until the maximum value belongs to the current window. Why? Because those elements will be eventually removed when the maximum element goes out of the window.
+
+
\ No newline at end of file
diff --git a/hints/three-integer-sum.md b/hints/three-integer-sum.md
index d5acceb5c..444e13872 100644
--- a/hints/three-integer-sum.md
+++ b/hints/three-integer-sum.md
@@ -26,7 +26,7 @@
Hint 3
- we can iterate through nums with index i
and get nums[i] = -(nums[j] + nums[k])
after rearranging the equation, making -nums[i] = nums[j] + nums[k]
. For each index i
, we should efficiently calculate the j
and k
pairs without duplicates. Which algorithm is suitable to find j
and k
pairs?
+ We can iterate through nums with index i
and get nums[i] = -(nums[j] + nums[k])
after rearranging the equation, making -nums[i] = nums[j] + nums[k]
. For each index i
, we should efficiently calculate the j
and k
pairs without duplicates. Which algorithm is suitable to find j
and k
pairs?
diff --git a/hints/trapping-rain-water.md b/hints/trapping-rain-water.md
new file mode 100644
index 000000000..2ae54b063
--- /dev/null
+++ b/hints/trapping-rain-water.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
+
+ How can we determine the amount of water that can be trapped at a specific position in the array? Perhaps looking at the image might help clarify.
+
+
+
+
+
+ Hint 2
+
+ From the image, we can see that to calculate the amount of water trapped at a position, the greater element to the left l
and the greater element to the right r
of the current position are crucial. The formula for the trapped water at index i
is given by: min(height[l], height[r]) - height[i]
.
+
+
+
+
+
+ Hint 3
+
+ A brute force solution would involve iterating through the array with index i
, finding the greater elements to the left (l
) and right (r
) for each index, and then calculating the trapped water for that position. The total amount of trapped water would be the sum of the water trapped at each index. Finding l
and r
for each index involves repeated work, resulting in an O(n^2)
solution. Can you think of a more efficient approach? Maybe there is something that we can precompute and store in arrays.
+
+
+
+
+
+ Hint 4
+
+ We can store the prefix maximum in an array by iterating from left to right and the suffix maximum in another array by iterating from right to left. For example, in [1, 5, 2, 3, 4]
, for the element 3
, the prefix maximum is 5
, and the suffix maximum is 4
. Once these arrays are built, we can iterate through the array with index i
and calculate the total water trapped at each position using the formula: min(prefix[i], suffix[i]) - height[i]
.
+
+
\ No newline at end of file
diff --git a/hints/validate-parentheses.md b/hints/validate-parentheses.md
new file mode 100644
index 000000000..ec5216bb4
--- /dev/null
+++ b/hints/validate-parentheses.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 length of the given string.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to continuously remove valid brackets until no more can be removed. If the remaining string is empty, return true; otherwise, return false. This would result in an O(n^2)
solution. Can we think of a better approach? Perhaps a data structure could help.
+
+
+
+
+
+ Hint 2
+
+ We can use a stack to store characters. Iterate through the string by index. For an opening bracket, push it onto the stack. If the bracket is a closing type, check for the corresponding opening bracket at the top of the stack. If we don't find the corresponding opening bracket, immediately return false. Why does this work?
+
+
+
+
+
+ Hint 3
+
+ In a valid parenthesis expression, every opening bracket must have a corresponding closing bracket. The stack is used to process the valid string, and it should be empty after the entire process. This ensures that there is a valid substring between each opening and closing bracket.
+
+
\ No newline at end of file
From 864a32a131c2c3b3527b1aae80225c04afa4d593 Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Mon, 18 Nov 2024 10:34:38 +0530
Subject: [PATCH 15/67] Batch-3/Neetcode-150/Added hints (#3742)
---
articles/add-two-numbers.md | 4 +-
hints/add-two-numbers.md | 23 +++++++++
hints/copy-linked-list-with-random-pointer.md | 31 ++++++++++++
hints/find-minimum-in-rotated-sorted-array.md | 40 ++++++++++++++++
hints/find-target-in-rotated-sorted-array.md | 40 ++++++++++++++++
hints/median-of-two-sorted-arrays.md | 47 +++++++++++++++++++
hints/merge-two-sorted-linked-lists.md | 31 ++++++++++++
hints/remove-node-from-end-of-linked-list.md | 47 +++++++++++++++++++
hints/reorder-linked-list.md | 31 ++++++++++++
hints/reverse-a-linked-list.md | 39 +++++++++++++++
hints/time-based-key-value-store.md | 39 +++++++++++++++
11 files changed, 370 insertions(+), 2 deletions(-)
create mode 100644 hints/add-two-numbers.md
create mode 100644 hints/copy-linked-list-with-random-pointer.md
create mode 100644 hints/find-minimum-in-rotated-sorted-array.md
create mode 100644 hints/find-target-in-rotated-sorted-array.md
create mode 100644 hints/median-of-two-sorted-arrays.md
create mode 100644 hints/merge-two-sorted-linked-lists.md
create mode 100644 hints/remove-node-from-end-of-linked-list.md
create mode 100644 hints/reorder-linked-list.md
create mode 100644 hints/reverse-a-linked-list.md
create mode 100644 hints/time-based-key-value-store.md
diff --git a/articles/add-two-numbers.md b/articles/add-two-numbers.md
index 0fb91cffb..6225ac227 100644
--- a/articles/add-two-numbers.md
+++ b/articles/add-two-numbers.md
@@ -310,7 +310,7 @@ class Solution {
* Time complexity: $O(m + n)$
* Space complexity: $O(m + n)$
-> Where $m$ is the length $l1$ and $n$ is the length of $l2$.
+> Where $m$ is the length of $l1$ and $n$ is the length of $l2$.
---
@@ -584,4 +584,4 @@ class Solution {
* Time complexity: $O(m + n)$
* Space complexity: $O(1)$
-> Where $m$ is the length $l1$ and $n$ is the length of $l2$.
\ No newline at end of file
+> Where $m$ is the length of $l1$ and $n$ is the length of $l2$.
\ No newline at end of file
diff --git a/hints/add-two-numbers.md b/hints/add-two-numbers.md
new file mode 100644
index 000000000..2cdafc4fa
--- /dev/null
+++ b/hints/add-two-numbers.md
@@ -0,0 +1,23 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(m + n)
time and O(1)
space, where m
is the length of list l1
and n
is the length of list l2
.
+
+
+
+
+
+ Hint 1
+
+ Try to visualize the addition of two numbers. We know that the addition of two numbers is done by starting at the one's digit. We add the numbers by going through digit by digit. We track the extra value as a carry
because the addition of two digits can result in a number with two digits. The carry
is then added to the next digits, and so on. How do you implement this in case of linked lists?
+
+
+
+
+
+ Hint 2
+
+ We track the extra value, carry
, here as well. We iterate through the lists l1
and l2
until both lists reach null
. We add the values of both nodes as well as the carry. If either of the nodes is null
, we add 0
in its place and continue the process while tracking the carry simultaneously. Once we complete the process, if we are left with any carry
, we add an extra node with that carry value and return the head of the result list.
+
+
\ No newline at end of file
diff --git a/hints/copy-linked-list-with-random-pointer.md b/hints/copy-linked-list-with-random-pointer.md
new file mode 100644
index 000000000..73a1417ae
--- /dev/null
+++ b/hints/copy-linked-list-with-random-pointer.md
@@ -0,0 +1,31 @@
+
+
+ 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 given list.
+
+
+
+
+
+ Hint 1
+
+ There is an extra random pointer for each node, and unlike the next pointer, which points to the next node, the random pointer can point to any random node in the list. A deep copy is meant to create completely separate nodes occupying different memory. Why can't we build a new list while iterating through the original list?
+
+
+
+
+
+ Hint 2
+
+ Because, while iterating through the list, when we encounter a node and create a copy of it, we can't immediately assign the random pointer's address. This is because the random pointer might point to a node that has not yet been created. To solve this, we can first create copies of all the nodes in one iteration. However, we still can't directly assign the random pointers since we don't have the addresses of the copies of those random pointers. Can you think of a data structure to store this information? Maybe a hash data structure could help.
+
+
+
+
+
+ Hint 3
+
+ We can use a hash data structure, such as a hash map, which takes O(1)
time to retrieve data. This can help by mapping the original nodes to their corresponding copies. This way, we can easily retrieve the copy of any node and assign the random pointers in a subsequent pass after creating copies of all nodes in the first pass.
+
+
\ No newline at end of file
diff --git a/hints/find-minimum-in-rotated-sorted-array.md b/hints/find-minimum-in-rotated-sorted-array.md
new file mode 100644
index 000000000..568e4ef1f
--- /dev/null
+++ b/hints/find-minimum-in-rotated-sorted-array.md
@@ -0,0 +1,40 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(logn)
time and O(1)
space, where n
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to do a linear search on the array to find the minimum element. This would be an O(n)
solution. Can you think of a better way? Maybe an efficient searching algorithm is helpful.
+
+
+
+
+
+ Hint 2
+
+ Given that the array is rotated after sorting, elements from the right end are moved to the left end one by one. This creates two parts of a sorted array, separated by a deflection point caused by the rotation. For example, consider the array [3, 4, 1, 2]
. Here, the array is rotated twice, resulting in two sorted segments: [3, 4]
and [1, 2]
. And the minimum element will be the first element of the right segment. Can you do a binary search to find this cut?
+
+
+
+
+
+ Hint 3
+
+ We perform a binary search on the array with pointers l
and r
, which belong to two different sorted segments. For example, in [3, 4, 5, 6, 1, 2, 3]
, l = 0
, r = 6
, and mid = 3
. At least two of l
, mid
, and r
will always be in the same sorted segment. Can you find conditions to eliminate one half and continue the binary search? Perhaps analyzing all possible conditions for l
, mid
, and r
would help.
+
+
+
+
+
+ Hint 4
+
+ There will be two conditions where l
and mid
will be in left sorted segment or mid
and r
will be in right sorted segement.
+ If l
and mid
in sorted segement, then nums[l] < nums[mid]
and the minimum element will be in the right part. If mid
and r
in sorted segment, then nums[m] < nums[r]
and the minimum element will be in the left part. After the binary search we end up finding the minimum element.
+
+
\ No newline at end of file
diff --git a/hints/find-target-in-rotated-sorted-array.md b/hints/find-target-in-rotated-sorted-array.md
new file mode 100644
index 000000000..7133b3821
--- /dev/null
+++ b/hints/find-target-in-rotated-sorted-array.md
@@ -0,0 +1,40 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(logn)
time and O(1)
space, where n
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to do a linear search on the array to find the target element. This would be an O(n)
solution. Can you think of a better way? Maybe an efficient searching algorithm is helpful.
+
+
+
+
+
+ Hint 2
+
+ Given that the array is rotated after sorting, elements from the right end are moved to the left end one by one, creating two sorted segments separated by a deflection point due to the rotation. For example, consider the array [3, 4, 1, 2]
, which is rotated twice, resulting in two sorted segments: [3, 4]
and [1, 2]
. In a fully sorted array, it's easy to find the target. So, if you can identify the deflection point (cut), you can perform a binary search on both segments to find the target element. Can you use binary search to find this cut?
+
+
+
+
+
+ Hint 3
+
+ We perform a binary search on the array with pointers l
and r
, which belong to two different sorted segments. For example, in [3, 4, 5, 6, 1, 2, 3]
, l = 0
, r = 6
, and mid = 3
. At least two of l
, mid
, and r
will always be in the same sorted segment. Can you find conditions to eliminate one half and continue the binary search? Perhaps analyzing all possible conditions for l
, mid
, and r
may help.
+
+
+
+
+
+ Hint 4
+
+ There are two cases: l
and mid
belong to the left sorted segment, or mid
and r
belong to the right sorted segment.
+ If l
and mid
are in the same segment, nums[l] < nums[mid]
, so the pivot index must lie in the right part. If mid
and r
are in the same segment, nums[mid] < nums[r]
, so the pivot index must lie in the left part. After the binary search, we eventually find the pivot index. Once the pivot is found, it's straightforward to select the segment where the target lies and perform a binary search on that segement to find its position. If we don't find the target, we return -1
.
+
+
\ No newline at end of file
diff --git a/hints/median-of-two-sorted-arrays.md b/hints/median-of-two-sorted-arrays.md
new file mode 100644
index 000000000..bfbe9c032
--- /dev/null
+++ b/hints/median-of-two-sorted-arrays.md
@@ -0,0 +1,47 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(log(min(n, m)))
time and O(1)
space, where n
is the size of nums1
and m
is the size of nums2
.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to create a new array by merging elements from both arrays, then sorting it and returning the median. This would be an O(n + m)
solution. Can you think of a better way? Maybe you can use the criteria of both the arrays being sorted in ascending order.
+
+
+
+
+
+ Hint 2
+
+ Suppose we merged both arrays. Then, we would have half = (m + n) / 2
elements to the left of the median. So, without merging, is there any way to use this information to find the median? You can leverage the fact that the arrays are sorted. Consider the smaller array between the two and use binary search to find the correct partition between the two arrays, which will allow you to directly find the median without fully merging the arrays. How will you implement this?
+
+
+
+
+
+ Hint 3
+
+ We will always try to keep array A
smaller and interchange it with array B
if len(A) > len(B)
. Now, we perform binary search on the number of elements we will choose from array A
. It is straightforward that when we choose x
elements from array A
, we have to choose half - x
elements from array B
. But we should also ensure that this partition is valid. How can we do this?
+
+
+
+
+
+ Hint 4
+
+ When we do a partition for both arrays, we should ensure that the maximum elements from the left partitions of both arrays are smaller than or equal to the minimum elements of the right partitions of both the arrays. This will ensure that the partition is valid, and we can then find the median. We can find the min or max of these partitions in O(1)
as these partitions are sorted in ascending order. Why does this work?
+
+
+
+
+
+ Hint 5
+
+ For example, consider the arrays A = [1, 2, 3, 4, 5]
and B = [1, 2, 3, 4, 5, 6, 7, 8]
. When we select x = 2
, we take 4
elements from array B
. However, this partition is not valid because value 4
from the left partition of array B
is greater than the value 3
from the right partition of array A
. So, we should try to take more elements from array A
to make the partition valid. Binary search will eventually help us find a valid partition.
+
+
\ No newline at end of file
diff --git a/hints/merge-two-sorted-linked-lists.md b/hints/merge-two-sorted-linked-lists.md
new file mode 100644
index 000000000..5fbfafd3c
--- /dev/null
+++ b/hints/merge-two-sorted-linked-lists.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n + m)
time and O(1)
space, where n
is the length of list1
and m
is the length of list2
.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve storing the values of both linked lists in an array, sorting the array, and then converting it back into a linked list. This approach would use O(n)
extra space and is trivial. Can you think of a better way? Perhaps the sorted nature of the lists can be leveraged.
+
+
+
+
+
+ Hint 2
+
+ We create a dummy node to keep track of the head of the resulting linked list while iterating through the lists. Using l1
and l2
as iterators for list1
and list2
, respectively, we traverse both lists node by node to build a final linked list that is also sorted. How do you implement this?
+
+
+
+
+ Hint 3
+
+ For example, consider list1 = [1, 2, 3]
and list2 = [2, 3, 4]
. While iterating through the lists, we move the pointers by comparing the node values from both lists. We link the next pointer of the iterator to the node with the smaller value. For instance, when l1 = 1
and l2 = 2
, since l1 < l2
, we point the iterator's next pointer to l1
and proceed.
+
+
+
\ No newline at end of file
diff --git a/hints/remove-node-from-end-of-linked-list.md b/hints/remove-node-from-end-of-linked-list.md
new file mode 100644
index 000000000..d73855f6f
--- /dev/null
+++ b/hints/remove-node-from-end-of-linked-list.md
@@ -0,0 +1,47 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(N)
time and O(1)
space, where N
is the length of the given list.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve storing the nodes of the list into an array, removing the nth
node from the array, and then converting the array back into a linked list to return the new head. However, this requires O(N)
extra space. Can you think of a better approach to avoid using extra space? Maybe you should first solve with a two pass approach.
+
+
+
+
+
+ Hint 2
+
+ We can use a two-pass approach by first finding the length of the list, N
. Since removing the nth
node from the end is equivalent to removing the (N - n)th
node from the front, as they both mean the same. How can you remove the node in a linked list?
+
+
+
+
+
+ Hint 3
+
+ For example, consider a three-node list [1, 2, 3]
. If we want to remove 2
, we update the next
pointer of 1
(initially pointing to 2
) to point to the node after 2
, which is 3
. After this operation, the list becomes [1, 3]
, and we return the head. But, can we think of a more better approach? Maybe a greedy calculation can help.
+
+
+
+
+
+ Hint 4
+
+ We can solve this in one pass using a greedy approach. Move the first
pointer n
steps ahead. Then, start another pointer second
at the head and iterate both pointers simultaneously until first
reaches null
. At this point, the second
pointer is just before the node to be removed. We then remove the node that is next to the second
pointer. Why does this work?
+
+
+
+
+
+ Hint 5
+
+ This greedy approach works because the second
pointer is n
nodes behind the first
pointer. When the first
pointer reaches the end, the second
pointer is exactly n
nodes from the end. This positioning allows us to remove the nth
node from the end efficiently.
+
+
\ No newline at end of file
diff --git a/hints/reorder-linked-list.md b/hints/reorder-linked-list.md
new file mode 100644
index 000000000..299b6c081
--- /dev/null
+++ b/hints/reorder-linked-list.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 length of the given list.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to store the node values of the list in an array, reorder the values, and create a new list. Can you think of a better way? Perhaps you can try reordering the nodes directly in place, avoiding the use of extra space.
+
+
+
+
+
+ Hint 2
+
+ For example, consider the list [1, 2, 3, 4, 5]
. To reorder the list, we connect the first and last nodes, then continue with the second and second-to-last nodes, and so on. Essentially, the list is split into two halves: the first half remains as is, and the second half is reversed and merged with the first half. For instance, [1, 2]
will merge with the reversed [5, 4, 3]
. Can you figure out a way to implement this reordering process? Maybe dividing the list into two halves could help.
+
+
+
+
+
+ Hint 3
+
+ We can divide the list into two halves using the fast and slow pointer approach, which helps identify the midpoint of the list. This allows us to split the list into two halves, with the heads labeled as l1
and l2
. Next, we reverse the second half (l2
). After these steps, we proceed to reorder the two lists by iterating through them node by node, updating the next pointers accordingly.
+
+
diff --git a/hints/reverse-a-linked-list.md b/hints/reverse-a-linked-list.md
new file mode 100644
index 000000000..9d8db81d4
--- /dev/null
+++ b/hints/reverse-a-linked-list.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 length of the given list.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to store the node values of the linked list into an array, then reverse the array, convert it back into a linked list, and return the new linked list's head. This would be an O(n)
time solution but uses extra space. Can you think of a better way? Maybe there is an approach to reverse a linked list in place.
+
+
+
+
+
+ Hint 2
+
+ As you can see, the head of the linked list becomes the tail after we reverse it. Can you think of an approach to change the references of the node pointers? Perhaps reversing a simple two-node list might help clarify the process.
+
+
+
+
+
+ Hint 3
+
+ For example, consider a list [2, 3]
, where 2
is the head of the list and 3
is the tail. When we reverse it, 3
becomes the new head, and its next pointer will point to 2
. Then, 2
's next pointer will point to null
. Can you figure out how to apply this approach to reverse a linked list of length n
by iterating through it?
+
+
+
+
+
+ Hint 4
+
+ We can reverse the linked list in place by reversing the pointers between two nodes while keeping track of the next node's address. Before changing the next pointer of the current node, we must store the next node to ensure we don't lose the rest of the list during the reversal. This way, we can safely update the links between the previous and current nodes.
+
+
\ No newline at end of file
diff --git a/hints/time-based-key-value-store.md b/hints/time-based-key-value-store.md
new file mode 100644
index 000000000..5b4e80ea6
--- /dev/null
+++ b/hints/time-based-key-value-store.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(1)
time for set()
, O(logn)
time for get()
, and O(m * n)
space, where n
is the total number of values associated with a key, and m
is the total number of keys.
+
+
+
+
+
+ Hint 1
+
+ Can you think of a data structure that is useful for storing key-value pairs? Perhaps a hash-based data structure where we not only store unique elements but also associate additional information with each element?
+
+
+
+
+
+ Hint 2
+
+ We store key-value pairs in a hash map. In this case, we store the keys as usual, but instead of a single value, we store a list of values, each paired with its corresponding timestamp. This allows us to implement the set()
method in O(1)
. How can you leverage this hash map to implement the get()
method?
+
+
+
+
+
+ Hint 3
+
+ A brute force solution would involve linearly going through every value associated with the key and returning the most recent value with a timestamp less than or equal to the given timestamp. This approach has a time complexity of O(n)
for each get()
call. Can you think of a better way? Since the timestamps in the value list are sorted in ascending order by default, maybe an efficient searching algorithm could help.
+
+
+
+
+
+ Hint 4
+
+ We can use binary search because the timestamps in the values list are sorted in ascending order. This makes it straightforward to find the value with the most recent timestamp that is less than or equal to the given timestamp.
+
+
\ No newline at end of file
From b00d70a33c4c71e730e995f54b2e3a79f58e9aab Mon Sep 17 00:00:00 2001
From: Anton Dryakhlykh
Date: Mon, 18 Nov 2024 10:30:57 +0300
Subject: [PATCH 16/67] Create 0073-set-matrix-zeroes.swift
---
swift/0073-set-matrix-zeroes.swift | 39 ++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 swift/0073-set-matrix-zeroes.swift
diff --git a/swift/0073-set-matrix-zeroes.swift b/swift/0073-set-matrix-zeroes.swift
new file mode 100644
index 000000000..ec6867aca
--- /dev/null
+++ b/swift/0073-set-matrix-zeroes.swift
@@ -0,0 +1,39 @@
+class Solution {
+ func setZeroes(_ matrix: inout [[Int]]) {
+ let rows = matrix.count, cols = matrix[0].count
+ var rowZero = false
+
+ for r in 0.. 0 {
+ matrix[r][0] = 0
+ } else {
+ rowZero = true
+ }
+ }
+ }
+ }
+
+ for r in 1..
Date: Wed, 20 Nov 2024 00:39:39 +0530
Subject: [PATCH 17/67] Batch-3/Neetcode-150/Added hints (#3744)
---
hints/balanced-binary-tree.md | 23 ++++++++++++++
hints/binary-tree-diameter.md | 39 +++++++++++++++++++++++
hints/depth-of-binary-tree.md | 31 ++++++++++++++++++
hints/find-duplicate-integer.md | 39 +++++++++++++++++++++++
hints/invert-a-binary-tree.md | 23 ++++++++++++++
hints/linked-list-cycle-detection.md | 31 ++++++++++++++++++
hints/lru-cache.md | 47 ++++++++++++++++++++++++++++
hints/merge-k-sorted-linked-lists.md | 31 ++++++++++++++++++
hints/reverse-nodes-in-k-group.md | 31 ++++++++++++++++++
hints/same-binary-tree.md | 31 ++++++++++++++++++
10 files changed, 326 insertions(+)
create mode 100644 hints/balanced-binary-tree.md
create mode 100644 hints/binary-tree-diameter.md
create mode 100644 hints/depth-of-binary-tree.md
create mode 100644 hints/find-duplicate-integer.md
create mode 100644 hints/invert-a-binary-tree.md
create mode 100644 hints/linked-list-cycle-detection.md
create mode 100644 hints/lru-cache.md
create mode 100644 hints/merge-k-sorted-linked-lists.md
create mode 100644 hints/reverse-nodes-in-k-group.md
create mode 100644 hints/same-binary-tree.md
diff --git a/hints/balanced-binary-tree.md b/hints/balanced-binary-tree.md
new file mode 100644
index 000000000..51473ca01
--- /dev/null
+++ b/hints/balanced-binary-tree.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 number of nodes in the tree.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve traversing every node and checking whether the tree rooted at each node is balanced by computing the heights of its left and right subtrees. This approach would result in an O(n^2)
solution. Can you think of a more efficient way? Perhaps you could avoid repeatedly computing the heights for every node by determining balance and height in a single traversal.
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to compute the heights at each node. While calculating the heights of the left and right subtrees, we also check if the tree rooted at the current node is balanced. If leftHeight - rightHeight > 1
, we update a global variable, such as isBalanced = False
. After traversing all the nodes, the value of isBalanced
indicates whether the entire tree is balanced or not.
+
+
\ No newline at end of file
diff --git a/hints/binary-tree-diameter.md b/hints/binary-tree-diameter.md
new file mode 100644
index 000000000..d8c6b6ec3
--- /dev/null
+++ b/hints/binary-tree-diameter.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n)
time and O(n)
space, where n
is the number of nodes in the tree.
+
+
+
+
+
+ Hint 1
+
+ The diameter of a binary tree is the maximum among the sums of the left height and right height of the nodes in the tree. Why?
+
+
+
+
+
+ Hint 2
+
+ Because the diameter of a binary tree is defined as the longest path between any two nodes in the tree. The path may or may not pass through the root. For any given node, the longest path that passes through it is the sum of the height of its left subtree and the height of its right subtree.
+
+
+
+
+
+ Hint 3
+
+ A brute force solution would be to go through every node in the tree and compute its left height and right height, returning the maximum diameter found. This would be an O(n^2)
solution. Can you think of a better way? Maybe we can compute the diameter as we calculate the height of the tree? Think about what information you need from each subtree during a single traversal.
+
+
+
+
+
+ Hint 4
+
+ We can use the Depth First Search (DFS) algorithm to calculate the height of the tree. At each node, the subtrees return their respective heights (leftHeight and rightHeight). Then we calculate the diameter at that node as d = leftHeight + rightHeight
. We use a global variable to update the maximum diameter as needed during the traversal.
+
+
\ No newline at end of file
diff --git a/hints/depth-of-binary-tree.md b/hints/depth-of-binary-tree.md
new file mode 100644
index 000000000..51538e4c8
--- /dev/null
+++ b/hints/depth-of-binary-tree.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 number of nodes in the tree.
+
+
+
+
+
+ Hint 1
+
+ From the definition of binary tree's maximum depth, Can you think of a way to achieve this recursively? Maybe you should consider the max depth of the subtrees first before computing the maxdepth at the root.
+
+
+
+
+
+ Hint 2
+
+ We use the Depth First Search (DFS) algorithm to find the maximum depth of a binary tree, starting from the root
. For the subtrees rooted at the left
and right
children of the root
node, we calculate their maximum depths recursively going through left
and right
subtrees. We return 1 + max(leftDepth, rightDepth)
. Why?
+
+
+
+
+
+ Hint 3
+
+ The +1
accounts for the current node, as it contributes to the current depth in the recursion call. We pass the maximum depth from the current node's left and right subtrees to its parent because the current maximum depth determines the longest path from the parent to a leaf node through this subtree.
+
+
\ No newline at end of file
diff --git a/hints/find-duplicate-integer.md b/hints/find-duplicate-integer.md
new file mode 100644
index 000000000..e399acf89
--- /dev/null
+++ b/hints/find-duplicate-integer.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 naive approach would be to use a hash set, which takes O(1)
time to detect duplicates. Although this solution is acceptable, it requires O(n)
extra space. Can you think of a better solution that avoids using extra space? Consider that the elements in the given array nums
are within the range 1
to len(nums)
.
+
+
+
+
+
+ Hint 2
+
+ We can use the given input array itself as a hash set without creating a new one. This can be achieved by marking the positions (0
-indexed) corresponding to the elements that have already been encountered. Can you implement this?
+
+
+
+
+
+ Hint 3
+
+ We iterate through the array using index i
. For each element, we use its absolute value to find the corresponding index and mark that position as negative: nums[abs(nums[i]) - 1] *= -1
. Taking absolute value ensures we work with the original value even if it’s already negated. How can you detect duplicates?
+
+
+
+
+
+ Hint 4
+
+ For example, in the array [2, 1, 2, 3]
, where 2
is repeated, we mark the index corresponding to each element as negative. If we encounter a number whose corresponding position is already negative, it means the number is a duplicate, and we return it.
+
+
\ No newline at end of file
diff --git a/hints/invert-a-binary-tree.md b/hints/invert-a-binary-tree.md
new file mode 100644
index 000000000..eacb6582d
--- /dev/null
+++ b/hints/invert-a-binary-tree.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 number of nodes in the tree.
+
+
+
+
+
+ Hint 1
+
+ From the diagram, you can see that the left and right children of every node in the tree are swapped. Can you think of a way to achieve this recursively? Maybe an algorithm that is helpful to traverse the tree.
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm. At each node, we swap its left and right children by swapping their pointers. This inverts the current node, but every node in the tree also needs to be inverted. To achieve this, we recursively visit the left and right children and perform the same operation. If the current node is null
, we simply return.
+
+
\ No newline at end of file
diff --git a/hints/linked-list-cycle-detection.md b/hints/linked-list-cycle-detection.md
new file mode 100644
index 000000000..04c8f4623
--- /dev/null
+++ b/hints/linked-list-cycle-detection.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 length of the given list.
+
+
+
+
+
+ Hint 1
+
+ A naive approach would be to use a hash set, which takes O(1)
time to detect duplicates. Although this solution is acceptable, it requires O(n)
extra space. Can you think of a better solution that avoids using extra space? Maybe there is an efficient algorithm which uses two pointers.
+
+
+
+
+
+ Hint 2
+
+ We can use the fast and slow pointers technique, which is primarily used to detect cycles in a linked list. We iterate through the list using two pointers. The slow pointer moves one step at a time, while the fast pointer moves two steps at a time. If the list has a cycle, these two pointers will eventually meet. Why does this work?
+
+
+
+
+
+ Hint 3
+
+ When there is no cycle in the list, the loop ends when the fast pointer becomes null
. If a cycle exists, the fast pointer moves faster and continuously loops through the cycle. With each step, it reduces the gap between itself and the slow pointer by one node. For example, if the gap is 10
, the slow pointer moves by 1
, increasing the gap to 11
, while the fast pointer moves by 2
, reducing the gap to 9
. This process continues until the fast pointer catches up to the slow pointer, confirming a cycle.
+
+
\ No newline at end of file
diff --git a/hints/lru-cache.md b/hints/lru-cache.md
new file mode 100644
index 000000000..7db2c01ef
--- /dev/null
+++ b/hints/lru-cache.md
@@ -0,0 +1,47 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(1)
time for each put()
and get()
function call and an overall space of O(n)
, where n
is the capacity of the LRU
cache.
+
+
+
+
+
+ Hint 1
+
+ Can you think of a data structure for storing data in key-value pairs? Maybe a hash-based data structure with unique keys.
+
+
+
+
+
+ Hint 2
+
+ We can use a hash map which takes O(1)
time to get and put the values. But, how can you deal with the least recently used to be removed criteria as a key is updated by the put()
or recently used by the get()
functions? Can you think of a data structure to store the order of values?
+
+
+
+
+
+ Hint 3
+
+ A brute-force solution would involve maintaining the order of key-value pairs in an array list, performing operations by iterating through the list to erase and insert these key-value pairs. However, this would result in an O(n)
time complexity. Can you think of a data structure that allows removing and reinserting elements in O(1)
time?
+
+
+
+
+
+ Hint 4
+
+ We can use a doubly-linked list, which allows us to remove a node from the list when we have the address of that node. Can you think of a way to store these addresses so that we can efficiently remove or update a key when needed?
+
+
+
+
+
+ Hint 5
+
+ We can use a doubly linked list where key-value pairs are stored as nodes, with the least recently used (LRU) node at the head and the most recently used (MRU) node at the tail. Whenever a key is accessed using get()
or put()
, we remove the corresponding node and reinsert it at the tail. When the cache reaches its capacity, we remove the LRU node from the head of the list. Additionally, we use a hash map to store each key and the corresponding address of its node, enabling efficient operations in O(1)
time.
+
+
\ No newline at end of file
diff --git a/hints/merge-k-sorted-linked-lists.md b/hints/merge-k-sorted-linked-lists.md
new file mode 100644
index 000000000..aec8ab73a
--- /dev/null
+++ b/hints/merge-k-sorted-linked-lists.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(n * k)
time and O(1)
space, where k
is the total number of lists and n
is the total number of nodes across all lists.
+
+
+
+
+
+ Hint 1
+
+ A brute-force solution would involve storing all n
nodes in an array, sorting them, and converting the array back into a linked list, resulting in an O(nlogn)
time complexity. Can you think of a better way? Perhaps consider leveraging the idea behind merging two sorted linked lists.
+
+
+
+
+
+ Hint 2
+
+ We can merge two sorted linked lists without using any extra space. To handle k
sorted linked lists, we can iteratively merge each linked list with a resultant merged list. How can you implement this?
+
+
+
+
+
+ Hint 3
+
+ We iterate through the list array with index i
, starting at i = 1
. We merge the linked lists using mergeTwoLists(lists[i], lists[i - 1])
, which returns the head of the merged list. This head is stored in lists[i]
, and the process continues. Finally, the merged list is obtained at the last index, and we return its head.
+
+
\ No newline at end of file
diff --git a/hints/reverse-nodes-in-k-group.md b/hints/reverse-nodes-in-k-group.md
new file mode 100644
index 000000000..b686ce645
--- /dev/null
+++ b/hints/reverse-nodes-in-k-group.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 length of the given list.
+
+
+
+
+
+ Hint 1
+
+ A brute-force solution would involve storing the linked list node values in an array, reversing the k
groups one by one, and then converting the array back into a linked list, requiring extra space of O(n)
. Can you think of a better way? Perhaps you could apply the idea of reversing a linked list in-place without using extra space.
+
+
+
+
+
+ Hint 2
+
+ We can avoid extra space by reversing each group in-place while keeping track of the head of the next group. For example, consider the list [1, 2, 3, 4, 5]
with k = 2
. First, we reverse the group [1, 2]
to [2, 1]
. Then, we reverse [3, 4]
, resulting in [2, 1, 4, 3, 5]
. While reversing [3, 4]
, we need to link 1
to 4
and also link 3
to 5
. How can we efficiently manage these pointers?
+
+
+
+
+
+ Hint 3
+
+ We create a dummy node to handle modifications to the head of the linked list, pointing its next
pointer to the current head. We then iterate k
nodes, storing the address of the next group's head and tracking the tail of the previous group. After reversing the current group, we reconnect it by linking the previous group's tail to the new head and the current group's tail to the next group's head. This process is repeated for all groups, and we return the new head of the linked list.
+
+
\ No newline at end of file
diff --git a/hints/same-binary-tree.md b/hints/same-binary-tree.md
new file mode 100644
index 000000000..3a79a39f2
--- /dev/null
+++ b/hints/same-binary-tree.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 number of nodes in the tree.
+
+
+
+
+
+ Hint 1
+
+ Can you think of an algorithm that is used to traverse the tree? Maybe in terms of recursion.
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to traverse the tree. Can you think of a way to simultaneously traverse both the trees?
+
+
+
+
+
+ Hint 3
+
+ We traverse both trees starting from their root nodes. At each step in the recursion, we check if the current nodes in both trees are either null
or have the same value. If one node is null
while the other is not, or if their values differ, we return false
. If the values match, we recursively check their left
and right
subtrees. If any recursive call returns false
, the result for the current recursive call is false
.
+
+
\ No newline at end of file
From 7a6051c623e905a01768115b1b8a5ba3963d1c32 Mon Sep 17 00:00:00 2001
From: neetcode-gh <77742485+neetcode-gh@users.noreply.github.com>
Date: Tue, 19 Nov 2024 14:29:53 -0800
Subject: [PATCH 18/67] Update is-anagram.md
---
articles/is-anagram.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/articles/is-anagram.md b/articles/is-anagram.md
index 1460b56c7..45f2dd7d4 100644
--- a/articles/is-anagram.md
+++ b/articles/is-anagram.md
@@ -271,9 +271,9 @@ class Solution {
### Time & Space Complexity
* Time complexity: $O(n + m)$
-* Space complexity: $O(1)$
+* Space complexity: $O(1)$ since we have at most 26 different characters.
-> 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$.
---
@@ -439,6 +439,6 @@ class Solution {
### Time & Space Complexity
* Time complexity: $O(n + m)$
-* Space complexity: $O(1)$
+* Space complexity: $O(1)$ since we have at most 26 different characters.
-> Where $n$ is the length of string $s$ and $m$ is the length of string $t$.
\ No newline at end of file
+> Where $n$ is the length of string $s$ and $m$ is the length of string $t$.
From ac2ef79b1254396d146689d5060a2dfca402908a Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Thu, 21 Nov 2024 03:32:23 +0530
Subject: [PATCH 19/67] Batch-3/Neetcode-150/Added hints (#3745)
---
articles/subtree-of-a-binary-tree.md | 2 +-
...ree-from-preorder-and-inorder-traversal.md | 47 +++++++++++++++++++
hints/binary-tree-maximum-path-sum.md | 39 +++++++++++++++
hints/binary-tree-right-side-view.md | 31 ++++++++++++
hints/count-good-nodes-in-binary-tree.md | 31 ++++++++++++
hints/kth-smallest-integer-in-bst.md | 31 ++++++++++++
hints/level-order-traversal-of-binary-tree.md | 31 ++++++++++++
...t-common-ancestor-in-binary-search-tree.md | 39 +++++++++++++++
.../serialize-and-deserialize-binary-tree.md | 31 ++++++++++++
hints/subtree-of-a-binary-tree.md | 31 ++++++++++++
hints/valid-binary-search-tree.md | 31 ++++++++++++
11 files changed, 343 insertions(+), 1 deletion(-)
create mode 100644 hints/binary-tree-from-preorder-and-inorder-traversal.md
create mode 100644 hints/binary-tree-maximum-path-sum.md
create mode 100644 hints/binary-tree-right-side-view.md
create mode 100644 hints/count-good-nodes-in-binary-tree.md
create mode 100644 hints/kth-smallest-integer-in-bst.md
create mode 100644 hints/level-order-traversal-of-binary-tree.md
create mode 100644 hints/lowest-common-ancestor-in-binary-search-tree.md
create mode 100644 hints/serialize-and-deserialize-binary-tree.md
create mode 100644 hints/subtree-of-a-binary-tree.md
create mode 100644 hints/valid-binary-search-tree.md
diff --git a/articles/subtree-of-a-binary-tree.md b/articles/subtree-of-a-binary-tree.md
index 35ea1584a..3b88e53d9 100644
--- a/articles/subtree-of-a-binary-tree.md
+++ b/articles/subtree-of-a-binary-tree.md
@@ -1,4 +1,4 @@
-## 1. Brute Force (DFS)
+## 1. Depth First Search (DFS)
::tabs-start
diff --git a/hints/binary-tree-from-preorder-and-inorder-traversal.md b/hints/binary-tree-from-preorder-and-inorder-traversal.md
new file mode 100644
index 000000000..d46b6141c
--- /dev/null
+++ b/hints/binary-tree-from-preorder-and-inorder-traversal.md
@@ -0,0 +1,47 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n)
time and O(n)
space, where n
is the number of nodes.
+
+
+
+
+
+ Hint 1
+
+ You can observe that the in-order traversal helps divide the array into two halves based on the root node: the left part corresponds to the left subtree, and the right part corresponds to the right subtree. Can you think of how we can get the index of the root node in the in-order array? Maybe you should look into the pre-order traversal array.
+
+
+
+
+
+ Hint 2
+
+ From the pre-order traversal, we know that the first node is the root node. Using this information, can you now construct the binary tree?
+
+
+
+
+
+ Hint 3
+
+ After getting the root node from pre-order traversal, we then look for the index of that node in the in-order array. We can linearly search for the index but this would be an O(n^2)
solution. Can you think of a better way? Maybe we can use a data structure to get the index of a node in O(1)
?
+
+
+
+
+
+ Hint 4
+
+ We can use a hash map to get the index of any node in the in-order array in O(1)
time. How can we implement this?
+
+
+
+
+
+ Hint 5
+
+ We use Depth First Search (DFS) to construct the tree. A global variable tracks the current index in the pre-order array. Indices l
and r
represent the segment in the in-order array for the current subtree. For each node in the pre-order array, we create a node, find its index in the in-order array using the hash map, and recursively build the left and right subtrees by splitting the range [l, r]
into two parts for the left and right subtrees.
+
+
\ No newline at end of file
diff --git a/hints/binary-tree-maximum-path-sum.md b/hints/binary-tree-maximum-path-sum.md
new file mode 100644
index 000000000..318e1a388
--- /dev/null
+++ b/hints/binary-tree-maximum-path-sum.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n)
time and O(n)
space, where n
is the number of nodes in the given tree.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve checking the path sum between every pair of nodes in the tree, leading to an O(n^2)
time complexity. Can you think of a more efficient approach? Consider what information you would need at each node to calculate the path sum if it passes through the current node.
+
+
+
+
+
+ Hint 2
+
+ At a node, there are three scenarios to compute the maximum path sum that includes the current node. One includes both the left and right subtrees, with the current node as the connecting node. Another path sum includes only one of the subtrees (either left or right), but not both. Another considers the path sum extending from the current node to the parent. However, the parent’s contribution is computed during the traversal at the parent node. Can you implement this?
+
+
+
+
+
+ Hint 3
+
+ We can use the Depth First Search (DFS) algorithm to traverse the tree. We maintain a global variable to track the maximum path sum. At each node, we first calculate the maximum path sum from the left and right subtrees by traversing them. After that, we compute the maximum path sum at the current node. This approach follows a post-order traversal, where we visit the subtrees before processing the current node.
+
+
+
+
+
+ Hint 4
+
+ We return the maximum path sum from the current node to its parent, considering only one of the subtrees (either left or right) to extend the path. While calculating the left and right subtree path sums, we also ensure that we take the maximum with 0
to avoid negative sums, indicating that we should not include the subtree path in the calculation of the maximum path at the current node.
+
+
\ No newline at end of file
diff --git a/hints/binary-tree-right-side-view.md b/hints/binary-tree-right-side-view.md
new file mode 100644
index 000000000..a02d2c585
--- /dev/null
+++ b/hints/binary-tree-right-side-view.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 number of nodes in the given tree.
+
+
+
+
+
+ Hint 1
+
+ In the right-side view of a tree, can you identify the nodes that are visible? Maybe you could traverse the tree level by level and determine which nodes are visible from the right side.
+
+
+
+
+
+ Hint 2
+
+ The nodes visible in the right-side view are the last nodes at each level of the tree. Can you think of an algorithm to identify these nodes? Maybe an algorithm that can traverse the tree level by level.
+
+
+
+
+
+ Hint 3
+
+ We can use the Breadth First Search (BFS) algorithm to traverse the tree level by level. Once we completely visit a level, we take the last node of that level and add it to the result array. After processing all levels, we return the result.
+
+
\ No newline at end of file
diff --git a/hints/count-good-nodes-in-binary-tree.md b/hints/count-good-nodes-in-binary-tree.md
new file mode 100644
index 000000000..39e8783d5
--- /dev/null
+++ b/hints/count-good-nodes-in-binary-tree.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n)
time andO(n)
space, where n
is the number of nodes in the given tree.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve considering every node and checking if the path from the root to that node is valid, resulting in an O(n^2)
time complexity. Can you think of a better approach?
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to traverse the tree. But can you think of a way to determine if the current node is a good node in a single traversal? Maybe we need to track a value while traversing the tree.
+
+
+
+
+
+ Hint 3
+
+ While traversing the tree, we should track the maximum value along the current path. This allows us to determine whether the nodes we encounter are good. We can use a global variable to count the number of good nodes.
+
+
\ No newline at end of file
diff --git a/hints/kth-smallest-integer-in-bst.md b/hints/kth-smallest-integer-in-bst.md
new file mode 100644
index 000000000..2af2e63de
--- /dev/null
+++ b/hints/kth-smallest-integer-in-bst.md
@@ -0,0 +1,31 @@
+
+
+ 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 number of nodes in the given tree.
+
+
+
+
+
+ Hint 1
+
+ A naive solution would be to store the node values in an array, sort it, and then return the k-th
value from the sorted array. This would be an O(nlogn)
solution due to sorting. Can you think of a better way? Maybe you should try one of the traversal technique.
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to traverse the tree. Since the tree is a Binary Search Tree (BST), we can leverage its structure and perform an in-order traversal, where we first visit the left subtree, then the current node, and finally the right subtree. Why? Because we need the k-th
smallest integer, and by visiting the left subtree first, we ensure that we encounter smaller nodes before the current node. How can you implement this?
+
+
+
+
+
+ Hint 3
+
+ We keep a counter variable cnt
to track the position of the current node in the ascending order of values. When cnt == k
, we store the current node's value in a global variable and return. This allows us to identify and return the k-th
smallest element during the in-order traversal.
+
+
\ No newline at end of file
diff --git a/hints/level-order-traversal-of-binary-tree.md b/hints/level-order-traversal-of-binary-tree.md
new file mode 100644
index 000000000..e59c454b5
--- /dev/null
+++ b/hints/level-order-traversal-of-binary-tree.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 number of nodes in the given tree.
+
+
+
+
+
+ Hint 1
+
+ The level of a tree refers to the nodes that are at equal distance from the root node. Can you think of an algorithm that traverses the tree level by level, rather than going deeper into the tree?
+
+
+
+
+
+ Hint 2
+
+ We can use the Breadth First Search (BFS) algorithm to traverse the tree level by level. BFS uses a queue data structure to achieve this. At each step of BFS, we only iterate over the queue up to its size at that step. Then, we take the left and right child pointers and add them to the queue. This allows us to explore all paths simultaneously.
+
+
+
+
+
+ Hint 3
+
+ The number of times we iterate the queue corresponds to the number of levels in the tree. At each step, we pop all nodes from the queue for the current level and add them collectively to the resultant array. This ensures that we capture all nodes at each level of the tree.
+
+
\ No newline at end of file
diff --git a/hints/lowest-common-ancestor-in-binary-search-tree.md b/hints/lowest-common-ancestor-in-binary-search-tree.md
new file mode 100644
index 000000000..b7357e2b3
--- /dev/null
+++ b/hints/lowest-common-ancestor-in-binary-search-tree.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(h)
time and O(h)
space, where h
is the height of the given tree.
+
+
+
+
+
+ Hint 1
+
+ A Binary Search Tree (BST) is a tree in which the values of all nodes in the left subtree of a node are less than the node's value, and the values of all nodes in the right subtree are greater than the node's value. Additionally, every subtree of a BST must also satisfy this property, meaning the "less than" or "greater than" condition is valid for all nodes in the tree, not just the root. How can you use this idea to find the LCA of the given nodes in the tree?
+
+
+
+
+
+ Hint 2
+
+ We can use recursion to traverse the tree. Can you figure out the conditions we encounter when choosing a path between the left and right subtrees during traversal using the values of the two given nodes? Perhaps you can determine the LCA by traversing based on these conditions.
+
+
+
+
+
+ Hint 3
+
+ If nodes p
and q
are in different subtrees, a split occurs, making the current node the LCA. If both are in the left or right subtree, the LCA lies in that subtree and we further choose that subtree to traverse using recursion. You should also handle other multiple scenarios to get the LCA.
+
+
+
+
+
+ Hint 4
+
+ The LCA can also be one of the nodes, p
or q
, if the current node is equal to either of them. This is because if we encounter either p
or q
during the traversal, that node is the LCA.
+
+
\ No newline at end of file
diff --git a/hints/serialize-and-deserialize-binary-tree.md b/hints/serialize-and-deserialize-binary-tree.md
new file mode 100644
index 000000000..a93feef8e
--- /dev/null
+++ b/hints/serialize-and-deserialize-binary-tree.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 number of nodes in the given tree.
+
+
+
+
+
+ Hint 1
+
+ A straightforward way to serialize a tree is by traversing it and adding nodes to a string separated by a delimiter (example: ","), but this does not handle null
nodes effectively. During deserialization, it becomes unclear where to stop or how to handle missing children. Can you think of a way to indicate null
nodes explicitly?
+
+
+
+
+
+ Hint 2
+
+ Including a placeholder for null
nodes (example: "N") during serialization ensures that the exact structure of the tree is preserved. This placeholder allows us to identify missing children and reconstruct the tree accurately during deserialization.
+
+
+
+
+
+ Hint 3
+
+ We can use the Depth First Search (DFS) algorithm for both serialization and deserialization. During serialization, we traverse the tree and add node values to the result string separated by a delimiter, inserting N
whenever we encounter a null
node. During deserialization, we process the serialized string using an index i
, create nodes for valid values, and return from the current path whenever we encounter N
, reconstructing the tree accurately.
+
+
\ No newline at end of file
diff --git a/hints/subtree-of-a-binary-tree.md b/hints/subtree-of-a-binary-tree.md
new file mode 100644
index 000000000..79aaf1a57
--- /dev/null
+++ b/hints/subtree-of-a-binary-tree.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 n
and m
are the number of nodes in root
and subRoot
, respectively.
+
+
+
+
+
+ Hint 1
+
+ A subtree of a tree is a tree rooted at a specific node. We need to check whether the given subRoot
is identical to any of the subtrees of root
. Can you think of a recursive way to check this? Maybe you can leverage the idea of solving a problem where two trees are given, and you need to check whether they are identical in structure and values.
+
+
+
+
+
+ Hint 2
+
+ When two trees are identical, it means that every node in both trees has the same value and structure. We can use the Depth First Search (DFS) algorithm to solve the problem. How do you implement this?
+
+
+
+
+
+ Hint 3
+
+ We traverse the given root
, and at each node, we check if the subtree rooted at that node is identical to the given subRoot
. We use a helper function, sameTree(root1, root2)
, to determine whether the two trees passed to it are identical in both structure and values.
+
+
\ No newline at end of file
diff --git a/hints/valid-binary-search-tree.md b/hints/valid-binary-search-tree.md
new file mode 100644
index 000000000..9a691ece8
--- /dev/null
+++ b/hints/valid-binary-search-tree.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 number of nodes in the given tree.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve traversing the tree and, for every node, checking its entire left subtree to ensure all nodes are less than the current node, and its entire right subtree to ensure all nodes are greater. This results in an O(n^2)
solution. Can you think of a better way? Maybe tracking values during the traversal would help.
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to traverse the tree. At each node, we need to ensure that the tree rooted at that node is a valid Binary Search Tree (BST). One way to do this is by tracking an interval that defines the lower and upper limits for the node's value in that subtree. This interval will be updated as we move down the tree, ensuring each node adheres to the BST property.
+
+
+
+
+
+ Hint 3
+
+ We start with the interval [-infinity, infinity]
for the root node. As we traverse the tree, when checking the left subtree, we update the maximum value limit because all values in the left subtree must be less than the current node's value. Conversely, when checking the right subtree, we update the minimum value limit because all values in the right subtree must be greater than the current node's value.
+
+
\ No newline at end of file
From df08b81b893af7d0adb8a49fd4132988849147ca Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Sat, 23 Nov 2024 06:46:40 +0530
Subject: [PATCH 20/67] Sri Hari: Batch-3/Neetcode-150/Added hints (#3746)
* Batch-3/Neetcode-150/Added hints
* Batch-3/Neetcode-150/Added hints
---
articles/design-twitter-feed.md | 12 +++----
articles/kth-largest-element-in-an-array.md | 2 +-
articles/kth-largest-integer-in-a-stream.md | 2 +-
articles/task-scheduling.md | 8 ++---
hints/combination-target-sum.md | 31 ++++++++++++++++
hints/find-median-in-a-data-stream.md | 39 +++++++++++++++++++++
hints/k-closest-points-to-origin.md | 31 ++++++++++++++++
hints/kth-largest-element-in-an-array.md | 39 +++++++++++++++++++++
hints/kth-largest-integer-in-a-stream.md | 39 +++++++++++++++++++++
hints/last-stone-weight.md | 23 ++++++++++++
hints/permutations.md | 31 ++++++++++++++++
hints/subsets.md | 39 +++++++++++++++++++++
hints/task-scheduling.md | 39 +++++++++++++++++++++
13 files changed, 323 insertions(+), 12 deletions(-)
create mode 100644 hints/combination-target-sum.md
create mode 100644 hints/find-median-in-a-data-stream.md
create mode 100644 hints/k-closest-points-to-origin.md
create mode 100644 hints/kth-largest-element-in-an-array.md
create mode 100644 hints/kth-largest-integer-in-a-stream.md
create mode 100644 hints/last-stone-weight.md
create mode 100644 hints/permutations.md
create mode 100644 hints/subsets.md
create mode 100644 hints/task-scheduling.md
diff --git a/articles/design-twitter-feed.md b/articles/design-twitter-feed.md
index 87eeec612..2c53e29a8 100644
--- a/articles/design-twitter-feed.md
+++ b/articles/design-twitter-feed.md
@@ -325,10 +325,10 @@ class Twitter {
### Time & Space Complexity
-* Time complexity: $O(n \log n)$ for $getNewsFeed()$ and $O(1)$ for remaining methods.
-* Space complexity: $O(1)$
+* Time complexity: $O(n * m + t\log t)$ for each $getNewsFeed()$ call and $O(1)$ for remaining methods.
+* Space complexity: $O(N * m + N * M)$
-> Where $n$ is the number of tweets associated with the $useId$ and its $followeeIds$.
+> Where $n$ is the total number of $followeeIds$ associated with the $userId$, $m$ is the maximum number of tweets by any user, $t$ is the total number of tweets associated with the $userId$ and its $followeeIds$, $N$ is the total number of $userIds$ and $M$ is the maximum number of followees for any user.
---
@@ -778,7 +778,7 @@ class Twitter {
### Time & Space Complexity
-* Time complexity: $O(n+\log n)$ for $getNewsFeed()$ and $O(1)$ for remaining methods.
-* Space complexity: $O(1)$
+* Time complexity: $O(n)$ for each $getNewsFeed()$ call and $O(1)$ for remaining methods.
+* Space complexity: $O(N * m + N * M + n)$
-> Where $n$ is the number of tweets associated with the $useId$ and its $followeeIds$.
\ No newline at end of file
+> Where $n$ is the total number of $followeeIds$ associated with the $userId$, $m$ is the maximum number of tweets by any user, $N$ is the total number of $userIds$ and $M$ is the maximum number of followees for any user.
\ 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 b901745c4..ba0f51363 100644
--- a/articles/kth-largest-element-in-an-array.md
+++ b/articles/kth-largest-element-in-an-array.md
@@ -76,7 +76,7 @@ class Solution {
---
-## 2. Heap
+## 2. Min-Heap
::tabs-start
diff --git a/articles/kth-largest-integer-in-a-stream.md b/articles/kth-largest-integer-in-a-stream.md
index 9bc24a5b3..7913b93ca 100644
--- a/articles/kth-largest-integer-in-a-stream.md
+++ b/articles/kth-largest-integer-in-a-stream.md
@@ -135,7 +135,7 @@ class KthLargest(k: Int, nums: IntArray) {
---
-## 2. Heap
+## 2. Min-Heap
::tabs-start
diff --git a/articles/task-scheduling.md b/articles/task-scheduling.md
index 1a3f3c55a..d6718ba3f 100644
--- a/articles/task-scheduling.md
+++ b/articles/task-scheduling.md
@@ -341,7 +341,7 @@ class Solution {
---
-## 2. Heap
+## 2. Max-Heap
::tabs-start
@@ -609,7 +609,7 @@ class Solution {
### Time & Space Complexity
* Time complexity: $O(m)$
-* Space complexity: $O(m)$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
> Where $m$ is the number of tasks.
@@ -780,7 +780,7 @@ class Solution {
### Time & Space Complexity
* Time complexity: $O(m)$
-* Space complexity: $O(1)$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
> Where $m$ is the number of tasks.
@@ -956,6 +956,6 @@ class Solution {
### Time & Space Complexity
* Time complexity: $O(m)$
-* Space complexity: $O(1)$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
> Where $m$ is the number of tasks.
\ No newline at end of file
diff --git a/hints/combination-target-sum.md b/hints/combination-target-sum.md
new file mode 100644
index 000000000..cf6d8d47d
--- /dev/null
+++ b/hints/combination-target-sum.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(2^(t/m))
time and O(t/m)
space, where t
is the given target
and m
is the minimum value in the given array.
+
+
+
+
+
+ Hint 1
+
+ Can you think of this problem in terms of a decision tree, where at each step, we have n
decisions, where n
is the size of the array? In this decision tree, we can observe that different combinations of paths are formed. Can you think of a base condition to stop extending a path? Maybe you should consider the target value.
+
+
+
+
+
+ Hint 2
+
+ We can use backtracking to recursively traverse these paths and make decisions to choose an element at each step. We maintain a variable sum
, which represents the sum of all the elements chosen in the current path. We stop this recursive path if sum == target
, and add a copy of the chosen elements to the result. How do you implement it?
+
+
+
+
+
+ Hint 3
+
+ We recursively select elements, increasing the sum
and appending the element to the temporary list, which tracks the chosen elements in the current path. At each step, we have the option to consider all elements in the array, but we only proceed with elements that, when added to sum
, do not exceed the target
. We iterate through the entire array at each step, choosing elements accordingly.
+
+
\ No newline at end of file
diff --git a/hints/find-median-in-a-data-stream.md b/hints/find-median-in-a-data-stream.md
new file mode 100644
index 000000000..ea07e7519
--- /dev/null
+++ b/hints/find-median-in-a-data-stream.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(logn)
time for addNum()
, O(1)
time for findMedian()
, and O(n)
space, where n
is the current number of elements.
+
+
+
+
+
+ Hint 1
+
+ A naive solution would be to store the data stream in an array and sort it each time to find the median, resulting in O(nlogn)
time for each findMedian()
call. Can you think of a better way? Perhaps using a data structure that allows efficient insertion and retrieval of the median can make the solution more efficient.
+
+
+
+
+
+ Hint 2
+
+ If we divide the array into two parts, we can find the median in O(1)
if the left half can efficiently return the maximum and the right half can efficiently return the minimum. These values determine the median. However, the process changes slightly if the total number of elements is odd — in that case, the median is the element from the half with the larger size. Can you think of a data structure which is suitable to implement this?
+
+
+
+
+
+ Hint 3
+
+ We can use a Heap (Max-Heap for the left half and Min-Heap for the right half). Instead of dividing the array, we store the elements in these heaps as they arrive in the data stream. But how can you maintain equal halves of elements in these two heaps? How do you implement this?
+
+
+
+
+
+ Hint 4
+
+ We initialize a Max-Heap and a Min-Heap. When adding an element, if the element is greater than the minimum element of the Min-Heap, we push it into the Min-Heap; otherwise, we push it into the Max-Heap. If the size difference between the two heaps becomes greater than one, we rebalance them by popping an element from the larger heap and pushing it into the smaller heap. This process ensures that the elements are evenly distributed between the two heaps, allowing us to retrieve the middle element or elements in O(1)
time.
+
+
\ No newline at end of file
diff --git a/hints/k-closest-points-to-origin.md b/hints/k-closest-points-to-origin.md
new file mode 100644
index 000000000..277e19160
--- /dev/null
+++ b/hints/k-closest-points-to-origin.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(nlogk)
time and O(k)
space, where n
is the size of the input array, and k
is the number of points to be returned.
+
+
+
+
+
+ Hint 1
+
+ A naive solution would be to sort the array in ascending order based on the distances of the points from the origin (0, 0)
and return the first k
points. This would take O(nlogn)
time. Can you think of a better way? Perhaps you could use a data structure that maintains only k
points and allows efficient insertion and removal.
+
+
+
+
+
+ Hint 2
+
+ We can use a Max-Heap that keeps the maximum element at its top and allows retrieval in O(1)
time. This data structure is ideal because we need to return the k
closest points to the origin. By maintaining only k
points in the heap, we can efficiently remove the farthest point when the size exceeds k
. How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We initialize a Max-Heap that orders points based on their distances from the origin. Starting with an empty heap, we iterate through the array of points, inserting each point into the heap. If the size of the heap exceeds k
, we remove the farthest point (the maximum element in the heap). After completing the iteration, the heap will contain the k
closest points to the origin. Finally, we convert the heap into an array and return it.
+
+
\ No newline at end of file
diff --git a/hints/kth-largest-element-in-an-array.md b/hints/kth-largest-element-in-an-array.md
new file mode 100644
index 000000000..8d68feba3
--- /dev/null
+++ b/hints/kth-largest-element-in-an-array.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(nlogk)
time and O(k)
space, where n
is the size of the input array, and k
represents the rank of the largest number to be returned (i.e., the k-th
largest element).
+
+
+
+
+
+ Hint 1
+
+ A naive solution would be to sort the array in descending order and return the k-th
largest element. This would be an O(nlogn)
solution. Can you think of a better way? Maybe you should think of a data structure which can maintain only the top k
largest elements.
+
+
+
+
+
+ Hint 2
+
+ We can use a Min-Heap, which stores elements and keeps the smallest element at its top. When we add an element to the Min-Heap, it takes O(logk)
time since we are storing k
elements in it. Retrieving the top element (the smallest in the heap) takes O(1)
time. How can this be useful for finding the k-th
largest element?
+
+
+
+
+
+ Hint 3
+
+ The k-th
largest element is the smallest element among the top k
largest elements. This means we only need to maintain k
elements in our Min-Heap to efficiently determine the k-th
largest element. Whenever the size of the Min-Heap exceeds k
, we remove the smallest element by popping from the heap. How do you implement this?
+
+
+
+
+
+ Hint 4
+
+ We initialize an empty Min-Heap. We iterate through the array and add elements to the heap. When the size of the heap exceeds k
, we pop from the heap and continue. After the iteration, the top element of the heap is the k-th
largest element.
+
+
\ No newline at end of file
diff --git a/hints/kth-largest-integer-in-a-stream.md b/hints/kth-largest-integer-in-a-stream.md
new file mode 100644
index 000000000..2d7d952e8
--- /dev/null
+++ b/hints/kth-largest-integer-in-a-stream.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(mlogk)
time and O(k)
space, where m
is the number of times add()
is called, and k
represents the rank of the largest number to be tracked (i.e., the k-th
largest element).
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would involve sorting the array in every time a number is added using add()
, and then returning the k-th
largest element. This would take O(m * nlogn)
time, where m
is the number of calls to add()
and n
is the total number of elements added. However, do we really need to track all the elements added, given that we only need the k-th
largest element? Maybe you should think of a data structure which can maintain only the top k
largest elements.
+
+
+
+
+
+ Hint 2
+
+ We can use a Min-Heap, which stores elements and keeps the smallest element at its top. When we add an element to the Min-Heap, it takes O(logk)
time since we are storing k
elements in it. Retrieving the top element (the smallest in the heap) takes O(1)
time. How can this be useful for finding the k-th
largest element?
+
+
+
+
+
+ Hint 3
+
+ The k-th
largest element is the smallest element among the top k
largest elements. This means we only need to maintain k
elements in our Min-Heap to efficiently determine the k-th
largest element. Whenever the size of the Min-Heap exceeds k
, we remove the smallest element by popping from the heap. How do you implement this?
+
+
+
+
+
+ Hint 4
+
+ We initialize a Min-Heap with the elements of the input array. When the add()
function is called, we insert the new element into the heap. If the heap size exceeds k
, we remove the smallest element (the root of the heap). Finally, the top element of the heap represents the k-th
largest element and is returned.
+
+
\ No newline at end of file
diff --git a/hints/last-stone-weight.md b/hints/last-stone-weight.md
new file mode 100644
index 000000000..5404da55d
--- /dev/null
+++ b/hints/last-stone-weight.md
@@ -0,0 +1,23 @@
+
+
+ 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
+
+ A naive solution would involve simulating the process by sorting the array at each step and processing the top 2
heaviest stones, resulting in an O(n * nlogn)
time complexity. Can you think of a better way? Consider using a data structure that efficiently supports insertion and removal of elements and maintain the sorted order.
+
+
+
+
+
+ Hint 2
+
+ We can use a Max-Heap, which allows us to retrieve the maximum element in O(1)
time. We initially insert all the weights into the Max-Heap, which takes O(logn)
time per insertion. We then simulate the process until only one or no element remains in the Max-Heap. At each step, we pop two elements from the Max-Heap which takes O(logn)
time. If they are equal, we do not insert anything back into the heap and continue. Otherwise, we insert the difference of the two elements back into the heap.
+
+
\ No newline at end of file
diff --git a/hints/permutations.md b/hints/permutations.md
new file mode 100644
index 000000000..3f3d59477
--- /dev/null
+++ b/hints/permutations.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n * n!)
time and O(n)
space, where n
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A permutation is the same as the array but with the numbers arranged in a different order. The given array itself is also considered a permutation. This means we should make a decision at each step to take any element from the array that has not been chosen previously. By doing this recursively, we can generate all permutations. How do you implement it?
+
+
+
+
+
+ Hint 2
+
+ We can use backtracking to explore all possible permutation paths. We initialize a temporary list to append the chosen elements and a boolean array of size n
(the same size as the input array) to track which elements have been picked so far (true
means the element is chosen; otherwise, false
). At each step of recursion, we iterate through the entire array, picking elements that have not been chosen previously, and proceed further along that path. Can you think of the base condition to terminate the current recursive path?
+
+
+
+
+
+ Hint 3
+
+ We observe that every permutation has the same size as the input array. Therefore, we can append a copy of the list of chosen elements in the current path to the result list if the size of the list equals the size of the input array terminating the current recursive path.
+
+
\ No newline at end of file
diff --git a/hints/subsets.md b/hints/subsets.md
new file mode 100644
index 000000000..63a694ba2
--- /dev/null
+++ b/hints/subsets.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n * (2^n))
time and O(n)
space, where n
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ It is straightforward that if the array is empty we return an empty array. When we have an array [1]
which is of size 1
, we have two subsets, [[], [1]]
as the output. Can you think why the output is so?
+
+
+
+
+
+ Hint 2
+
+ We can see that one subset includes a number, and another does not. From this, we can conclude that we need to find the subsets that include a number and those that do not. This results in 2^n
subsets for an array of size n
because there are many combinations for including and excluding the array of numbers. Since the elements are unique, duplicate subsets will not be formed if we ensure that we don't pick the element more than once in the current subset. Which algorithm is helpful to generate all subsets, and how would you implement it?
+
+
+
+
+
+ Hint 3
+
+ We can use backtracking to generate all possible subsets. We iterate through the given array with an index i
and an initially empty temporary list representing the current subset. We recursively process each index, adding the corresponding element to the current subset and continuing, which results in a subset that includes that element. Alternatively, we skip the element by not adding it to the subset and proceed to the next index, forming a subset without including that element. What can be the base condition to end this recursion?
+
+
+
+
+
+ Hint 4
+
+ When the index i
reaches the end of the array, we append a copy of the subset formed in that particular recursive path to the result list and return. All subsets of the given array are generated from these different recursive paths, which represent various combinations of "include" and "not include" steps for the elements of the array. As we are only iterating from left to right in the array, we don't pick an element more than once.
+
+
\ No newline at end of file
diff --git a/hints/task-scheduling.md b/hints/task-scheduling.md
new file mode 100644
index 000000000..1b351db49
--- /dev/null
+++ b/hints/task-scheduling.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(m)
time and O(1)
space, where m
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ There are at most 26
different tasks, represented by A
through Z
. It is more efficient to count the frequency of each task and store it in a hash map or an array of size 26
. Can you think of a way to determine which task should be processed first?
+
+
+
+
+
+ Hint 2
+
+ We should always process the most frequent task first. After selecting the most frequent task, we must ensure that it is not processed again until after n
seconds, due to the cooldown condition. Can you think of an efficient way to select the most frequent task and enforce the cooldown? Perhaps you could use a data structure that allows for O(1)
time to retrieve the maximum element and another data structure to cooldown the processed tasks.
+
+
+
+
+
+ Hint 3
+
+ We can use a Max-Heap to efficiently retrieve the most frequent task at any given instance. However, to enforce the cooldown period, we must temporarily hold off from reinserting the processed task into the heap. This is where a queue data structure comes in handy. It helps maintain the order of processed tasks. Can you implement this?
+
+
+
+
+
+ Hint 4
+
+ We start by calculating the frequency of each task and initialize a variable time
to track the total processing time. The task frequencies are inserted into a Max-Heap. We also use a queue to store tasks along with the time they become available after the cooldown. At each step, if the Max-Heap is empty, we update time
to match the next available task in the queue, covering idle time. Otherwise, we process the most frequent task from the heap, decrement its frequency, and if it's still valid, add it back to the queue with its next available time. If the task at the front of the queue becomes available, we pop it and reinsert it into the heap.
+
+
\ No newline at end of file
From 5640128430938a29ab4603268b5d018817f8f6bb Mon Sep 17 00:00:00 2001
From: Anton Dryakhlykh
Date: Sat, 23 Nov 2024 11:40:04 +0300
Subject: [PATCH 21/67] Create 2013-detect-squares.swift
---
swift/2013-detect-squares.swift | 35 +++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 swift/2013-detect-squares.swift
diff --git a/swift/2013-detect-squares.swift b/swift/2013-detect-squares.swift
new file mode 100644
index 000000000..09c58c0ff
--- /dev/null
+++ b/swift/2013-detect-squares.swift
@@ -0,0 +1,35 @@
+
+class DetectSquares {
+
+ var pts = [[Int]]()
+ var ptsCount = [[Int]: Int]()
+
+ init() {
+
+ }
+
+ func add(_ point: [Int]) {
+ ptsCount[point, default: 0] += 1
+ pts.append(point)
+ }
+
+ func count(_ point: [Int]) -> Int {
+ var res = 0
+ var x = point[0], y = point[1]
+ for val in pts {
+ let px = val[0], py = val[1]
+ if abs(py - y) != abs(px - x) || x == px || y == py {
+ continue
+ }
+ res += ptsCount[[x, py], default: 0] * ptsCount[[px, y], default: 0]
+ }
+ return res
+ }
+}
+
+/**
+ * Your DetectSquares object will be instantiated and called as such:
+ * let obj = DetectSquares()
+ * obj.add(point)
+ * let ret_2: Int = obj.count(point)
+ */
\ No newline at end of file
From 4661f2004a78dd8246bfd749d165f0616deb94d5 Mon Sep 17 00:00:00 2001
From: Bot-A0 <71089234+Ahmad-A0@users.noreply.github.com>
Date: Sun, 24 Nov 2024 08:07:46 +0000
Subject: [PATCH 22/67] =?UTF-8?q?=F0=9F=93=9C=20Update=20README=20table=20?=
=?UTF-8?q?(=F0=9F=9B=A0=EF=B8=8F=20from=20Github=20Actions)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index f495a37f6..fbe35a7f3 100644
--- a/README.md
+++ b/README.md
@@ -504,7 +504,7 @@ If you would like to have collaborator permissions on the repo to merge your own
[0048 - Rotate Image](https://leetcode.com/problems/rotate-image/) | ❌
| [✔️](c%2F0048-rotate-image.c)
| [✔️](cpp%2F0048-rotate-image.cpp)
| [✔️](csharp%2F0048-rotate-image.cs)
| ❌
| [✔️](go%2F0048-rotate-image.go)
| ❌
| [✔️](java%2F0048-rotate-image.java)
| [✔️](javascript%2F0048-rotate-image.js)
| [✔️](kotlin%2F0048-rotate-image.kt)
| [✔️](python%2F0048-rotate-image.py)
| [✔️](ruby%2F0048-rotate-image.rb)
| [✔️](rust%2F0048-rotate-image.rs)
| ❌
| [✔️](swift%2F0048-rotate-image.swift)
| [✔️](typescript%2F0048-rotate-image.ts)
[0054 - Spiral Matrix](https://leetcode.com/problems/spiral-matrix/) | ❌
| [✔️](c%2F0054-spiral-matrix.c)
| [✔️](cpp%2F0054-spiral-matrix.cpp)
| [✔️](csharp%2F0054-spiral-matrix.cs)
| ❌
| [✔️](go%2F0054-spiral-matrix.go)
| ❌
| [✔️](java%2F0054-spiral-matrix.java)
| [✔️](javascript%2F0054-spiral-matrix.js)
| [✔️](kotlin%2F0054-spiral-matrix.kt)
| [✔️](python%2F0054-spiral-matrix.py)
| [✔️](ruby%2F0054-spiral-matrix.rb)
| ❌
| ❌
| [✔️](swift%2F0054-spiral-matrix.swift)
| [✔️](typescript%2F0054-spiral-matrix.ts)
[0059 - Spiral Matrix II ](https://leetcode.com/problems/spiral-matrix-ii/) | ❌
| ❌
| [✔️](cpp%2F0059-spiral-matrix-ii.cpp)
| ❌
| ❌
| ❌
| ❌
| [✔️](java%2F0059-spiral-matrix-ii.java)
| [✔️](javascript%2F0059-spiral-matrix-ii.js)
| [✔️](kotlin%2F0059-spiral-matrix-ii.kt)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
-[0073 - Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/) | ❌
| [✔️](c%2F0073-set-matrix-zeroes.c)
| [✔️](cpp%2F0073-set-matrix-zeroes.cpp)
| [✔️](csharp%2F0073-set-matrix-zeroes.cs)
| ❌
| [✔️](go%2F0073-set-matrix-zeroes.go)
| ❌
| [✔️](java%2F0073-set-matrix-zeroes.java)
| [✔️](javascript%2F0073-set-matrix-zeroes.js)
| [✔️](kotlin%2F0073-set-matrix-zeroes.kt)
| [✔️](python%2F0073-set-matrix-zeroes.py)
| [✔️](ruby%2F0073-set-matrix-zeroes.rb)
| ❌
| ❌
| ❌
| [✔️](typescript%2F0073-set-matrix-zeroes.ts)
+[0073 - Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/) | ❌
| [✔️](c%2F0073-set-matrix-zeroes.c)
| [✔️](cpp%2F0073-set-matrix-zeroes.cpp)
| [✔️](csharp%2F0073-set-matrix-zeroes.cs)
| ❌
| [✔️](go%2F0073-set-matrix-zeroes.go)
| ❌
| [✔️](java%2F0073-set-matrix-zeroes.java)
| [✔️](javascript%2F0073-set-matrix-zeroes.js)
| [✔️](kotlin%2F0073-set-matrix-zeroes.kt)
| [✔️](python%2F0073-set-matrix-zeroes.py)
| [✔️](ruby%2F0073-set-matrix-zeroes.rb)
| ❌
| ❌
| [✔️](swift%2F0073-set-matrix-zeroes.swift)
| [✔️](typescript%2F0073-set-matrix-zeroes.ts)
[0202 - Happy Number](https://leetcode.com/problems/happy-number/) | ❌
| [✔️](c%2F0202-happy-number.c)
| [✔️](cpp%2F0202-happy-number.cpp)
| [✔️](csharp%2F0202-happy-number.cs)
| ❌
| [✔️](go%2F0202-happy-number.go)
| ❌
| [✔️](java%2F0202-happy-number.java)
| [✔️](javascript%2F0202-happy-number.js)
| [✔️](kotlin%2F0202-happy-number.kt)
| [✔️](python%2F0202-happy-number.py)
| [✔️](ruby%2F0202-happy-number.rb)
| [✔️](rust%2F0202-happy-number.rs)
| ❌
| [✔️](swift%2F0202-happy-number.swift)
| [✔️](typescript%2F0202-happy-number.ts)
[0066 - Plus One](https://leetcode.com/problems/plus-one/) | ❌
| [✔️](c%2F0066-plus-one.c)
| [✔️](cpp%2F0066-plus-one.cpp)
| [✔️](csharp%2F0066-plus-one.cs)
| ❌
| [✔️](go%2F0066-plus-one.go)
| ❌
| [✔️](java%2F0066-plus-one.java)
| [✔️](javascript%2F0066-plus-one.js)
| [✔️](kotlin%2F0066-plus-one.kt)
| [✔️](python%2F0066-plus-one.py)
| [✔️](ruby%2F0066-plus-one.rb)
| [✔️](rust%2F0066-plus-one.rs)
| ❌
| [✔️](swift%2F0066-plus-one.swift)
| [✔️](typescript%2F0066-plus-one.ts)
[0009 - Palindrome Number](https://leetcode.com/problems/palindrome-number/) | ❌
| [✔️](c%2F0009-palindrome-number.c)
| [✔️](cpp%2F0009-palindrome-number.cpp)
| ❌
| ❌
| [✔️](go%2F0009-palindrome-number.go)
| ❌
| [✔️](java%2F0009-palindrome-number.java)
| [✔️](javascript%2F0009-palindrome-number.js)
| [✔️](kotlin%2F0009-palindrome-number.kt)
| [✔️](python%2F0009-palindrome-number.py)
| ❌
| [✔️](rust%2F0009-palindrome-number.rs)
| ❌
| [✔️](swift%2F0009-palindrome-number.swift)
| [✔️](typescript%2F0009-palindrome-number.ts)
@@ -514,7 +514,7 @@ If you would like to have collaborator permissions on the repo to merge your own
[0012 - Integer to Roman](https://leetcode.com/problems/integer-to-roman/) | ❌
| ❌
| [✔️](cpp%2F0012-integer-to-roman.cpp)
| ❌
| ❌
| [✔️](go%2F0012-integer-to-roman.go)
| ❌
| [✔️](java%2F0012-integer-to-roman.java)
| [✔️](javascript%2F0012-integer-to-roman.js)
| [✔️](kotlin%2F0012-integer-to-roman.kt)
| [✔️](python%2F0012-integer-to-roman.py)
| ❌
| [✔️](rust%2F0012-integer-to-roman.rs)
| ❌
| ❌
| [✔️](typescript%2F0012-integer-to-roman.ts)
[0050 - Pow(x, n)](https://leetcode.com/problems/powx-n/) | ❌
| [✔️](c%2F0050-powx-n.c)
| [✔️](cpp%2F0050-powx-n.cpp)
| [✔️](csharp%2F0050-powx-n.cs)
| ❌
| ❌
| ❌
| [✔️](java%2F0050-powx-n.java)
| [✔️](javascript%2F0050-powx-n.js)
| [✔️](kotlin%2F0050-powx-n.kt)
| [✔️](python%2F0050-powx-n.py)
| [✔️](ruby%2F0050-powx-n.rb)
| [✔️](rust%2F0050-powx-n.rs)
| ❌
| [✔️](swift%2F0050-powx-n.swift)
| [✔️](typescript%2F0050-powx-n.ts)
[0043 - Multiply Strings](https://leetcode.com/problems/multiply-strings/) | ❌
| [✔️](c%2F0043-multiply-strings.c)
| [✔️](cpp%2F0043-multiply-strings.cpp)
| [✔️](csharp%2F0043-multiply-strings.cs)
| ❌
| ❌
| ❌
| [✔️](java%2F0043-multiply-strings.java)
| [✔️](javascript%2F0043-multiply-strings.js)
| [✔️](kotlin%2F0043-multiply-strings.kt)
| [✔️](python%2F0043-multiply-strings.py)
| [✔️](ruby%2F0043-multiply-strings.rb)
| [✔️](rust%2F0043-multiply-strings.rs)
| ❌
| [✔️](swift%2F0043-multiply-strings.swift)
| [✔️](typescript%2F0043-multiply-strings.ts)
-[2013 - Detect Squares](https://leetcode.com/problems/detect-squares/) | ❌
| ❌
| [✔️](cpp%2F2013-Detect-Squares.cpp)
| [✔️](csharp%2F2013-Detect-Squares.cs)
| ❌
| ❌
| ❌
| [✔️](java%2F2013-Detect-Squares.java)
| [✔️](javascript%2F2013-Detect-Squares.js)
| [✔️](kotlin%2F2013-detect-squares.kt)
| [✔️](python%2F2013-detect-squares.py)
| [✔️](ruby%2F2013-detect-squares.rb)
| [✔️](rust%2F2013-detect-squares.rs)
| ❌
| ❌
| ❌
+[2013 - Detect Squares](https://leetcode.com/problems/detect-squares/) | ❌
| ❌
| [✔️](cpp%2F2013-Detect-Squares.cpp)
| [✔️](csharp%2F2013-Detect-Squares.cs)
| ❌
| ❌
| ❌
| [✔️](java%2F2013-Detect-Squares.java)
| [✔️](javascript%2F2013-Detect-Squares.js)
| [✔️](kotlin%2F2013-detect-squares.kt)
| [✔️](python%2F2013-detect-squares.py)
| [✔️](ruby%2F2013-detect-squares.rb)
| [✔️](rust%2F2013-detect-squares.rs)
| ❌
| [✔️](swift%2F2013-detect-squares.swift)
| ❌
[1041 - Robot Bounded In Circle](https://leetcode.com/problems/robot-bounded-in-circle/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](java%2F1041-robot-bounded-in-circle.java)
| ❌
| [✔️](kotlin%2F1041-robot-bounded-in-circle.kt)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
[0006 - Zigzag Conversion](https://leetcode.com/problems/zigzag-conversion/) | ❌
| ❌
| [✔️](cpp%2F0006-zigzag-conversion.cpp)
| ❌
| ❌
| [✔️](go%2F0006-zigzag-conversion.go)
| ❌
| [✔️](java%2F0006-zigzag-conversion.java)
| ❌
| [✔️](kotlin%2F0006-zigzag-conversion.kt)
| [✔️](python%2F0006-zigzag-conversion.py)
| ❌
| ❌
| ❌
| ❌
| ❌
[2028 - Find Missing Observations](https://leetcode.com/problems/find-missing-observations/) | ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
| [✔️](kotlin%2F2028-find-missing-observations.kt)
| ❌
| ❌
| ❌
| ❌
| ❌
| ❌
From 8e802c589cafeb39e4a54b6b5fbf0654ce8c6b74 Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Sun, 24 Nov 2024 22:02:07 +0530
Subject: [PATCH 23/67] Batch-3/Neetcode-150/Added hints (#3749)
---
articles/design-word-search-data-structure.md | 6 +--
hints/combination-target-sum-ii.md | 31 +++++++++++++++
hints/combination-target-sum.md | 2 +-
hints/combinations-of-a-phone-number.md | 31 +++++++++++++++
hints/design-word-search-data-structure.md | 31 +++++++++++++++
hints/implement-prefix-tree.md | 31 +++++++++++++++
hints/n-queens.md | 31 +++++++++++++++
hints/palindrome-partitioning.md | 31 +++++++++++++++
hints/search-for-word-ii.md | 39 +++++++++++++++++++
hints/search-for-word.md | 31 +++++++++++++++
hints/subsets-ii.md | 31 +++++++++++++++
11 files changed, 291 insertions(+), 4 deletions(-)
create mode 100644 hints/combination-target-sum-ii.md
create mode 100644 hints/combinations-of-a-phone-number.md
create mode 100644 hints/design-word-search-data-structure.md
create mode 100644 hints/implement-prefix-tree.md
create mode 100644 hints/n-queens.md
create mode 100644 hints/palindrome-partitioning.md
create mode 100644 hints/search-for-word-ii.md
create mode 100644 hints/search-for-word.md
create mode 100644 hints/subsets-ii.md
diff --git a/articles/design-word-search-data-structure.md b/articles/design-word-search-data-structure.md
index 9050009e5..2771fc3f8 100644
--- a/articles/design-word-search-data-structure.md
+++ b/articles/design-word-search-data-structure.md
@@ -226,10 +226,10 @@ class WordDictionary {
### Time & Space Complexity
-* Time complexity: $O(1)$ for $addWord()$, $O(m * n)$ for $search()$.
+* Time complexity: $O(n)$ for $addWord()$, $O(m * n)$ for $search()$.
* Space complexity: $O(m * n)$
-> Where $m$ is the number of words added and $n$ is the length of the search string.
+> Where $m$ is the number of words added and $n$ is the length of the string.
---
@@ -631,7 +631,7 @@ class WordDictionary {
### Time & Space Complexity
-* Time complexity: $O(n)$ for $addWord()$, $O(26 ^ n)$ for $search()$.
+* Time complexity: $O(n)$ for $addWord()$, $O(n)$ for $search()$.
* Space complexity: $O(t + n)$
> Where $n$ is the length of the string and $t$ is the total number of TrieNodes created in the Trie.
\ No newline at end of file
diff --git a/hints/combination-target-sum-ii.md b/hints/combination-target-sum-ii.md
new file mode 100644
index 000000000..ef8aabd56
--- /dev/null
+++ b/hints/combination-target-sum-ii.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n * (2^n))
time and O(n)
space, where n
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A brute-force solution would be to create a hash set
, which is used to detect duplicates, to get combinations without duplicates. Can you think of a better way without using a hash set
? Maybe you should sort the input array and observe the recursive calls that are responsible for duplicate combinations.
+
+
+
+
+
+ Hint 2
+
+ We can use backtracking to generate all combinations whose sum equals the given target. When the input array contains duplicate elements, it may result in duplicate combinations. To avoid this, we can sort the array. Why does sorting help? Because as we traverse the array from left to right, we form combinations with the current element. By skipping duplicate elements, we ensure that the same combinations are not repeated for identical elements. How can you implement this?
+
+
+
+
+
+ Hint 3
+
+ We recursively traverse the given array starting at index i
, with a variable sum
representing the sum of the picked elements. We explore elements from i
to the end of the array and extend the recursive path if adding the current element results in sum <= target
. When we processed an element, we backtrack and proceed to the next distinct element, skipping any similar elements in the middle to avoid duplicate combinations.
+
+
\ No newline at end of file
diff --git a/hints/combination-target-sum.md b/hints/combination-target-sum.md
index cf6d8d47d..1eca71f3f 100644
--- a/hints/combination-target-sum.md
+++ b/hints/combination-target-sum.md
@@ -26,6 +26,6 @@
Hint 3
- We recursively select elements, increasing the sum
and appending the element to the temporary list, which tracks the chosen elements in the current path. At each step, we have the option to consider all elements in the array, but we only proceed with elements that, when added to sum
, do not exceed the target
. We iterate through the entire array at each step, choosing elements accordingly.
+ We recursively traverse the array starting from index i
. At each step, we select an element from i
to the end of the array. We extend the recursive path with elements where sum <= target
after including that element. This creates multiple recursive paths, and we append the current list to the result whenever the base condition is met.
\ No newline at end of file
diff --git a/hints/combinations-of-a-phone-number.md b/hints/combinations-of-a-phone-number.md
new file mode 100644
index 000000000..7154a859d
--- /dev/null
+++ b/hints/combinations-of-a-phone-number.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n * (4^n))
time and O(n)
space, where n
is the length of the input string.
+
+
+
+
+
+ Hint 1
+
+ We can use a hash map to pair all the digits with their corresponding letters. Think of this as a decision tree, where at each step, we have a digit, and we select one of multiple characters to proceed to the next digit in the given string digits
. Can you think of an algorithm to generate all combinations of strings?
+
+
+
+
+
+ Hint 2
+
+ We can use backtracking where we select a character and process it, then backtrack to process another character. We recursively iterate on the given string with index i
. At each step, we consider the letters from the hash map that correspond to the digit at the i-th
index. Can you think of the base condition to stop this recursive path?
+
+
+
+
+
+ Hint 3
+
+ We initialize an empty string that represents the choices of the characters throughout the current recursive path. When the index i
reaches the end of the string, we add the current string to the result list and return.
+
+
\ No newline at end of file
diff --git a/hints/design-word-search-data-structure.md b/hints/design-word-search-data-structure.md
new file mode 100644
index 000000000..db99718c2
--- /dev/null
+++ b/hints/design-word-search-data-structure.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n)
time for each function call and O(t + n)
space, where n
is the length of the string and t
is the total number of nodes created in the Trie.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to store each added word in a list and search linearly through the list for a word every time. This would be an O(m * n)
solution, where m
is the size of the list and n
is the length of the string. Can you think of a better way? Maybe there is a tree-like data structure.
+
+
+
+
+
+ Hint 2
+
+ We can use a Trie to implement adding and searching for words efficiently. Adding a word follows the standard Trie insertion process. However, when searching for a word containing '.'
, which can match any character, we need a different approach. Instead of directly matching, we consider all possible characters at the position of '.'
and recursively check the rest of the word for each possibility. How would you implement it?
+
+
+
+
+
+ Hint 3
+
+ We traverse the word with index i
, starting at the root of the Trie. For normal characters, we search as usual. When encountering a dot ('.'
), we try all possible characters by recursively extending the search in each direction. If any path leads to a valid word, we return true
; otherwise, we return false
. Although we try all paths for a dot, the time complexity is still O(n)
because there are at most two dots ('.'
) in the word, making the complexity O((26^2) * n)
.
+
+
\ No newline at end of file
diff --git a/hints/implement-prefix-tree.md b/hints/implement-prefix-tree.md
new file mode 100644
index 000000000..f2908be7f
--- /dev/null
+++ b/hints/implement-prefix-tree.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n)
time for each function call and O(t)
space, where n
is the length of the given string and t
is the total number of nodes created in the Trie.
+
+
+
+
+
+ Hint 1
+
+ A Trie is structured as a tree-like data structure where each node contains a hash map (or an array for fixed character sets) to store references to its child nodes, which represent characters. Each node also includes a boolean flag to indicate whether the current node marks the end of a valid word. The Trie starts with a root node that does not hold any character and serves as the entry point for all operations. The child nodes of the root and subsequent nodes represent unique characters from the words stored in the Trie, forming a hierarchical structure based on the prefixes of the words.
+
+
+
+
+
+ Hint 2
+
+ To insert a word, we iterate through the characters of the word with index i
, starting at the root of the Trie as the current node. If the current node already contains word[i]
, we continue to the next character and move to the node that word[i]
points to. If word[i]
is not present, we create a new node for word[i]
and continue the process until we reach the end of the word. We mark the boolean variable as true as it is the end of the inserted word.
+
+
+
+
+
+ Hint 3
+
+ Searching for a word is similar to inserting, but instead of creating new nodes, we return false
if we don't find a character in the path while iterating or if the end-of-word marker is not set to true
when we reach the end of the word.
+
+
\ No newline at end of file
diff --git a/hints/n-queens.md b/hints/n-queens.md
new file mode 100644
index 000000000..60c5f6fef
--- /dev/null
+++ b/hints/n-queens.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n!)
time and O(n^2)
space, where n
is the size of the given square board.
+
+
+
+
+
+ Hint 1
+
+ A queen can move in 8
directions, and no two queens can be in the same row or column. This means we can place one queen per row or column. We iterate column-wise and try to place a queen in each column while ensuring no other queen exists in the same row, left diagonal, or left bottom diagonal. Can you think of a recursive algorithm to find all possible combinations?
+
+
+
+
+
+ Hint 2
+
+ We can use backtracking to traverse through the columns with index c
while maintaining a board that represents the current state in the recursive path. We reach the base condition when c == n
and we add a copy of the board to the result. How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We initialize an empty board and recursively go through each column. For each column, we check each cell to see if we can place a queen there. We use a function to check if the cell is suitable by iterating along the left directions and verifying if the same row, left diagonal, or left bottom diagonal are free. If it is possible, we place the queen on the board, move along the recursive path, and then backtrack by removing the queen to continue to the next cell in the column.
+
+
\ No newline at end of file
diff --git a/hints/palindrome-partitioning.md b/hints/palindrome-partitioning.md
new file mode 100644
index 000000000..a2d81783f
--- /dev/null
+++ b/hints/palindrome-partitioning.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n * (2^n))
time and O(n)
space, where n
is the length of the input string.
+
+
+
+
+
+ Hint 1
+
+ For a given string there are 2^n
possible partitions because at each index we have two decisions: we can either partition and start a new string, or continue without partitioning. Can you think of an algorithm to recursively traverse all combinations?
+
+
+
+
+
+ Hint 2
+
+ We can use backtracking to recursively traverse the string with indices j
(start of the current substring) and i
(current iterating index). At each step, we either skip partitioning at the current index or, if the substring from j
to i
is a palindrome, make a partition, update j = i + 1
, and start a new substring. The base condition to stop the recursion is when j
reaches the end of the string. How do you implement this?
+
+
+
+
+
+ Hint 3
+
+ We start with j = 0
, i = 0
and a temporary list which stores the substrings from the partitions. Then we recursively iterate the string with the index i
. At each step we apply the 2
decisions accordingly. At the base condition of the recursive path, we make a copy of the current partition list and add it to the result.
+
+
\ No newline at end of file
diff --git a/hints/search-for-word-ii.md b/hints/search-for-word-ii.md
new file mode 100644
index 000000000..205964c7e
--- /dev/null
+++ b/hints/search-for-word-ii.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(m * n * 4 * (3^(t-1)) + s)
time and O(s)
space, where m
is the number of rows, n
is the number of columns, t
is the maximum length of any word and s
is the sum of the lengths of all the words.
+
+
+
+
+
+ Hint 1
+
+ To search for a word in the grid, we can use backtracking by starting at each cell, simultaneously iterating through the word and matching the characters with the cells, recursively visiting the neighboring cells. However, if we are given a list of words and need to search for each one, it becomes inefficient to iterate through each word and run backtracking for each. Can you think of a better way? Perhaps a data structure could help with more efficient word search and insertion.
+
+
+
+
+
+ Hint 2
+
+ We can use a Trie to efficiently search for multiple words. After inserting all words into the Trie, we traverse the grid once. For each character in the grid, we check if it exists in the current Trie node. If not, we prune the search. If we encounter an "end of word" flag in the Trie node, we know a valid word has been found. But how can we add that word to the result list? Maybe you should think about what additional information you can store in the Trie node.
+
+
+
+
+
+ Hint 3
+
+ When we insert a word into the Trie, we can store the word's index. Why? Because when we want to add the word to the result list after finding a valid word, we can easily add it using the index. After adding that word, we put index = -1
as we shouldn't add the word multiple times to the result list. How can you implement this?
+
+
+
+
+
+ Hint 4
+
+ We insert all the words into the Trie with their indices marked. Then, we iterate through each cell in the grid. At each cell, we start at the root of the Trie and explore all possible paths. As we traverse, we match characters in the cell with those in the Trie nodes. If we encounter the end of a word, we take the index at that node and add the corresponding word to the result list. Afterward, we unmark that index and continue exploring further paths.
+
+
\ No newline at end of file
diff --git a/hints/search-for-word.md b/hints/search-for-word.md
new file mode 100644
index 000000000..9dcdf4102
--- /dev/null
+++ b/hints/search-for-word.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(m * (4^n))
time and O(n)
space, where m
is the number of cells in the given board
and n
is the size of the given word
.
+
+
+
+
+
+ Hint 1
+
+ As we can start at any cell on the board, we can explore all paths from that cell. Can you think of an algorithm to do so? Also, you should consider a way to avoid visiting a cell that has already been visited in the current path.
+
+
+
+
+
+ Hint 2
+
+ We can use a hash set to avoid revisiting a cell in the current path by inserting the (row, col)
of the visiting cell into the hash set and exploring all paths (four directions, as we can move to four neighboring cells) from that cell. Can you think of the base condition for this recursive path? Maybe you should consider the board boundaries, and also, we can extend a path if the character at the cell matches the character in the word.
+
+
+
+
+
+ Hint 3
+
+ We can use backtracking, starting from each cell on the board with coordinates (row, col)
and index i
for the given word. We return false if (row, col)
is out of bounds or if board[row][col] != word[i]
. When i
reaches the end of the word, we return true, indicating a valid path. At each step, we add (row, col)
to a hash set to avoid revisiting cells. After exploring the four possible directions, we backtrack and remove (row, col)
from the hash set.
+
+
\ No newline at end of file
diff --git a/hints/subsets-ii.md b/hints/subsets-ii.md
new file mode 100644
index 000000000..4001ea052
--- /dev/null
+++ b/hints/subsets-ii.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(n * (2^n))
time and O(n)
space, where n
is the size of the input array.
+
+
+
+
+
+ Hint 1
+
+ A brute-force solution would involve creating a hash set and inserting every subset into it. Then, converting the hash set to a list and returning it. However, this approach would require extra space of O(2^n)
. Can you think of a better way? Maybe you should sort the input array and observe which recusive calls are resposible to make duplicate subsets.
+
+
+
+
+
+ Hint 2
+
+ We can use backtracking to generate subsets of an array. If the input contains duplicates, duplicate subsets may be created. To prevent this, we sort the array beforehand. For example, in [1, 1, 2]
, sorting allows us to create subsets using the first 1
and skip the second 1
, ensuring unique subsets. How can you implement this?
+
+
+
+
+
+ Hint 3
+
+ We start by sorting the input array. Then, we recursively iterate through the array from left to right, extending recursive paths by including or excluding each element. To avoid duplicate subsets, we skip an element if it is the same as the previous one. Finally, we return the generated subsets as a list.
+
+
\ No newline at end of file
From c4ff1cc35c6e65f2cbbed8d8d99b984b352d0c3d Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Thu, 28 Nov 2024 18:24:39 +0530
Subject: [PATCH 24/67] Batch-3/Neetcode-150/Added hints (#3750)
---
articles/pacific-atlantic-water-flow.md | 2 +-
hints/clone-graph.md | 31 ++++++++++++++++++++
hints/count-number-of-islands.md | 23 +++++++++++++++
hints/course-schedule.md | 31 ++++++++++++++++++++
hints/design-twitter-feed.md | 39 +++++++++++++++++++++++++
hints/islands-and-treasure.md | 31 ++++++++++++++++++++
hints/max-area-of-island.md | 31 ++++++++++++++++++++
hints/pacific-atlantic-water-flow.md | 31 ++++++++++++++++++++
hints/rotting-fruit.md | 31 ++++++++++++++++++++
hints/surrounded-regions.md | 31 ++++++++++++++++++++
10 files changed, 280 insertions(+), 1 deletion(-)
create mode 100644 hints/clone-graph.md
create mode 100644 hints/count-number-of-islands.md
create mode 100644 hints/course-schedule.md
create mode 100644 hints/design-twitter-feed.md
create mode 100644 hints/islands-and-treasure.md
create mode 100644 hints/max-area-of-island.md
create mode 100644 hints/pacific-atlantic-water-flow.md
create mode 100644 hints/rotting-fruit.md
create mode 100644 hints/surrounded-regions.md
diff --git a/articles/pacific-atlantic-water-flow.md b/articles/pacific-atlantic-water-flow.md
index a866accf0..1b718571a 100644
--- a/articles/pacific-atlantic-water-flow.md
+++ b/articles/pacific-atlantic-water-flow.md
@@ -1,4 +1,4 @@
-## 1. Backtracking
+## 1. Brute Force (Backtracking)
::tabs-start
diff --git a/hints/clone-graph.md b/hints/clone-graph.md
new file mode 100644
index 000000000..1e332bf4a
--- /dev/null
+++ b/hints/clone-graph.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(V + E)
time and O(E)
space, where V
is the number of vertices and E
is the number of edges in the given graph.
+
+
+
+
+
+ Hint 1
+
+ We are given only the reference to the node in the graph. Cloning the entire graph means we need to clone all the nodes as well as their child nodes. We can't just clone the node and its neighbor and return the node. We also need to clone the entire graph. Can you think of a recursive way to do this, as we are cloning nodes in a nested manner? Also, can you think of a data structure that can store the nodes with their cloned references?
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm. We use a hash map to map the nodes to their cloned nodes. We start from the given node. At each step of the DFS, we create a node with the current node's value. We then recursively go to the current node's neighbors and try to clone them first. After that, we add their cloned node references to the current node's neighbors list. Can you think of a base condition to stop this recursive path?
+
+
+
+
+
+ Hint 3
+
+ We stop this recursive path when we encounter a node that has already been cloned or visited. This DFS approach creates an exact clone of the given graph, and we return the clone of the given node.
+
+
\ No newline at end of file
diff --git a/hints/count-number-of-islands.md b/hints/count-number-of-islands.md
new file mode 100644
index 000000000..a8cb92e6f
--- /dev/null
+++ b/hints/count-number-of-islands.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 grid.
+
+
+
+
+
+ Hint 1
+
+ An island is a group of 1
's in which every 1
is reachable from any other 1
in that group. Can you think of an algorithm that can find the number of groups by visiting a group only once? Maybe there is a recursive way of doing it.
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to traverse each group independently. We iterate through each cell of the grid. When we encounter a 1
, we perform a DFS starting at that cell and recursively visit every other 1
that is reachable. During this process, we mark the visited 1
's as 0
to ensure we don't revisit them, as they belong to the same group. The number of groups corresponds to the number of islands.
+
+
\ No newline at end of file
diff --git a/hints/course-schedule.md b/hints/course-schedule.md
new file mode 100644
index 000000000..1660429b5
--- /dev/null
+++ b/hints/course-schedule.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(V + E)
time and O(V + E)
space, where V
is the number of courses (nodes) and E
is the number of prerequisites (edges).
+
+
+
+
+
+ Hint 1
+
+ Consider the problem as a graph where courses represent the nodes, and prerequisite[i] = [a, b]
represents a directed edge from a
to b
. We need to determine whether the graph contains a cycle. Why? Because if there is a cycle, it is impossible to complete the courses involved in the cycle. Can you think of an algorithm to detect cycle in a graph?
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to detect a cycle in a graph. We iterate over each course, run a DFS from that course, and first try to finish its prerequisite courses by recursively traversing through them. To detect a cycle, we initialize a hash set called path
, which contains the nodes visited in the current DFS call. If we encounter a course that is already in the path
, we can conclude that a cycle is detected. How would you implement it?
+
+
+
+
+
+ Hint 3
+
+ We run a DFS starting from each course by initializing a hash set, path
, to track the nodes in the current DFS call. At each step of the DFS, we return false
if the current node is already in the path
, indicating a cycle. We recursively traverse the neighbors of the current node, and if any of the neighbor DFS calls detect a cycle, we immediately return false
. Additionally, we clear the neighbors list of a node when no cycle is found from that node to avoid revisiting those paths again.
+
+
\ No newline at end of file
diff --git a/hints/design-twitter-feed.md b/hints/design-twitter-feed.md
new file mode 100644
index 000000000..4dcbd38e4
--- /dev/null
+++ b/hints/design-twitter-feed.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(n)
time for each getNewsFeed()
function call, O(1)
time for the remaining methods, and O((N * m) + (N * M) + n)
space, where n
is the number of followeeIds
associated with the userId
, m
is the maximum number of tweets by any user, N
is the total number of userIds
, and M
is the maximum number of followees for any user.
+
+
+
+
+
+ Hint 1
+
+ Can you think of a data structure to store all the information, such as userIds
and corresponding followeeIds
, or userIds
and their tweets? Maybe you should think of a hash data structure in terms of key-value pairs. Also, can you think of a way to determine that a tweet was posted before another tweet?
+
+
+
+
+
+ Hint 2
+
+ We use a hash map followMap
to store userIds
and their unique followeeIds
as a hash set
. Another hash map, tweetMap
, stores userIds
and their tweets as a list of (count, tweetId)
pairs. A counter count
, incremented with each tweet, tracks the order of tweets. The variable count
is helpful in distinguishing the time of tweets from two users. This way of storing data makes the functions follow()
, unfollow()
, and postTweet()
run in O(1)
. Can you think of a way to implement getNewsFeed()
? Maybe consider a brute force approach and try to optimize it.
+
+
+
+
+
+ Hint 3
+
+ A naive solution would involve taking the tweets of the userId and its followeeIds into a list, sorting them in descending order based on their count
values, and returning the top 10
tweets as the most recent ones. Can you think of a more efficient approach that avoids collecting all tweets and sorting? Perhaps consider a data structure and leverage the fact that each user's individual tweets list is already sorted.
+
+
+
+
+
+ Hint 4
+
+ We can use a Max-Heap to efficiently retrieve the top 10
most recent tweets. For each followee and the userId, we insert their most recent tweet from the tweetMap
into the heap, along with the tweet's count
and its index in the tweet list. This index is necessary because after processing a tweet, we can insert the next most recent tweet from the same user's list. By always pushing and popping tweets from the heap, we ensure that the 10
most recent tweets are retrieved without sorting all tweets.
+
+
\ No newline at end of file
diff --git a/hints/islands-and-treasure.md b/hints/islands-and-treasure.md
new file mode 100644
index 000000000..b7ef502de
--- /dev/null
+++ b/hints/islands-and-treasure.md
@@ -0,0 +1,31 @@
+
+
+ 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 grid.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to iterate on each land cell and run a BFS from that cells to find the nearest treasure chest. This would be an O((m * n)^2)
solution. Can you think of a better way? Sometimes it is not optimal to go from source to destination.
+
+
+
+
+
+ Hint 2
+
+ We can see that instead of going from every cell to find the nearest treasure chest, we can do it in reverse. We can just do a BFS from all the treasure chests in grid and just explore all possible paths from those chests. Why? Because in this approach, the treasure chests self mark the cells level by level and the level number will be the distance from that cell to a treasure chest. We don't revisit a cell. This approach is called Multi-Source BFS
. How would you implement it?
+
+
+
+
+
+ Hint 3
+
+ We insert all the cells (row, col)
that represent the treasure chests into the queue. Then, we process the cells level by level, handling all the current cells in the queue at once. For each cell, we mark it as visited and store the current level value as the distance at that cell. We then try to add the neighboring cells (adjacent cells) to the queue, but only if they have not been visited and are land cells.
+
+
\ No newline at end of file
diff --git a/hints/max-area-of-island.md b/hints/max-area-of-island.md
new file mode 100644
index 000000000..a8502e52a
--- /dev/null
+++ b/hints/max-area-of-island.md
@@ -0,0 +1,31 @@
+
+
+ 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 grid.
+
+
+
+
+
+ Hint 1
+
+ An island is a group of 1
's in which every 1
is reachable from any other 1
in that group. Can you think of an algorithm that can find the number of groups by visiting a group only once? Maybe there is a recursive way of doing it.
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to traverse each group by starting at a cell with 1
and recursively visiting all the cells that are reachable from that cell and are also 1
. Can you think about how to find the area of that island? How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We traverse the grid, and when we encounter a 1
, we initialize a variable area
. We then start a DFS from that cell to visit all connected 1
's recursively, marking them as 0
to indicate they are visited. At each recursion step, we increment area
. After completing the DFS, we update maxArea
, which tracks the maximum area of an island in the grid, if maxArea < area
. Finally, after traversing the grid, we return maxArea
.
+
+
\ No newline at end of file
diff --git a/hints/pacific-atlantic-water-flow.md b/hints/pacific-atlantic-water-flow.md
new file mode 100644
index 000000000..6ed584779
--- /dev/null
+++ b/hints/pacific-atlantic-water-flow.md
@@ -0,0 +1,31 @@
+
+
+ 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 grid.
+
+
+
+
+
+ Hint 1
+
+ A brute force solution would be to traverse each cell in the grid and run a BFS from each cell to check if it can reach both oceans. This would result in an O((m * n)^2)
solution. Can you think of a better way? Maybe you should consider a reverse way of traversing.
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm starting from the border cells of the grid. However, we reverse the condition such that the next visiting cell should have a height greater than or equal to the current cell. For the top and left borders connected to the Pacific Ocean, we use a hash set called pacific
and run a DFS from each of these cells, visiting nodes recursively. Similarly, for the bottom and right borders connected to the Atlantic Ocean, we use a hash set called atlantic
and run a DFS. The required coordinates are the cells that exist in both the pacific
and atlantic
sets. How do you implement this?
+
+
+
+
+
+ Hint 3
+
+ We perform DFS from the border cells, using their respective hash sets. During the DFS, we recursively visit the neighbouring cells that are unvisited and have height greater than or equal to the current cell's height and add the current cell's coordinates to the corresponding hash set. Once the DFS completes, we traverse the grid and check if a cell exists in both the hash sets. If so, we add that cell to the result list.
+
+
\ No newline at end of file
diff --git a/hints/rotting-fruit.md b/hints/rotting-fruit.md
new file mode 100644
index 000000000..76ce34b5b
--- /dev/null
+++ b/hints/rotting-fruit.md
@@ -0,0 +1,31 @@
+
+
+ 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 grid.
+
+
+
+
+
+ Hint 1
+
+ The DFS algorithm is not suitable for this problem because it explores nodes deeply rather than level by level. In this scenario, we need to determine which oranges rot at each second, which naturally fits a level-by-level traversal. Can you think of an algorithm designed for such a traversal?
+
+
+
+
+
+ Hint 2
+
+ We can use the Breadth First Search (BFS) algorithm. At each second, we rot the oranges that are adjacent to the rotten ones. So, we store the rotten oranges in a queue and process them in one go. The time at which a fresh orange gets rotten is the level at which it is visited. How would you implement it?
+
+
+
+
+
+ Hint 3
+
+ We traverse the grid and store the rotten oranges in a queue. We then run a BFS, processing the current level of rotten oranges and visiting the adjacent cells of each rotten orange. We only insert the adjacent cell into the queue if it contains a fresh orange. This process continues until the queue is empty. The level at which the BFS stops is the answer. However, we also need to check whether all oranges have rotted by traversing the grid. If any fresh orange is found, we return -1
; otherwise, we return the level.
+
+
\ No newline at end of file
diff --git a/hints/surrounded-regions.md b/hints/surrounded-regions.md
new file mode 100644
index 000000000..d61a1db78
--- /dev/null
+++ b/hints/surrounded-regions.md
@@ -0,0 +1,31 @@
+
+
+ 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 matrix.
+
+
+
+
+
+ Hint 1
+
+ We observe that we need to capture the regions that are not connected to the O
's on the border of the matrix. This means there should be no path connecting the O
's on the border to any O
's in the region. Can you think of a way to check the region connected to these border O
's?
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS
) algorithm. Instead of checking the region connected to the border O
's, we can reverse the approach and mark the regions that are reachable from the border O
's. How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We run the DFS from every 'O'
on the border of the matrix, visiting the neighboring cells that are equal to 'O'
recursively and marking them as '#'
to avoid revisiting. After completing all the DFS calls, we traverse the matrix again and capture the cells where matrix[i][j] == 'O'
, and unmark the cells back to 'O'
where matrix[i][j] == '#'
.
+
+
\ No newline at end of file
From dd8c1d1e9b01005522bc076e6344bc843dbf586c Mon Sep 17 00:00:00 2001
From: rey
Date: Fri, 29 Nov 2024 03:06:50 -0800
Subject: [PATCH 25/67] clarify log for 2d search (#3755)
---
articles/search-2d-matrix.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/articles/search-2d-matrix.md b/articles/search-2d-matrix.md
index 21be9f5e9..722cbe2b6 100644
--- a/articles/search-2d-matrix.md
+++ b/articles/search-2d-matrix.md
@@ -550,7 +550,7 @@ class Solution {
### Time & Space Complexity
-* Time complexity: $O(\log m + \log n)$
+* Time complexity: $O(\log m + \log n)$ (which reduces to $O(\log(m * n))$)
* Space complexity: $O(1)$
> Where $m$ is the number of rows and $n$ is the number of columns of matrix.
From 986f35a352662a0060678bf02c5bd9c2d1b79b69 Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Sat, 30 Nov 2024 13:14:07 +0530
Subject: [PATCH 26/67] Sri Hari: Batch-3/Neetcode-ALL/Added articles (#3751)
* Batch-3/Neetcode-ALL/Added
* Batch-3/Neetcode-All/Added
---
articles/can-place-flowers.md | 178 ++++++
articles/concatenation-of-array.md | 135 +++++
articles/find-pivot-index.md | 284 ++++++++++
articles/is-anagram.md | 4 +-
articles/is-subsequence.md | 513 ++++++++++++++++++
articles/isomorphic-strings.md | 201 +++++++
articles/length-of-last-word.md | 230 ++++++++
articles/longest-common-prefix.md | 503 +++++++++++++++++
articles/majority-element.md | 494 +++++++++++++++++
articles/maximum-number-of-balloons.md | 185 +++++++
articles/next-greater-element-i.md | 334 ++++++++++++
articles/pascals-triangle.md | 260 +++++++++
articles/remove-element.md | 233 ++++++++
...nts-with-greatest-element-on-right-side.md | 154 ++++++
articles/unique-email-addresses.md | 197 +++++++
15 files changed, 3903 insertions(+), 2 deletions(-)
create mode 100644 articles/can-place-flowers.md
create mode 100644 articles/concatenation-of-array.md
create mode 100644 articles/find-pivot-index.md
create mode 100644 articles/is-subsequence.md
create mode 100644 articles/isomorphic-strings.md
create mode 100644 articles/length-of-last-word.md
create mode 100644 articles/longest-common-prefix.md
create mode 100644 articles/majority-element.md
create mode 100644 articles/maximum-number-of-balloons.md
create mode 100644 articles/next-greater-element-i.md
create mode 100644 articles/pascals-triangle.md
create mode 100644 articles/remove-element.md
create mode 100644 articles/replace-elements-with-greatest-element-on-right-side.md
create mode 100644 articles/unique-email-addresses.md
diff --git a/articles/can-place-flowers.md b/articles/can-place-flowers.md
new file mode 100644
index 000000000..7ccaeba96
--- /dev/null
+++ b/articles/can-place-flowers.md
@@ -0,0 +1,178 @@
+## 1. Iteration - I
+
+::tabs-start
+
+```python
+class Solution:
+ def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
+ f = [0] + flowerbed + [0]
+
+ for i in range(1, len(f) - 1):
+ if f[i - 1] == 0 and f[i] == 0 and f[i + 1] == 0:
+ f[i] = 1
+ n -= 1
+
+ return n <= 0
+```
+
+```java
+public class Solution {
+ public boolean canPlaceFlowers(int[] flowerbed, int n) {
+ int[] f = new int[flowerbed.length + 2];
+ for (int i = 0; i < flowerbed.length; i++) {
+ f[i + 1] = flowerbed[i];
+ }
+
+ for (int i = 1; i < f.length - 1; i++) {
+ if (f[i - 1] == 0 && f[i] == 0 && f[i + 1] == 0) {
+ f[i] = 1;
+ n--;
+ }
+ }
+ return n <= 0;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool canPlaceFlowers(vector& flowerbed, int n) {
+ vector f(flowerbed.size() + 2, 0);
+ for (int i = 0; i < flowerbed.size(); i++) {
+ f[i + 1] = flowerbed[i];
+ }
+
+ for (int i = 1; i < f.size() - 1; i++) {
+ if (f[i - 1] == 0 && f[i] == 0 && f[i + 1] == 0) {
+ f[i] = 1;
+ n--;
+ }
+ }
+ return n <= 0;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} flowerbed
+ * @param {number} n
+ * @return {boolean}
+ */
+ canPlaceFlowers(flowerbed, n) {
+ const f = [0, ...flowerbed, 0];
+
+ for (let i = 1; i < f.length - 1; i++) {
+ if (f[i - 1] === 0 && f[i] === 0 && f[i + 1] === 0) {
+ f[i] = 1;
+ n--;
+ }
+ }
+ return n <= 0;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 2. Iteration - II
+
+::tabs-start
+
+```python
+class Solution:
+ def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
+ empty = 0 if flowerbed[0] else 1
+
+ for f in flowerbed:
+ if f:
+ n -= int((empty - 1) / 2)
+ empty = 0
+ else:
+ empty += 1
+
+ n -= empty // 2
+ return n <= 0
+```
+
+```java
+public class Solution {
+ public boolean canPlaceFlowers(int[] flowerbed, int n) {
+ int empty = flowerbed[0] == 0 ? 1 : 0;
+
+ for (int f : flowerbed) {
+ if (f == 1) {
+ n -= (empty - 1) / 2;
+ empty = 0;
+ } else {
+ empty++;
+ }
+ }
+
+ n -= empty / 2;
+ return n <= 0;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool canPlaceFlowers(vector& flowerbed, int n) {
+ int empty = flowerbed[0] == 0 ? 1 : 0;
+
+ for (int f : flowerbed) {
+ if (f == 1) {
+ n -= (empty - 1) / 2;
+ empty = 0;
+ } else {
+ empty++;
+ }
+ }
+
+ n -= empty / 2;
+ return n <= 0;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} flowerbed
+ * @param {number} n
+ * @return {boolean}
+ */
+ canPlaceFlowers(flowerbed, n) {
+ let empty = flowerbed[0] === 0 ? 1 : 0;
+
+ for (let f of flowerbed) {
+ if (f === 1) {
+ n -= Math.floor(Math.max(0, empty - 1) / 2);
+ empty = 0;
+ } else {
+ empty++;
+ }
+ }
+
+ n -= Math.floor(empty / 2);
+ return n <= 0;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
\ No newline at end of file
diff --git a/articles/concatenation-of-array.md b/articles/concatenation-of-array.md
new file mode 100644
index 000000000..24e788da2
--- /dev/null
+++ b/articles/concatenation-of-array.md
@@ -0,0 +1,135 @@
+## 1. Iteration (Two Pass)
+
+::tabs-start
+
+```python
+class Solution:
+ def getConcatenation(self, nums: List[int]) -> List[int]:
+ ans = []
+ for i in range(2):
+ for num in nums:
+ ans.append(num)
+ return ans
+```
+
+```java
+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++) {
+ for (int num : nums) {
+ ans[idx++] = num;
+ }
+ }
+ return ans;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector getConcatenation(vector& nums) {
+ vector ans;
+ for (int i = 0; i < 2; ++i) {
+ for (int num : nums) {
+ ans.push_back(num);
+ }
+ }
+ return ans;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+ getConcatenation(nums) {
+ let ans = [];
+ for (let i = 0; i < 2; i++) {
+ for (let num of nums) {
+ ans.push(num);
+ }
+ }
+ return ans;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
+
+---
+
+## 2. Iteration (One Pass)
+
+::tabs-start
+
+```python
+class Solution:
+ def getConcatenation(self, nums: List[int]) -> List[int]:
+ n = len(nums)
+ ans = [0] * (2 * n)
+ for i, num in enumerate(nums):
+ ans[i] = ans[i + n] = num
+ return ans
+```
+
+```java
+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;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector getConcatenation(vector& nums) {
+ int n = nums.size();
+ vector ans(2 * n);
+ for (int i = 0; i < n; ++i) {
+ ans[i] = ans[i + n] = nums[i];
+ }
+ return ans;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+ getConcatenation(nums) {
+ let n = nums.length;
+ let ans = new Array(2 * n);
+ for (let i = 0; i < n; i++) {
+ ans[i] = ans[i + n] = nums[i];
+ }
+ return ans;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
\ No newline at end of file
diff --git a/articles/find-pivot-index.md b/articles/find-pivot-index.md
new file mode 100644
index 000000000..7e8568d02
--- /dev/null
+++ b/articles/find-pivot-index.md
@@ -0,0 +1,284 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def pivotIndex(self, nums: List[int]) -> int:
+ n = len(nums)
+ for i in range(n):
+ leftSum = rightSum = 0
+ for l in range(i):
+ leftSum += nums[l]
+ for r in range(i + 1, n):
+ rightSum += nums[r]
+ if leftSum == rightSum:
+ return i
+ return -1
+```
+
+```java
+public class Solution {
+ public int pivotIndex(int[] nums) {
+ int n = nums.length;
+ for (int i = 0; i < n; i++) {
+ int leftSum = 0, rightSum = 0;
+ for (int l = 0; l < i; l++) {
+ leftSum += nums[l];
+ }
+ for (int r = i + 1; r < n; r++) {
+ rightSum += nums[r];
+ }
+ if (leftSum == rightSum) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int pivotIndex(vector& nums) {
+ int n = nums.size();
+ for (int i = 0; i < n; i++) {
+ int leftSum = 0, rightSum = 0;
+ for (int l = 0; l < i; l++) {
+ leftSum += nums[l];
+ }
+ for (int r = i + 1; r < n; r++) {
+ rightSum += nums[r];
+ }
+ if (leftSum == rightSum) {
+ return i;
+ }
+ }
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ pivotIndex(nums) {
+ const n = nums.length;
+ for (let i = 0; i < n; i++) {
+ let leftSum = 0, rightSum = 0;
+ for (let l = 0; l < i; l++) {
+ leftSum += nums[l];
+ }
+ for (let r = i + 1; r < n; r++) {
+ rightSum += nums[r];
+ }
+ if (leftSum === rightSum) {
+ return i;
+ }
+ }
+ 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 pivotIndex(self, nums: List[int]) -> int:
+ n = len(nums)
+ prefixSum = [0] * (n + 1)
+ for i in range(n):
+ prefixSum[i + 1] = prefixSum[i] + nums[i]
+
+ for i in range(n):
+ leftSum = prefixSum[i]
+ rightSum = prefixSum[n] - prefixSum[i + 1]
+ if leftSum == rightSum:
+ return i
+ return -1
+```
+
+```java
+public class Solution {
+ public int pivotIndex(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];
+ }
+
+ for (int i = 0; i < n; i++) {
+ int leftSum = prefixSum[i];
+ int rightSum = prefixSum[n] - prefixSum[i + 1];
+ if (leftSum == rightSum) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int pivotIndex(vector& nums) {
+ int n = nums.size();
+ vector prefixSum(n + 1, 0);
+ for (int i = 0; i < n; i++) {
+ prefixSum[i + 1] = prefixSum[i] + nums[i];
+ }
+
+ for (int i = 0; i < n; i++) {
+ int leftSum = prefixSum[i];
+ int rightSum = prefixSum[n] - prefixSum[i + 1];
+ if (leftSum == rightSum) {
+ return i;
+ }
+ }
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ pivotIndex(nums) {
+ const n = nums.length;
+ const prefixSum = new Array(n + 1).fill(0);
+ for (let i = 0; i < n; i++) {
+ prefixSum[i + 1] = prefixSum[i] + nums[i];
+ }
+
+ for (let i = 0; i < n; i++) {
+ const leftSum = prefixSum[i];
+ const rightSum = prefixSum[n] - prefixSum[i + 1];
+ if (leftSum === rightSum) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 3. Prefix Sum (Optimal)
+
+::tabs-start
+
+```python
+class Solution:
+ def pivotIndex(self, nums: List[int]) -> int:
+ total = sum(nums)
+ leftSum = 0
+ for i in range(len(nums)):
+ rightSum = total - nums[i] - leftSum
+ if leftSum == rightSum:
+ return i
+ leftSum += nums[i]
+ return -1
+```
+
+```java
+public class Solution {
+ public int pivotIndex(int[] nums) {
+ int total = 0;
+ for (int num : nums) {
+ total += num;
+ }
+
+ int leftSum = 0;
+ for (int i = 0; i < nums.length; i++) {
+ int rightSum = total - leftSum - nums[i];
+ if (leftSum == rightSum) {
+ return i;
+ }
+ leftSum += nums[i];
+ }
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int pivotIndex(vector& nums) {
+ int total = 0;
+ for (int num : nums) {
+ total += num;
+ }
+
+ int leftSum = 0;
+ for (int i = 0; i < nums.size(); i++) {
+ int rightSum = total - leftSum - nums[i];
+ if (leftSum == rightSum) {
+ return i;
+ }
+ leftSum += nums[i];
+ }
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ pivotIndex(nums) {
+ let total = 0;
+ for (let num of nums) {
+ total += num;
+ }
+
+ let leftSum = 0;
+ for (let i = 0; i < nums.length; i++) {
+ let rightSum = total - leftSum - nums[i];
+ if (leftSum === rightSum) {
+ return i;
+ }
+ leftSum += nums[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/is-anagram.md b/articles/is-anagram.md
index 45f2dd7d4..ae3a44534 100644
--- a/articles/is-anagram.md
+++ b/articles/is-anagram.md
@@ -271,7 +271,7 @@ class Solution {
### Time & Space Complexity
* Time complexity: $O(n + m)$
-* Space complexity: $O(1)$ since we have at most 26 different characters.
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
> Where $n$ is the length of string $s$ and $m$ is the length of string $t$.
@@ -439,6 +439,6 @@ class Solution {
### Time & Space Complexity
* Time complexity: $O(n + m)$
-* Space complexity: $O(1)$ since we have at most 26 different characters.
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
> Where $n$ is the length of string $s$ and $m$ is the length of string $t$.
diff --git a/articles/is-subsequence.md b/articles/is-subsequence.md
new file mode 100644
index 000000000..fde7628a6
--- /dev/null
+++ b/articles/is-subsequence.md
@@ -0,0 +1,513 @@
+## 1. Recursion
+
+::tabs-start
+
+```python
+class Solution:
+ def isSubsequence(self, s: str, t: str) -> bool:
+ def rec(i, j):
+ if i == len(s):
+ return True
+ if j == len(t):
+ return False
+
+ if s[i] == t[j]:
+ return rec(i + 1, j + 1)
+ return rec(i, j + 1)
+ return rec(0, 0)
+```
+
+```java
+public class Solution {
+ public boolean isSubsequence(String s, String t) {
+ return rec(s, t, 0, 0);
+ }
+
+ private boolean rec(String s, String t, int i, int j) {
+ if (i == s.length()) return true;
+ if (j == t.length()) return false;
+ if (s.charAt(i) == t.charAt(j)) {
+ return rec(s, t, i + 1, j + 1);
+ }
+ return rec(s, t, i, j + 1);
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool isSubsequence(string s, string t) {
+ return rec(s, t, 0, 0);
+ }
+
+private:
+ bool rec(string& s, string& t, int i, int j) {
+ if (i == s.size()) return true;
+ if (j == t.size()) return false;
+ if (s[i] == t[j]) {
+ return rec(s, t, i + 1, j + 1);
+ }
+ return rec(s, t, i, j + 1);
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+ isSubsequence(s, t) {
+ const rec = (i, j) => {
+ if (i === s.length) return true;
+ if (j === t.length) return false;
+ if (s[i] === t[j]) return rec(i + 1, j + 1);
+ return rec(i, j + 1);
+ };
+ return rec(0, 0);
+ }
+}
+```
+
+::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 length of the string $t$.
+
+---
+
+## 2. Dynamic Programming (Top-Down)
+
+::tabs-start
+
+```python
+class Solution:
+ def isSubsequence(self, s: str, t: str) -> bool:
+ n, m = len(s), len(t)
+ memo = [[-1] * m for _ in range(n)]
+
+ def rec(i, j):
+ if i == n:
+ return True
+ if j == m:
+ return False
+ if memo[i][j] != -1:
+ return memo[i][j] == 1
+ if s[i] == t[j]:
+ memo[i][j] = 1 if rec(i + 1, j + 1) else 0
+ else:
+ memo[i][j] = 1 if rec(i, j + 1) else 0
+ return memo[i][j] == 1
+
+ return rec(0, 0)
+```
+
+```java
+public class Solution {
+ public boolean isSubsequence(String s, String t) {
+ int n = s.length(), m = t.length();
+ int[][] memo = new int[n][m];
+ for (int[] row : memo) {
+ Arrays.fill(row, -1);
+ }
+ return rec(s, t, 0, 0, memo);
+ }
+
+ private boolean rec(String s, String t, int i, int j, int[][] memo) {
+ if (i == s.length()) return true;
+ if (j == t.length()) return false;
+ if (memo[i][j] != -1) return memo[i][j] == 1;
+ if (s.charAt(i) == t.charAt(j)) {
+ memo[i][j] = rec(s, t, i + 1, j + 1, memo) ? 1 : 0;
+ } else {
+ memo[i][j] = rec(s, t, i, j + 1, memo) ? 1 : 0;
+ }
+ return memo[i][j] == 1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool isSubsequence(string s, string t) {
+ int n = s.size(), m = t.size();
+ vector> memo(n, vector(m, -1));
+ return rec(s, t, 0, 0, memo);
+ }
+
+private:
+ bool rec(string& s, string& t, int i, int j, vector>& memo) {
+ if (i == s.size()) return true;
+ if (j == t.size()) return false;
+ if (memo[i][j] != -1) return memo[i][j] == 1;
+ if (s[i] == t[j]) {
+ memo[i][j] = rec(s, t, i + 1, j + 1, memo) ? 1 : 0;
+ } else {
+ memo[i][j] = rec(s, t, i, j + 1, memo) ? 1 : 0;
+ }
+ return memo[i][j] == 1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+ isSubsequence(s, t) {
+ const n = s.length, m = t.length;
+ const memo = Array.from({ length: n }, () => Array(m).fill(-1));
+
+ const rec = (i, j) => {
+ if (i === n) return true;
+ if (j === m) return false;
+ if (memo[i][j] !== -1) return memo[i][j] === 1;
+ if (s[i] === t[j]) {
+ memo[i][j] = rec(i + 1, j + 1) ? 1 : 0;
+ } else {
+ memo[i][j] = rec(i, j + 1) ? 1 : 0;
+ }
+ return memo[i][j] === 1;
+ };
+
+ return rec(0, 0);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m)$
+* Space complexity: $O(n * m)$
+
+> Where $n$ is the length of the string $s$ and $m$ is the length of the string $t$.
+
+---
+
+## 3. Dynamic Programming (Bottom-Up)
+
+::tabs-start
+
+```python
+class Solution:
+ def isSubsequence(self, s: str, t: str) -> bool:
+ n, m = len(s), len(t)
+ dp = [[False] * (m + 1) for _ in range(n + 1)]
+
+ for j in range(m + 1):
+ dp[n][j] = True
+
+ for i in range(n - 1, -1, -1):
+ for j in range(m - 1, -1, -1):
+ if s[i] == t[j]:
+ dp[i][j] = dp[i + 1][j + 1]
+ else:
+ dp[i][j] = dp[i][j + 1]
+
+ return dp[0][0]
+```
+
+```java
+public class Solution {
+ public boolean isSubsequence(String s, String t) {
+ int n = s.length(), m = t.length();
+ boolean[][] dp = new boolean[n + 1][m + 1];
+
+ for (int j = 0; j <= m; j++) {
+ dp[n][j] = true;
+ }
+
+ for (int i = n - 1; i >= 0; i--) {
+ for (int j = m - 1; j >= 0; j--) {
+ if (s.charAt(i) == t.charAt(j)) {
+ dp[i][j] = dp[i + 1][j + 1];
+ } else {
+ dp[i][j] = dp[i][j + 1];
+ }
+ }
+ }
+
+ return dp[0][0];
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool isSubsequence(string s, string t) {
+ int n = s.size(), m = t.size();
+ vector> dp(n + 1, vector(m + 1, false));
+
+ for (int j = 0; j <= m; ++j) {
+ dp[n][j] = true;
+ }
+
+ for (int i = n - 1; i >= 0; --i) {
+ for (int j = m - 1; j >= 0; --j) {
+ if (s[i] == t[j]) {
+ dp[i][j] = dp[i + 1][j + 1];
+ } else {
+ dp[i][j] = dp[i][j + 1];
+ }
+ }
+ }
+
+ return dp[0][0];
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+ isSubsequence(s, t) {
+ const n = s.length, m = t.length;
+ const dp = Array.from({ length: n + 1 }, () => Array(m + 1).fill(false));
+
+ for (let j = 0; j <= m; j++) {
+ dp[n][j] = true;
+ }
+
+ for (let i = n - 1; i >= 0; i--) {
+ for (let j = m - 1; j >= 0; j--) {
+ if (s[i] === t[j]) {
+ dp[i][j] = dp[i + 1][j + 1];
+ } else {
+ dp[i][j] = dp[i][j + 1];
+ }
+ }
+ }
+
+ return dp[0][0];
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m)$
+* Space complexity: $O(n * m)$
+
+> Where $n$ is the length of the string $s$ and $m$ is the length of the string $t$.
+
+---
+
+## 4. Two Pointers
+
+::tabs-start
+
+```python
+class Solution:
+ def isSubsequence(self, s: str, t: str) -> bool:
+ i = j = 0
+ while i < len(s) and j < len(t):
+ if s[i] == t[j]:
+ i += 1
+ j += 1
+ return i == len(s)
+```
+
+```java
+public class Solution {
+ public boolean isSubsequence(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++;
+ }
+ return i == s.length();
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool isSubsequence(string s, string t) {
+ int i = 0, j = 0;
+ while (i < s.length() && j < t.length()) {
+ if (s[i] == t[j]) {
+ i++;
+ }
+ j++;
+ }
+ return i == s.length();
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+ isSubsequence(s, t) {
+ let i = 0, j = 0;
+ while (i < s.length && j < t.length) {
+ if (s.charAt(i) == t.charAt(j)) {
+ i++;
+ }
+ j++;
+ }
+ return i == s.length;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(1)$
+
+> Where $n$ is the length of the string $s$ and $m$ is the length of the string $t$.
+
+## 5. Follow-Up Solution (Index Jumping)
+
+::tabs-start
+
+```python
+class Solution:
+ def isSubsequence(self, s: str, t: str) -> bool:
+ n, m = len(s), len(t)
+ if m == 0:
+ return n == 0
+
+ store = [[m + 1] * 26 for _ in range(m)]
+ store[m - 1][ord(t[m - 1]) - ord('a')] = m - 1
+
+ for i in range(m - 2, -1, -1):
+ store[i] = store[i + 1][:]
+ store[i][ord(t[i]) - ord('a')] = i
+
+ i, j = 0, 0
+ while i < n and j < m:
+ j = store[j][ord(s[i]) - ord('a')] + 1
+ if j > m:
+ return False
+ i += 1
+
+ return i == n
+```
+
+```java
+public class Solution {
+ public boolean isSubsequence(String s, String t) {
+ int n = s.length(), m = t.length();
+ if (m == 0) return n == 0;
+
+ int[][] store = new int[m][26];
+ for (int i = 0; i < m; i++) {
+ Arrays.fill(store[i], m + 1);
+ }
+
+ store[m - 1][t.charAt(m - 1) - 'a'] = m - 1;
+
+ for (int i = m - 2; i >= 0; i--) {
+ store[i] = store[i + 1].clone();
+ store[i][t.charAt(i) - 'a'] = i;
+ }
+
+ int i = 0, j = 0;
+ while (i < n && j < m) {
+ j = store[j][s.charAt(i) - 'a'] + 1;
+ if (j > m) return false;
+ i++;
+ }
+
+ return i == n;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool isSubsequence(string s, string t) {
+ int n = s.length(), m = t.length();
+ if (m == 0) return n == 0;
+
+ vector> store(m, vector(26, m + 1));
+ store[m - 1][t[m - 1] - 'a'] = m - 1;
+
+ for (int i = m - 2; i >= 0; i--) {
+ store[i] = store[i + 1];
+ store[i][t[i] - 'a'] = i;
+ }
+
+ int i = 0, j = 0;
+ while (i < n && j < m) {
+ j = store[j][s[i] - 'a'] + 1;
+ if (j > m) return false;
+ i++;
+ }
+
+ return i == n;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+ isSubsequence(s, t) {
+ const n = s.length, m = t.length;
+ if (m === 0) return n === 0;
+
+ const store = Array.from({ length: m }, () => Array(26).fill(m + 1));
+ store[m - 1][t.charCodeAt(m - 1) - 'a'.charCodeAt(0)] = m - 1;
+
+ for (let i = m - 2; i >= 0; i--) {
+ store[i] = [...store[i + 1]];
+ store[i][t.charCodeAt(i) - 'a'.charCodeAt(0)] = i;
+ }
+
+ let i = 0, j = 0;
+ while (i < n && j < m) {
+ j = store[j][s.charCodeAt(i) - 'a'.charCodeAt(0)] + 1;
+ if (j > m) return false;
+ i++;
+ }
+
+ return i === n;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(m)$
+
+> Where $n$ is the length of the string $s$ and $m$ is the length of the string $t$.
\ No newline at end of file
diff --git a/articles/isomorphic-strings.md b/articles/isomorphic-strings.md
new file mode 100644
index 000000000..afbaa6c10
--- /dev/null
+++ b/articles/isomorphic-strings.md
@@ -0,0 +1,201 @@
+## 1. Hash Map (Two Pass)
+
+::tabs-start
+
+```python
+class Solution:
+ def helper(self, s: str, t: str) -> bool:
+ mp = {}
+ for i in range(len(s)):
+ if (s[i] in mp) and (mp[s[i]] != t[i]):
+ return False
+ mp[s[i]] = t[i]
+ return True
+
+ def isIsomorphic(self, s: str, t: str) -> bool:
+ return self.helper(s, t) and self.helper(t, s)
+```
+
+```java
+public class Solution {
+ private boolean helper(String s, String t) {
+ HashMap map = new HashMap<>();
+ for (int i = 0; i < s.length(); i++) {
+ char sc = s.charAt(i);
+ char tc = t.charAt(i);
+ if (map.containsKey(sc) && map.get(sc) != tc) {
+ return false;
+ }
+ map.put(sc, tc);
+ }
+ return true;
+ }
+
+ public boolean isIsomorphic(String s, String t) {
+ return helper(s, t) && helper(t, s);
+ }
+}
+```
+
+```cpp
+class Solution {
+private:
+ bool helper(const string& s, const string& t) {
+ unordered_map map;
+ for (int i = 0; i < s.length(); i++) {
+ if (map.count(s[i]) && map[s[i]] != t[i]) {
+ return false;
+ }
+ map[s[i]] = t[i];
+ }
+ return true;
+ }
+
+public:
+ bool isIsomorphic(string s, string t) {
+ return helper(s, t) && helper(t, s);
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+ helper(s, t) {
+ const map = new Map();
+ for (let i = 0; i < s.length; i++) {
+ if (map.has(s[i]) && map.get(s[i]) !== t[i]) {
+ return false;
+ }
+ map.set(s[i], t[i]);
+ }
+ return true;
+ }
+
+ /**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+ isIsomorphic(s, t) {
+ return this.helper(s, t) && this.helper(t, s);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(m)$
+
+> Where $n$ is the length of the input string and $m$ is the number of unique characters in the strings.
+
+---
+
+## 2. Hash Map (One Pass)
+
+::tabs-start
+
+```python
+class Solution:
+ def isIsomorphic(self, s: str, t: str) -> bool:
+ mapST, mapTS = {}, {}
+
+ for i in range(len(s)):
+ c1, c2 = s[i], t[i]
+ if ((c1 in mapST and mapST[c1] != c2) or
+ (c2 in mapTS and mapTS[c2] != c1)):
+ return False
+ mapST[c1] = c2
+ mapTS[c2] = c1
+
+ return True
+```
+
+```java
+public class Solution {
+ public boolean isIsomorphic(String s, String t) {
+ HashMap mapST = new HashMap<>();
+ HashMap mapTS = new HashMap<>();
+
+ for (int i = 0; i < s.length(); i++) {
+ char c1 = s.charAt(i), c2 = t.charAt(i);
+
+ if ((mapST.containsKey(c1) && mapST.get(c1) != c2) ||
+ (mapTS.containsKey(c2) && mapTS.get(c2) != c1)) {
+ return false;
+ }
+
+ mapST.put(c1, c2);
+ mapTS.put(c2, c1);
+ }
+
+ return true;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool isIsomorphic(string s, string t) {
+ unordered_map mapST, mapTS;
+
+ for (int i = 0; i < s.size(); i++) {
+ char c1 = s[i], c2 = t[i];
+
+ if ((mapST.count(c1) && mapST[c1] != c2) ||
+ (mapTS.count(c2) && mapTS[c2] != c1)) {
+ return false;
+ }
+
+ mapST[c1] = c2;
+ mapTS[c2] = c1;
+ }
+
+ return true;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+ isIsomorphic(s, t) {
+ const mapTS = new Map();
+
+ for (let i = 0; i < s.length; i++) {
+ const c1 = s[i], c2 = t[i];
+
+ if ((mapST.has(c1) && mapST.get(c1) !== c2) ||
+ (mapTS.has(c2) && mapTS.get(c2) !== c1)) {
+ return false;
+ }
+
+ mapST.set(c1, c2);
+ mapTS.set(c2, c1);
+ }
+
+ return true;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(m)$
+
+> Where $n$ is the length of the input string and $m$ is the number of unique characters in the strings.
\ No newline at end of file
diff --git a/articles/length-of-last-word.md b/articles/length-of-last-word.md
new file mode 100644
index 000000000..baa94e557
--- /dev/null
+++ b/articles/length-of-last-word.md
@@ -0,0 +1,230 @@
+## 1. Iteration - I
+
+::tabs-start
+
+```python
+class Solution:
+ def lengthOfLastWord(self, s: str) -> int:
+ length = i = 0
+ while i < len(s):
+ if s[i] == ' ':
+ while i < len(s) and s[i] == ' ':
+ i += 1
+ if i == len(s):
+ return length
+ length = 0
+ else:
+ length += 1
+ i += 1
+ return length
+```
+
+```java
+public class Solution {
+ public int lengthOfLastWord(String s) {
+ int length = 0, i = 0;
+ while (i < s.length()) {
+ if (s.charAt(i) == ' ') {
+ while (i < s.length() && s.charAt(i) == ' ') {
+ i++;
+ }
+ if (i == s.length()) {
+ return length;
+ }
+ length = 0;
+ } else {
+ length++;
+ i++;
+ }
+ }
+ return length;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int lengthOfLastWord(string s) {
+ int length = 0, i = 0;
+ while (i < s.length()) {
+ if (s[i] == ' ') {
+ while (i < s.length() && s[i] == ' ') {
+ i++;
+ }
+ if (i == s.length()) {
+ return length;
+ }
+ length = 0;
+ } else {
+ length++;
+ i++;
+ }
+ }
+ return length;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @return {number}
+ */
+ lengthOfLastWord(s) {
+ let length = 0, i = 0;
+ while (i < s.length) {
+ if (s[i] === ' ') {
+ while (i < s.length && s[i] === ' ') {
+ i++;
+ }
+ if (i === s.length) {
+ return length;
+ }
+ length = 0;
+ } else {
+ length++;
+ i++;
+ }
+ }
+ return length;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
+
+---
+
+## 2. Iteration - II
+
+::tabs-start
+
+```python
+class Solution:
+ def lengthOfLastWord(self, s: str) -> int:
+ i, length = len(s) - 1, 0
+ while s[i] == ' ':
+ i -= 1
+ while i >= 0 and s[i] != ' ':
+ i -= 1
+ length += 1
+ return length
+```
+
+```java
+public class Solution {
+ public int lengthOfLastWord(String s) {
+ int n = s.length();
+ int i = n - 1, length = 0;
+ while (s.charAt(i) == ' ') {
+ i--;
+ }
+ while (i >= 0 && s.charAt(i) != ' ') {
+ i--;
+ length++;
+ }
+ return length;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int lengthOfLastWord(string s) {
+ int n = s.length();
+ int i = n - 1, length = 0;
+ while (s[i] == ' ') i--;
+ while (i >= 0 && s[i] != ' ') {
+ i--;
+ length++;
+ }
+ return length;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @return {number}
+ */
+ lengthOfLastWord(s) {
+ let n = s.length;
+ let i = n - 1, length = 0;
+ while (s.charAt(i) === ' ') {
+ i--;
+ }
+ while (i >= 0 && s.charAt(i) !== ' ') {
+ i--;
+ length++;
+ }
+ return length;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
+
+---
+
+## 3. Built-In Function
+
+::tabs-start
+
+```python
+class Solution:
+ def lengthOfLastWord(self, s: str) -> int:
+ return len(s.split().pop())
+```
+
+```java
+public class Solution {
+ public int lengthOfLastWord(String s) {
+ s = s.trim();
+ return s.length() - s.lastIndexOf(" ") - 1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int lengthOfLastWord(string s) {
+ s.erase(s.find_last_not_of(' ') + 1);
+ return s.substr(s.find_last_of(' ') + 1).length();
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @return {number}
+ */
+ lengthOfLastWord(s) {
+ return s.trim().split(' ').pop().length
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
\ No newline at end of file
diff --git a/articles/longest-common-prefix.md b/articles/longest-common-prefix.md
new file mode 100644
index 000000000..c7f5658fb
--- /dev/null
+++ b/articles/longest-common-prefix.md
@@ -0,0 +1,503 @@
+## 1. Iteration - I
+
+::tabs-start
+
+```python
+class Solution:
+ def longestCommonPrefix(self, strs: List[str]) -> str:
+ prefix = strs[0]
+ for i in range(1, len(strs)):
+ j = 0
+ while j < min(len(prefix), len(strs[i])):
+ if prefix[j] != strs[i][j]:
+ break
+ j += 1
+ prefix = prefix[:j]
+ return prefix
+```
+
+```java
+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.charAt(j) != strs[i].charAt(j)) {
+ break;
+ }
+ j++;
+ }
+ prefix = prefix.substring(0, j);
+ }
+ return prefix;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ string longestCommonPrefix(vector& strs) {
+ string prefix = strs[0];
+ for (int i = 1; i < strs.size(); i++) {
+ int j = 0;
+ while (j < min(prefix.length(), strs[i].length())) {
+ if (prefix[j] != strs[i][j]) {
+ break;
+ }
+ j++;
+ }
+ prefix = prefix.substr(0, j);
+ }
+ return prefix;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[]} strs
+ * @return {string}
+ */
+ longestCommonPrefix(strs) {
+ let prefix = strs[0];
+ for (let i = 1; i < strs.length; i++) {
+ let j = 0;
+ while (j < Math.min(prefix.length, strs[i].length)) {
+ if (prefix[j] !== strs[i][j]) {
+ break;
+ }
+ j++;
+ }
+ prefix = prefix.slice(0, j);
+ }
+ return prefix;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* 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.
+
+---
+
+## 2. Iteration - II
+
+::tabs-start
+
+```python
+class Solution:
+ def longestCommonPrefix(self, strs: List[str]) -> str:
+ for i in range(len(strs[0])):
+ for s in strs:
+ if i == len(s) or s[i] != strs[0][i]:
+ return s[:i]
+ return strs[0]
+```
+
+```java
+public class Solution {
+ public String longestCommonPrefix(String[] strs) {
+ for (int i = 0; i < strs[0].length(); i++) {
+ for (String s : strs) {
+ if (i == s.length() || s.charAt(i) != strs[0].charAt(i)) {
+ return s.substring(0, i);
+ }
+ }
+ }
+ return strs[0];
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ string longestCommonPrefix(vector& strs) {
+ for (int i = 0; i < strs[0].length(); i++) {
+ for (const string& s : strs) {
+ if (i == s.length() || s[i] != strs[0][i]) {
+ return s.substr(0, i);
+ }
+ }
+ }
+ return strs[0];
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[]} strs
+ * @return {string}
+ */
+ longestCommonPrefix(strs) {
+ for (let i = 0; i < strs[0].length; i++) {
+ for (let s of strs) {
+ if (i === s.length || s[i] !== strs[0][i]) {
+ return s.slice(0, i);
+ }
+ }
+ }
+ return strs[0];
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m)$
+* Space complexity: $O(1)$ since we did not use extra space.
+
+> Where $n$ is the length of the shortest string and $m$ is the number of strings.
+
+---
+
+## 3. Sorting
+
+::tabs-start
+
+```python
+class Solution:
+ def longestCommonPrefix(self, strs: List[str]) -> str:
+ if len(strs) == 1:
+ return strs[0]
+
+ strs = sorted(strs)
+ for i in range(min(len(strs[0]), len(strs[-1]))):
+ if strs[0][i] != strs[-1][i]:
+ return strs[0][:i]
+ return strs[0]
+```
+
+```java
+public class Solution {
+ public String longestCommonPrefix(String[] strs) {
+ if (strs.length == 1) {
+ return strs[0];
+ }
+
+ Arrays.sort(strs);
+ int N = Math.min(strs[0].length(), strs[strs.length - 1].length());
+ for (int i = 0; i < N; i++) {
+ if (strs[0].charAt(i) != strs[strs.length - 1].charAt(i)) {
+ return strs[0].substring(0, i);
+ }
+ }
+ return strs[0];
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ string longestCommonPrefix(vector& strs) {
+ if (strs.size() == 1) {
+ return strs[0];
+ }
+
+ sort(strs.begin(), strs.end());
+ for (int i = 0; i < min(strs[0].length(), strs.back().length()); i++) {
+ if (strs[0][i] != strs.back()[i]) {
+ return strs[0].substr(0, i);
+ }
+ }
+ return strs[0];
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[]} strs
+ * @return {string}
+ */
+ longestCommonPrefix(strs) {
+ if (strs.length === 1) {
+ return strs[0];
+ }
+
+ strs.sort();
+ let N = Math.min(strs[0].length, strs[strs.length - 1].length);
+ for (let i = 0; i < N; i++) {
+ if (strs[0][i] !== strs[strs.length - 1][i]) {
+ return strs[0].slice(0, i);
+ }
+ }
+ return strs[0];
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m \log m)$
+* Space complexity: $O(1)$ or $O(m)$ depending on the sorting algorithm.
+
+> Where $n$ is the length of the longest string and $m$ is the number of strings.
+
+---
+
+## 4. Trie
+
+::tabs-start
+
+```python
+class TrieNode:
+ def __init__(self):
+ self.children = {}
+
+class Trie:
+ def __init__(self):
+ self.root = TrieNode()
+
+ def insert(self, word: str) -> None:
+ node = self.root
+ for char in word:
+ if char not in node.children:
+ node.children[char] = TrieNode()
+ node = node.children[char]
+
+ def lcp(self, word: str, prefixLen: int) -> int:
+ node = self.root
+ for i in range(min(len(word), prefixLen)):
+ if word[i] not in node.children:
+ return i
+ node = node.children[word[i]]
+ return min(len(word), prefixLen)
+
+class Solution:
+ def longestCommonPrefix(self, strs: list[str]) -> str:
+ if len(strs) == 1:
+ return strs[0]
+
+ mini = 0
+ for i in range(1, len(strs)):
+ if len(strs[mini]) > len(strs[i]):
+ mini = i
+
+ trie = Trie()
+ trie.insert(strs[mini])
+ prefixLen = len(strs[mini])
+ for i in range(len(strs)):
+ prefixLen = trie.lcp(strs[i], prefixLen)
+ return strs[0][:prefixLen]
+```
+
+```java
+class TrieNode {
+ Map children = new HashMap<>();
+}
+
+class Trie {
+ TrieNode root = new TrieNode();
+
+ void insert(String word) {
+ TrieNode node = root;
+ for (char c : word.toCharArray()) {
+ node.children.putIfAbsent(c, new TrieNode());
+ node = node.children.get(c);
+ }
+ }
+
+ int lcp(String word, int prefixLen) {
+ TrieNode node = root;
+ int i = 0;
+ while (i < Math.min(word.length(), prefixLen)) {
+ if (!node.children.containsKey(word.charAt(i))) {
+ return i;
+ }
+ node = node.children.get(word.charAt(i));
+ 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[mini].length() > strs[i].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);
+ }
+}
+```
+
+```cpp
+class TrieNode {
+public:
+ unordered_map children;
+};
+
+class Trie {
+public:
+ TrieNode* root;
+ Trie() {
+ root = new TrieNode();
+ }
+
+ void insert(const string& word) {
+ TrieNode* node = root;
+ for (char c : word) {
+ if (node->children.find(c) == node->children.end()) {
+ node->children[c] = new TrieNode();
+ }
+ node = node->children[c];
+ }
+ }
+
+ int lcp(const string& word, int prefixLen) {
+ TrieNode* node = root;
+ int i = 0;
+ while (i < min((int)word.length(), prefixLen)) {
+ if (node->children.find(word[i]) == node->children.end()) {
+ return i;
+ }
+ node = node->children[word[i]];
+ i++;
+ }
+ return min((int)word.length(), prefixLen);
+ }
+};
+
+class Solution {
+public:
+ string longestCommonPrefix(vector& strs) {
+ if (strs.size() == 1) {
+ return strs[0];
+ }
+ int mini = 0;
+ for (int i = 1; i < strs.size(); i++) {
+ if (strs[mini].size() > strs[i].size()) {
+ mini = i;
+ }
+ }
+
+ Trie trie;
+ trie.insert(strs[mini]);
+ int prefixLen = strs[mini].length();
+
+ for (int i = 0; i < strs.size(); i++) {
+ prefixLen = trie.lcp(strs[i], prefixLen);
+ }
+
+ return strs[0].substr(0, prefixLen);
+ }
+};
+```
+
+```javascript
+class TrieNode {
+ constructor() {
+ this.children = {};
+ }
+}
+
+class Trie {
+ constructor() {
+ this.root = new TrieNode();
+ }
+
+ /**
+ * @param {string} word
+ * @return {void}
+ */
+ insert(word) {
+ let node = this.root;
+ for (let char of word) {
+ if (!node.children[char]) {
+ node.children[char] = new TrieNode();
+ }
+ node = node.children[char];
+ }
+ }
+
+ /**
+ * @param {string} word
+ * @param {number} prefixLen
+ * @return {number}
+ */
+ lcp(word, prefixLen) {
+ let node = this.root;
+ let i = 0;
+ while (i < Math.min(word.length, prefixLen)) {
+ if (!node.children[word[i]]) {
+ return i;
+ }
+ node = node.children[word[i]];
+ i++;
+ }
+ return Math.min(word.length, prefixLen);
+ }
+}
+
+class Solution {
+ /**
+ * @param {string[]} strs
+ * @return {string}
+ */
+ longestCommonPrefix(strs) {
+ if (strs.length === 1) {
+ return strs[0];
+ }
+
+ let mini = 0;
+ for (let i = 1; i < strs.length; i++) {
+ if (strs[mini].length > strs[i].length) {
+ mini = i;
+ }
+ }
+
+ const trie = new Trie();
+ trie.insert(strs[mini]);
+ let prefixLen = strs[mini].length;
+
+ for (let i = 0; i < strs.length; i++) {
+ prefixLen = trie.lcp(strs[i], prefixLen);
+ }
+
+ return strs[0].substring(0, prefixLen);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* 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.
\ No newline at end of file
diff --git a/articles/majority-element.md b/articles/majority-element.md
new file mode 100644
index 000000000..9ac32df2c
--- /dev/null
+++ b/articles/majority-element.md
@@ -0,0 +1,494 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def majorityElement(self, nums: List[int]) -> int:
+ n = len(nums)
+ for num in nums:
+ count = sum(1 for i in nums if i == num)
+ if count > n // 2:
+ return num
+```
+
+```java
+public class Solution {
+ public int majorityElement(int[] nums) {
+ int n = nums.length;
+ for (int num : nums) {
+ int count = 0;
+ for (int i : nums) {
+ if (i == num) {
+ count++;
+ }
+ }
+ if (count > n / 2) {
+ return num;
+ }
+ }
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int majorityElement(vector& nums) {
+ int n = nums.size();
+ for (int num : nums) {
+ int count = 0;
+ for (int i : nums) {
+ if (i == num) {
+ count++;
+ }
+ }
+ if (count > n / 2) {
+ return num;
+ }
+ }
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ majorityElement(nums) {
+ let n = nums.length;
+ for (let num of nums) {
+ let count = nums.reduce((acc, val) => acc + (val === num ? 1 : 0), 0);
+ if (count > Math.floor(n / 2)) {
+ return num;
+ }
+ }
+ return -1;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n ^ 2)$
+* Space complexity: $O(1)$
+
+---
+
+## 2. Hash Map
+
+::tabs-start
+
+```python
+class Solution:
+ def majorityElement(self, nums: List[int]) -> int:
+ count = defaultdict(int)
+ res = maxCount = 0
+
+ for num in nums:
+ count[num] += 1
+ if maxCount < count[num]:
+ res = num
+ maxCount = count[num]
+ return res
+```
+
+```java
+public class Solution {
+ public int majorityElement(int[] nums) {
+ HashMap count = new HashMap<>();
+ int res = 0, maxCount = 0;
+
+ for (int num : nums) {
+ count.put(num, count.getOrDefault(num, 0) + 1);
+ if (count.get(num) > maxCount) {
+ res = num;
+ maxCount = count.get(num);
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int majorityElement(vector& nums) {
+ unordered_map count;
+ int res = 0, maxCount = 0;
+
+ for (int num : nums) {
+ count[num]++;
+ if (count[num] > maxCount) {
+ res = num;
+ maxCount = count[num];
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ majorityElement(nums) {
+ const count = new Map();
+ let res = 0, maxCount = 0;
+
+ for (let num of nums) {
+ count.set(num, (count.get(num) || 0) + 1);
+ if (count.get(num) > maxCount) {
+ res = num;
+ maxCount = count.get(num);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 3. Sorting
+
+::tabs-start
+
+```python
+class Solution:
+ def majorityElement(self, nums: List[int]) -> int:
+ nums.sort()
+ return nums[len(nums) // 2]
+```
+
+```java
+public class Solution {
+ public int majorityElement(int[] nums) {
+ Arrays.sort(nums);
+ return nums[nums.length / 2];
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int majorityElement(vector& nums) {
+ sort(nums.begin(), nums.end());
+ return nums[nums.size() / 2];
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ majorityElement(nums) {
+ nums.sort();
+ return nums[Math.floor(nums.length / 2)];
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n \log n)$
+* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm.
+
+---
+
+## 4. Bit Manipulation
+
+::tabs-start
+
+```python
+class Solution:
+ def majorityElement(self, nums: List[int]) -> int:
+ n = len(nums)
+ bit = [0] * 32
+ for num in nums:
+ for i in range(32):
+ bit[i] += ((num >> i) & 1)
+
+ res = 0
+ for i in range(32):
+ if bit[i] > (n // 2):
+ if i == 31:
+ res -= (1 << i)
+ else:
+ res |= (1 << i)
+ return res
+```
+
+```java
+public class Solution {
+ public int majorityElement(int[] nums) {
+ int n = nums.length;
+ int[] bit = new int[32];
+ for (int num : 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;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int majorityElement(vector& nums) {
+ int n = nums.size();
+ vector bit(32, 0);
+ for (int num : 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;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ majorityElement(nums) {
+ const n = nums.length;
+ const bit = Array(32).fill(0);
+ for (let num of nums) {
+ for (let i = 0; i < 32; i++) {
+ bit[i] += (num >> i) & 1;
+ }
+ }
+
+ let res = 0;
+ for (let i = 0; i < 32; i++) {
+ if (bit[i] > Math.floor(n / 2)) {
+ res |= (1 << i);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * 32)$
+* Space complexity: $O(32)$
+
+> $32$ represents the number of bits as the given numbers are integers.
+
+---
+
+## 5. Boyer-Moore Voting Algorithm
+
+::tabs-start
+
+```python
+class Solution:
+ def majorityElement(self, nums):
+ res = count = 0
+
+ for num in nums:
+ if count == 0:
+ res = num
+ count += (1 if num == res else -1)
+ return res
+```
+
+```java
+public class Solution {
+ public int majorityElement(int[] nums) {
+ int res = 0, count = 0;
+
+ for (int num : nums) {
+ if (count == 0) {
+ res = num;
+ }
+ count += (num == res) ? 1 : -1;
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int majorityElement(vector& nums) {
+ int res = 0, count = 0;
+
+ for (int num : nums) {
+ if (count == 0) {
+ res = num;
+ }
+ count += (num == res) ? 1 : -1;
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ majorityElement(nums) {
+ let res = 0, count = 0;
+
+ for (let num of nums) {
+ if (count === 0) {
+ res = num;
+ }
+ count += (num === res) ? 1 : -1;
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
+
+---
+
+## 6. Randomization
+
+::tabs-start
+
+```python
+class Solution:
+ def majorityElement(self, nums):
+ n = len(nums)
+ while True:
+ candidate = random.choice(nums)
+ if nums.count(candidate) > n // 2:
+ return candidate
+```
+
+```java
+public class Solution {
+ public int majorityElement(int[] nums) {
+ Random rand = new Random();
+ int n = nums.length;
+
+ while (true) {
+ int candidate = nums[rand.nextInt(n)];
+ int count = 0;
+ for (int num : nums) {
+ if (num == candidate) {
+ count++;
+ }
+ }
+ if (count > n / 2) {
+ return candidate;
+ }
+ }
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int majorityElement(vector& nums) {
+ int n = nums.size();
+
+ while (true) {
+ int candidate = nums[rand() % n];
+ int count = 0;
+ for (int num : nums) {
+ if (num == candidate) {
+ count++;
+ }
+ }
+ if (count > n / 2) {
+ return candidate;
+ }
+ }
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number}
+ */
+ majorityElement(nums) {
+ const n = nums.length;
+ while (true) {
+ const candidate = nums[Math.floor(Math.random() * n)];
+ let count = 0;
+ for (const num of nums) {
+ if (num === candidate) {
+ count++;
+ }
+ }
+ if (count > Math.floor(n / 2)) {
+ return candidate;
+ }
+ }
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
+
+> The probability of randomly choosing the majority element is greater than $50\%$, so the expected number of iterations in the outer while loop is constant.
\ No newline at end of file
diff --git a/articles/maximum-number-of-balloons.md b/articles/maximum-number-of-balloons.md
new file mode 100644
index 000000000..597cbf295
--- /dev/null
+++ b/articles/maximum-number-of-balloons.md
@@ -0,0 +1,185 @@
+## 1. Hash Map - I
+
+::tabs-start
+
+```python
+class Solution:
+ def maxNumberOfBalloons(self, text: str) -> int:
+ countText = Counter(text)
+ balloon = Counter("balloon")
+
+ res = len(text)
+ for c in balloon:
+ res = min(res, countText[c] // balloon[c])
+ return res
+```
+
+```java
+public class Solution {
+ public int maxNumberOfBalloons(String text) {
+ Map countText = new HashMap<>();
+ for (char c : text.toCharArray()) {
+ countText.put(c, countText.getOrDefault(c, 0) + 1);
+ }
+
+ Map balloon = new HashMap<>();
+ for (char c : "balloon".toCharArray()) {
+ balloon.put(c, balloon.getOrDefault(c, 0) + 1);
+ }
+
+ int res = text.length();
+ for (char c : balloon.keySet()) {
+ res = Math.min(res, countText.getOrDefault(c, 0) / balloon.get(c));
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int maxNumberOfBalloons(string text) {
+ unordered_map countText;
+ for (char c : text) {
+ countText[c]++;
+ }
+
+ unordered_map balloon = {{'b', 1}, {'a', 1},
+ {'l', 2}, {'o', 2}, {'n', 1}};
+
+ int res = text.length();
+ for (auto& entry : balloon) {
+ res = min(res, countText[entry.first] / entry.second);
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} text
+ * @return {number}
+ */
+ maxNumberOfBalloons(text) {
+ const countText = {};
+ for (const c of text) {
+ countText[c] = (countText[c] || 0) + 1;
+ }
+
+ const balloon = { b: 1, a: 1, l: 2, o: 2, n: 1 };
+
+ let res = text.length;
+ for (const c in balloon) {
+ res = Math.min(res, Math.floor((countText[c] || 0) / balloon[c]));
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
+
+---
+
+## 2. Hash Map - II
+
+::tabs-start
+
+```python
+class Solution:
+ def maxNumberOfBalloons(self, text: str) -> int:
+ mp = defaultdict(int)
+ for c in text:
+ if c in "balon":
+ mp[c] += 1
+
+ if len(mp) < 5:
+ return 0
+
+ mp['l'] //= 2
+ mp['o'] //= 2
+ return min(mp.values())
+```
+
+```java
+public class Solution {
+ public int maxNumberOfBalloons(String text) {
+ Map mp = new HashMap<>();
+ for (char c : text.toCharArray()) {
+ if ("balon".indexOf(c) != -1) {
+ mp.put(c, mp.getOrDefault(c, 0) + 1);
+ }
+ }
+
+ if (mp.size() < 5) {
+ return 0;
+ }
+
+ mp.put('l', mp.get('l') / 2);
+ mp.put('o', mp.get('o') / 2);
+ return Collections.min(mp.values());
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int maxNumberOfBalloons(string text) {
+ unordered_map mp;
+ for (char c : text) {
+ if (string("balon").find(c) != string::npos) {
+ mp[c]++;
+ }
+ }
+
+ if (mp.size() < 5) {
+ return 0;
+ }
+
+ mp['l'] /= 2;
+ mp['o'] /= 2;
+ return min({mp['b'], mp['a'], mp['l'], mp['o'], mp['n']});
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} text
+ * @return {number}
+ */
+ maxNumberOfBalloons(text) {
+ const mp = new Map();
+ for (let c of text) {
+ if ("balon".includes(c)) {
+ mp.set(c, (mp.get(c) || 0) + 1);
+ }
+ }
+
+ if (mp.size < 5) {
+ return 0;
+ }
+
+ mp.set('l', Math.floor(mp.get('l') / 2));
+ mp.set('o', Math.floor(mp.get('o') / 2));
+ return Math.min(...Array.from(mp.values()));
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$ since $balloon$ has $5$ different characters.
\ No newline at end of file
diff --git a/articles/next-greater-element-i.md b/articles/next-greater-element-i.md
new file mode 100644
index 000000000..b81ca977a
--- /dev/null
+++ b/articles/next-greater-element-i.md
@@ -0,0 +1,334 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ n = len(nums2)
+ res = []
+ for num in nums1:
+ nextGreater = -1
+ for i in range(n - 1, -1, -1):
+ if nums2[i] > num:
+ nextGreater = nums2[i]
+ elif nums2[i] == num:
+ break
+ res.append(nextGreater)
+ return res
+```
+
+```java
+public class Solution {
+ public int[] nextGreaterElement(int[] nums1, int[] nums2) {
+ int n = nums2.length;
+ int[] res = new int[nums1.length];
+ for (int i = 0; i < nums1.length; i++) {
+ int nextGreater = -1;
+ for (int j = n - 1; j >= 0; j--) {
+ if (nums2[j] > nums1[i]) {
+ nextGreater = nums2[j];
+ } else if (nums2[j] == nums1[i]) {
+ break;
+ }
+ }
+ res[i] = nextGreater;
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector nextGreaterElement(vector& nums1, vector& nums2) {
+ int n = nums2.size();
+ vector res;
+ for (int num : nums1) {
+ int nextGreater = -1;
+ for (int i = n - 1; i >= 0; i--) {
+ if (nums2[i] > num) {
+ nextGreater = nums2[i];
+ } else if (nums2[i] == num) {
+ break;
+ }
+ }
+ res.push_back(nextGreater);
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number[]}
+ */
+ nextGreaterElement(nums1, nums2) {
+ const n = nums2.length;
+ const res = [];
+ for (const num of nums1) {
+ let nextGreater = -1;
+ for (let i = n - 1; i >= 0; i--) {
+ if (nums2[i] > num) {
+ nextGreater = nums2[i];
+ } else if (nums2[i] === num) {
+ break;
+ }
+ }
+ res.push(nextGreater);
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(m * n)$
+* Space complexity: $O(1)$
+
+> Where $m$ is the size of the array $nums1$ and $n$ is the size of the array $nums2$.
+
+---
+
+## 2. Hash Map
+
+::tabs-start
+
+```python
+class Solution:
+ def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ nums1Idx = {num : i for i, num in enumerate(nums1)}
+ res = [-1] * len(nums1)
+
+ for i in range(len(nums2)):
+ if nums2[i] not in nums1Idx:
+ continue
+ for j in range(i + 1, len(nums2)):
+ if nums2[j] > nums2[i]:
+ idx = nums1Idx[nums2[i]]
+ res[idx] = nums2[j]
+ break
+ return res
+```
+
+```java
+public class Solution {
+ public int[] nextGreaterElement(int[] nums1, int[] nums2) {
+ HashMap nums1Idx = new HashMap<>();
+ for (int i = 0; i < nums1.length; i++) {
+ nums1Idx.put(nums1[i], i);
+ }
+
+ int[] res = new int[nums1.length];
+ Arrays.fill(res, -1);
+
+ for (int i = 0; i < nums2.length; i++) {
+ if (!nums1Idx.containsKey(nums2[i])) {
+ continue;
+ }
+ for (int j = i + 1; j < nums2.length; j++) {
+ if (nums2[j] > nums2[i]) {
+ int idx = nums1Idx.get(nums2[i]);
+ res[idx] = nums2[j];
+ break;
+ }
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector nextGreaterElement(vector& nums1, vector& nums2) {
+ unordered_map nums1Idx;
+ for (int i = 0; i < nums1.size(); i++) {
+ nums1Idx[nums1[i]] = i;
+ }
+
+ vector res(nums1.size(), -1);
+
+ for (int i = 0; i < nums2.size(); i++) {
+ if (nums1Idx.find(nums2[i]) == nums1Idx.end()) {
+ continue;
+ }
+ for (int j = i + 1; j < nums2.size(); j++) {
+ if (nums2[j] > nums2[i]) {
+ int idx = nums1Idx[nums2[i]];
+ res[idx] = nums2[j];
+ break;
+ }
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number[]}
+ */
+ nextGreaterElement(nums1, nums2) {
+ const nums1Idx = new Map();
+ nums1.forEach((num, i) => nums1Idx.set(num, i));
+
+ const res = new Array(nums1.length).fill(-1);
+
+ for (let i = 0; i < nums2.length; i++) {
+ if (!nums1Idx.has(nums2[i])) {
+ continue;
+ }
+ for (let j = i + 1; j < nums2.length; j++) {
+ if (nums2[j] > nums2[i]) {
+ const idx = nums1Idx.get(nums2[i]);
+ res[idx] = nums2[j];
+ break;
+ }
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(m * n)$
+* Space complexity: $O(m)$
+
+> Where $m$ is the size of the array $nums1$ and $n$ is the size of the array $nums2$.
+
+---
+
+## 3. Stack
+
+::tabs-start
+
+```python
+class Solution:
+ def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ nums1Idx = {num : i for i, num in enumerate(nums1)}
+ res = [-1] * len(nums1)
+
+ stack = []
+ for i in range(len(nums2)):
+ cur = nums2[i]
+ while stack and cur > stack[-1]:
+ val = stack.pop()
+ idx = nums1Idx[val]
+ res[idx] = cur
+ if cur in nums1Idx:
+ stack.append(cur)
+ return res
+```
+
+```java
+public class Solution {
+ public int[] nextGreaterElement(int[] nums1, int[] nums2) {
+ HashMap nums1Idx = new HashMap<>();
+ for (int i = 0; i < nums1.length; i++) {
+ nums1Idx.put(nums1[i], i);
+ }
+
+ int[] res = new int[nums1.length];
+ for (int i = 0; i < res.length; i++) {
+ res[i] = -1;
+ }
+
+ Stack stack = new Stack<>();
+ for (int num : nums2) {
+ while (!stack.isEmpty() && num > stack.peek()) {
+ int val = stack.pop();
+ int idx = nums1Idx.get(val);
+ res[idx] = num;
+ }
+ if (nums1Idx.containsKey(num)) {
+ stack.push(num);
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector nextGreaterElement(vector& nums1, vector& nums2) {
+ unordered_map nums1Idx;
+ for (int i = 0; i < nums1.size(); i++) {
+ nums1Idx[nums1[i]] = i;
+ }
+
+ vector res(nums1.size(), -1);
+ stack stack;
+
+ for (int num : nums2) {
+ while (!stack.empty() && num > stack.top()) {
+ int val = stack.top();
+ stack.pop();
+ int idx = nums1Idx[val];
+ res[idx] = num;
+ }
+ if (nums1Idx.find(num) != nums1Idx.end()) {
+ stack.push(num);
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number[]}
+ */
+ nextGreaterElement(nums1, nums2) {
+ const nums1Idx = new Map();
+ nums1.forEach((num, i) => nums1Idx.set(num, i));
+
+ const res = new Array(nums1.length).fill(-1);
+ const stack = [];
+
+ for (let num of nums2) {
+ while (stack.length && num > stack[stack.length - 1]) {
+ const val = stack.pop();
+ const idx = nums1Idx.get(val);
+ res[idx] = num;
+ }
+ if (nums1Idx.has(num)) {
+ stack.push(num);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(m + n)$
+* Space complexity: $O(m)$
+
+> Where $m$ is the size of the array $nums1$ and $n$ is the size of the array $nums2$.
\ No newline at end of file
diff --git a/articles/pascals-triangle.md b/articles/pascals-triangle.md
new file mode 100644
index 000000000..a3434d283
--- /dev/null
+++ b/articles/pascals-triangle.md
@@ -0,0 +1,260 @@
+## 1. Combinatorics
+
+::tabs-start
+
+```python
+class Solution:
+ def generate(self, numRows: int) -> List[List[int]]:
+ res = []
+ for n in range(numRows):
+ row = [1]
+ val = 1
+ for k in range(1, n + 1):
+ val = val * (n - k + 1) // k
+ row.append(val)
+ res.append(row)
+ return res
+```
+
+```java
+public class Solution {
+ public List> generate(int numRows) {
+ List> res = new ArrayList<>();
+ for (int n = 0; n < numRows; n++) {
+ List row = new ArrayList<>();
+ row.add(1);
+ int val = 1;
+ for (int k = 1; k <= n; k++) {
+ val = val * (n - k + 1) / k;
+ row.add(val);
+ }
+ res.add(row);
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector> generate(int numRows) {
+ vector> res;
+ for (int n = 0; n < numRows; n++) {
+ vector row;
+ row.push_back(1);
+ int val = 1;
+ for (int k = 1; k <= n; k++) {
+ val = val * (n - k + 1) / k;
+ row.push_back(val);
+ }
+ res.push_back(row);
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number} numRows
+ * @return {number[][]}
+ */
+ generate(numRows) {
+ let res = [];
+ for (let n = 0; n < numRows; n++) {
+ let row = [1];
+ let val = 1;
+ for (let k = 1; k <= n; k++) {
+ val = (val * (n - k + 1)) / k;
+ row.push(val);
+ }
+ res.push(row);
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n ^ 2)$
+* Space complexity: $O(1)$
+
+---
+
+## 2. Dynamic Programming - I
+
+::tabs-start
+
+```python
+class Solution:
+ def generate(self, numRows: int) -> List[List[int]]:
+ res = [[1]]
+
+ for i in range(numRows - 1):
+ temp = [0] + res[-1] + [0]
+ row = []
+ for j in range(len(res[-1]) + 1):
+ row.append(temp[j] + temp[j + 1])
+ res.append(row)
+ return res
+```
+
+```java
+public class Solution {
+ public List> generate(int numRows) {
+ List> res = new ArrayList<>();
+ res.add(new ArrayList<>());
+ res.get(0).add(1);
+
+ for (int i = 1; i < numRows; i++) {
+ List temp = new ArrayList<>(res.get(i - 1));
+ temp.add(0, 0);
+ temp.add(0);
+ List row = new ArrayList<>();
+
+ for (int j = 0; j < res.get(i - 1).size() + 1; j++) {
+ row.add(temp.get(j) + temp.get(j + 1));
+ }
+
+ res.add(row);
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector> generate(int numRows) {
+ vector> res = {{1}};
+
+ for (int i = 0; i < numRows - 1; i++) {
+ vector temp = {0};
+ temp.insert(temp.end(), res.back().begin(), res.back().end());
+ temp.push_back(0);
+ vector row;
+ for (size_t j = 0; j < res.back().size() + 1; j++) {
+ row.push_back(temp[j] + temp[j + 1]);
+ }
+ res.push_back(row);
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number} numRows
+ * @return {number[][]}
+ */
+ generate(numRows) {
+ let res = [[1]];
+
+ for (let i = 0; i < numRows - 1; i++) {
+ let temp = [0, ...res[res.length - 1], 0];
+ let row = [];
+ for (let j = 0; j < res[res.length - 1].length + 1; j++) {
+ row.push(temp[j] + temp[j + 1]);
+ }
+ res.push(row);
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n ^ 2)$
+* Space complexity: $O(n)$
+
+---
+
+## 3. Dynamic Programming - II
+
+::tabs-start
+
+```python
+class Solution:
+ def generate(self, numRows: int) -> List[List[int]]:
+ res = [[1] * (i + 1) for i in range(numRows)]
+ for i in range(2, numRows):
+ for j in range(1, i):
+ res[i][j] = res[i - 1][j - 1] + res[i - 1][j]
+ return res
+```
+
+```java
+public class Solution {
+ public List> generate(int numRows) {
+ List> res = new ArrayList<>();
+
+ for (int i = 0; i < numRows; i++) {
+ List row = new ArrayList<>();
+ for (int j = 0; j <= i; j++) {
+ if (j == 0 || j == i) {
+ row.add(1);
+ } else {
+ row.add(res.get(i - 1).get(j - 1) + res.get(i - 1).get(j));
+ }
+ }
+ res.add(row);
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector> generate(int numRows) {
+ vector> res(numRows);
+
+ for (int i = 0; i < numRows; i++) {
+ res[i].resize(i + 1);
+ res[i][0] = res[i][i] = 1;
+ for (int j = 1; j < i; j++){
+ res[i][j] = res[i - 1][j - 1] + res[i - 1][j];
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number} numRows
+ * @return {number[][]}
+ */
+ generate(numRows) {
+ let res = Array.from({ length: numRows }, (_, i) => Array(i + 1).fill(1));
+
+ for (let i = 2; i < numRows; i++) {
+ for (let j = 1; j < i; j++) {
+ res[i][j] = res[i - 1][j - 1] + res[i - 1][j];
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n ^ 2)$
+* Space complexity: $O(1)$
\ No newline at end of file
diff --git a/articles/remove-element.md b/articles/remove-element.md
new file mode 100644
index 000000000..1c3d722e4
--- /dev/null
+++ b/articles/remove-element.md
@@ -0,0 +1,233 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def removeElement(self, nums: list[int], val: int) -> int:
+ tmp = []
+ for num in nums:
+ if num == val:
+ continue
+ tmp.append(num)
+ for i in range(len(tmp)):
+ nums[i] = tmp[i]
+ return len(tmp)
+```
+
+```java
+public class Solution {
+ public int removeElement(int[] nums, int val) {
+ List tmp = new ArrayList<>();
+ for (int num : nums) {
+ if (num != val) {
+ tmp.add(num);
+ }
+ }
+ for (int i = 0; i < tmp.size(); i++) {
+ nums[i] = tmp.get(i);
+ }
+ return tmp.size();
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int removeElement(vector& nums, int val) {
+ vector tmp;
+ for (int num : nums) {
+ if (num != val) {
+ tmp.push_back(num);
+ }
+ }
+ for (int i = 0; i < tmp.size(); i++) {
+ nums[i] = tmp[i];
+ }
+ return tmp.size();
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @param {number} val
+ * @return {number}
+ */
+ removeElement(nums, val) {
+ const tmp = [];
+ for (const num of nums) {
+ if (num !== val) {
+ tmp.push(num);
+ }
+ }
+ for (let i = 0; i < tmp.length; i++) {
+ nums[i] = tmp[i];
+ }
+ return tmp.length;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 2. Two Pointers - I
+
+::tabs-start
+
+```python
+class Solution:
+ def removeElement(self, nums: list[int], val: int) -> int:
+ k = 0
+ for i in range(len(nums)):
+ if nums[i] != val:
+ nums[k] = nums[i]
+ k += 1
+ return k
+```
+
+```java
+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;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int removeElement(vector& nums, int val) {
+ int k = 0;
+ for (int i = 0; i < nums.size(); i++) {
+ if (nums[i] != val) {
+ nums[k++] = nums[i];
+ }
+ }
+ return k;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @param {number} val
+ * @return {number}
+ */
+ removeElement(nums, val) {
+ let k = 0;
+ for (let i = 0; i < nums.length; i++) {
+ if (nums[i] !== val) {
+ nums[k++] = nums[i];
+ }
+ }
+ return k;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
+
+---
+
+## 3. Two Pointers - II
+
+::tabs-start
+
+```python
+class Solution:
+ def removeElement(self, nums: list[int], val: int) -> int:
+ i = 0
+ n = len(nums)
+ while i < n:
+ if nums[i] == val:
+ n -= 1
+ nums[i] = nums[n]
+ else:
+ i += 1
+ return n
+```
+
+```java
+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;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int removeElement(vector& nums, int val) {
+ int i = 0, n = nums.size();
+ while (i < n) {
+ if (nums[i] == val) {
+ nums[i] = nums[--n];
+ } else {
+ i++;
+ }
+ }
+ return n;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @param {number} val
+ * @return {number}
+ */
+ removeElement(nums, val) {
+ let 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
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
\ No newline at end of file
diff --git a/articles/replace-elements-with-greatest-element-on-right-side.md b/articles/replace-elements-with-greatest-element-on-right-side.md
new file mode 100644
index 000000000..1825436a7
--- /dev/null
+++ b/articles/replace-elements-with-greatest-element-on-right-side.md
@@ -0,0 +1,154 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def replaceElements(self, arr: List[int]) -> List[int]:
+ n = len(arr)
+ ans = [0] * n
+ for i in range(n):
+ rightMax = -1
+ for j in range(i + 1, n):
+ rightMax = max(rightMax, arr[j])
+ ans[i] = rightMax
+ return ans
+```
+
+```java
+public class Solution {
+ public int[] replaceElements(int[] arr) {
+ int n = arr.length;
+ int[] ans = new int[n];
+ for (int i = 0; i < n; i++) {
+ int rightMax = -1;
+ for (int j = i + 1; j < n; j++) {
+ rightMax = Math.max(rightMax, arr[j]);
+ }
+ ans[i] = rightMax;
+ }
+ return ans;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector replaceElements(vector& arr) {
+ int n = arr.size();
+ vector ans(n);
+ for (int i = 0; i < n; ++i) {
+ int rightMax = -1;
+ for (int j = i + 1; j < n; ++j) {
+ rightMax = max(rightMax, arr[j]);
+ }
+ ans[i] = rightMax;
+ }
+ return ans;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} arr
+ * @return {number[]}
+ */
+ replaceElements(arr) {
+ let n = arr.length;
+ let ans = new Array(n);
+ for (let i = 0; i < n; i++) {
+ let rightMax = -1;
+ for (let j = i + 1; j < n; j++) {
+ rightMax = Math.max(rightMax, arr[j]);
+ }
+ ans[i] = rightMax;
+ }
+ return ans;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n ^ 2)$
+* Space complexity: $O(1)$
+
+---
+
+## 2. Suffix Max
+
+::tabs-start
+
+```python
+class Solution:
+ def replaceElements(self, arr: List[int]) -> List[int]:
+ n = len(arr)
+ ans = [0] * n
+ rightMax = -1
+ for i in range(n - 1, -1, -1):
+ ans[i] = rightMax
+ rightMax = max(arr[i], rightMax)
+ return ans
+```
+
+```java
+public class Solution {
+ public int[] replaceElements(int[] arr) {
+ int n = arr.length;
+ int[] ans = new int[n];
+ int rightMax = -1;
+ for (int i = n - 1; i >= 0; i--) {
+ ans[i] = rightMax;
+ rightMax = Math.max(rightMax, arr[i]);
+ }
+ return ans;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector replaceElements(vector& arr) {
+ int n = arr.size();
+ vector ans(n);
+ int rightMax = -1;
+ for (int i = n - 1; i >= 0; --i) {
+ ans[i] = rightMax;
+ rightMax = max(rightMax, arr[i]);
+ }
+ return ans;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} arr
+ * @return {number[]}
+ */
+ replaceElements(arr) {
+ let n = arr.length;
+ let ans = new Array(n);
+ let rightMax = -1;
+ for (let i = n - 1; i >= 0; i--) {
+ ans[i] = rightMax;
+ rightMax = Math.max(rightMax, arr[i]);
+ }
+ return ans;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
\ No newline at end of file
diff --git a/articles/unique-email-addresses.md b/articles/unique-email-addresses.md
new file mode 100644
index 000000000..41aead4ae
--- /dev/null
+++ b/articles/unique-email-addresses.md
@@ -0,0 +1,197 @@
+## 1. Built-In Functions
+
+::tabs-start
+
+```python
+class Solution:
+ def numUniqueEmails(self, emails: List[str]) -> int:
+ unique = set()
+
+ for e in emails:
+ local, domain = e.split('@')
+ local = local.split("+")[0]
+ local = local.replace(".", "")
+ unique.add((local, domain))
+ return len(unique)
+```
+
+```java
+public class Solution {
+ public int numUniqueEmails(String[] emails) {
+ Set unique = new HashSet<>();
+
+ for (String e : emails) {
+ String[] parts = e.split("@");
+ String local = parts[0];
+ String domain = parts[1];
+
+ local = local.split("\\+")[0];
+ local = local.replace(".", "");
+ unique.add(local + "@" + domain);
+ }
+ return unique.size();
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int numUniqueEmails(vector& emails) {
+ unordered_set unique;
+
+ for (string e : emails) {
+ string local = e.substr(0, e.find('@'));
+ local = local.substr(0, local.find('+'));
+ erase(local, '.');
+ unique.insert(local + e.substr(e.find('@')));
+ }
+ return unique.size();
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[]} emails
+ * @return {number}
+ */
+ numUniqueEmails(emails) {
+ const unique = new Set();
+
+ for (let e of emails) {
+ let [local, domain] = e.split('@');
+ local = local.split('+')[0];
+ local = local.replace(/\./g, '');
+ unique.add(`${local}@${domain}`);
+ }
+ return unique.size;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m)$
+* Space complexity: $O(n)$
+
+> Where $n$ is the number of strings in the array, and $m$ is the average length of these strings.
+
+---
+
+## 2. Iteration
+
+::tabs-start
+
+```python
+class Solution:
+ def numUniqueEmails(self, emails: List[str]) -> int:
+ unique = set()
+
+ for e in emails:
+ i, local = 0, ""
+ while e[i] not in ["@", "+"]:
+ if e[i] != ".":
+ local += e[i]
+ i += 1
+
+ while e[i] != "@":
+ i += 1
+ domain = e[i + 1:]
+ unique.add((local, domain))
+ return len(unique)
+```
+
+```java
+public class Solution {
+ public int numUniqueEmails(String[] emails) {
+ Set unique = new HashSet<>();
+
+ for (String e : emails) {
+ int i = 0;
+ StringBuilder local = new StringBuilder();
+ while (i < e.length() && e.charAt(i) != '@' && e.charAt(i) != '+') {
+ if (e.charAt(i) != '.') {
+ local.append(e.charAt(i));
+ }
+ i++;
+ }
+
+ while (i < e.length() && e.charAt(i) != '@') {
+ i++;
+ }
+ String domain = e.substring(i + 1);
+ unique.add(local.toString() + "@" + domain);
+ }
+ return unique.size();
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int numUniqueEmails(vector& emails) {
+ unordered_set unique;
+
+ for (string e : emails) {
+ int i = 0;
+ string local = "";
+ while (i < e.length() && e[i] != '@' && e[i] != '+') {
+ if (e[i] != '.') {
+ local += e[i];
+ }
+ i++;
+ }
+
+ while (i < e.length() && e[i] != '@') {
+ i++;
+ }
+ string domain = e.substr(i + 1);
+ unique.insert(local + "@" + domain);
+ }
+ return unique.size();
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[]} emails
+ * @return {number}
+ */
+ numUniqueEmails(emails) {
+ const unique = new Set();
+
+ for (let e of emails) {
+ let i = 0, local = "";
+ while (i < e.length && e[i] !== '@' && e[i] !== '+') {
+ if (e[i] !== '.') {
+ local += e[i];
+ }
+ i++;
+ }
+
+ while (i < e.length && e[i] !== '@') {
+ i++;
+ }
+ const domain = e.slice(i + 1);
+ unique.add(`${local}@${domain}`);
+ }
+ return unique.size;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m)$
+* Space complexity: $O(n)$
+
+> Where $n$ is the number of strings in the array, and $m$ is the average length of these strings.
\ No newline at end of file
From fca0598663fbf47f4052046cd39af1f4e06e9341 Mon Sep 17 00:00:00 2001
From: Guillaume Desktop
Date: Sat, 30 Nov 2024 13:00:01 +0100
Subject: [PATCH 27/67] create csharp/0069-sqrt.cs
---
csharp/0069-sqrt.cs | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 csharp/0069-sqrt.cs
diff --git a/csharp/0069-sqrt.cs b/csharp/0069-sqrt.cs
new file mode 100644
index 000000000..103574432
--- /dev/null
+++ b/csharp/0069-sqrt.cs
@@ -0,0 +1,21 @@
+public class Solution
+{
+ public int MySqrt(int x)
+ {
+ int left = 0, right = x;
+ while (left <= right)
+ {
+ int mid = (left + right) >> 1;
+ long pow = (long)mid * mid;
+ if (pow <= x)
+ {
+ left = mid + 1;
+ }
+ else
+ {
+ right = mid - 1;
+ }
+ }
+ return left - 1;
+ }
+}
\ No newline at end of file
From f138da79ff0597a7e06d0c27a1fef8f681a9d809 Mon Sep 17 00:00:00 2001
From: Guillaume Desktop
Date: Sat, 30 Nov 2024 13:03:25 +0100
Subject: [PATCH 28/67] create csharp/0203-remove-linked-list-elements.cs
---
csharp/0203-remove-linked-list-elements.cs | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 csharp/0203-remove-linked-list-elements.cs
diff --git a/csharp/0203-remove-linked-list-elements.cs b/csharp/0203-remove-linked-list-elements.cs
new file mode 100644
index 000000000..a07d5b6f1
--- /dev/null
+++ b/csharp/0203-remove-linked-list-elements.cs
@@ -0,0 +1,21 @@
+public class Solution
+{
+ public ListNode RemoveElements(ListNode head, int val)
+ {
+ ListNode dummy = new ListNode(0, head);
+ ListNode current = dummy;
+
+ while (current.next is not null)
+ {
+ if (current.next.val == val)
+ {
+ current.next = current.next.next;
+ }
+ else
+ {
+ current = current.next;
+ }
+ }
+ return dummy.next;
+ }
+}
\ No newline at end of file
From ad912fbae839721e995671444e6b74f4e6a77342 Mon Sep 17 00:00:00 2001
From: Guillaume Desktop
Date: Sat, 30 Nov 2024 15:09:13 +0100
Subject: [PATCH 29/67] Added additional solution to
csharp/0003-longest-substring-without-repeating-characters.cs
---
...-substring-without-repeating-characters.cs | 52 +++++++++++++++++--
1 file changed, 47 insertions(+), 5 deletions(-)
diff --git a/csharp/0003-longest-substring-without-repeating-characters.cs b/csharp/0003-longest-substring-without-repeating-characters.cs
index cf6e82d7d..15f410758 100644
--- a/csharp/0003-longest-substring-without-repeating-characters.cs
+++ b/csharp/0003-longest-substring-without-repeating-characters.cs
@@ -1,14 +1,22 @@
-public class Solution {
- public int LengthOfLongestSubstring(string s) {
+// hashset
+public class Solution
+{
+ public int LengthOfLongestSubstring(string s)
+ {
int leftPointer = 0, rightPointer = 0, maxLength = 0;
HashSet chars = new HashSet();
- while (rightPointer < s.Length) {
+ while (rightPointer < s.Length)
+ {
char currChar = s[rightPointer];
- if (chars.Contains(currChar)) { // Move left pointer until all duplicate chars removed
+ if (chars.Contains(currChar))
+ {
+ // Move left pointer until all duplicate chars removed
chars.Remove(s[leftPointer]);
leftPointer++;
- } else {
+ }
+ else
+ {
chars.Add(currChar);
maxLength = Math.Max(maxLength, rightPointer - leftPointer + 1);
rightPointer++;
@@ -16,4 +24,38 @@ public int LengthOfLongestSubstring(string s) {
}
return maxLength;
}
+}
+
+//bitmask
+public class Solution
+{
+ private Int128 ONE = 1;
+ public int LengthOfLongestSubstring(string s)
+ {
+ int Convert(char ch) => ch - ' ';
+ Int128 mask = 0;
+ int l = 0, r = 0, output = 0;
+ while (r < s.Length)
+ {
+ Int128 temp = mask ^ (ONE << Convert(s[r]));
+ if (temp < mask)
+ {
+ while (s[l] != s[r])
+ {
+ mask ^= ONE << Convert(s[l]);
+ l++;
+ }
+ mask ^= ONE << Convert(s[l]);
+ l++;
+ }
+ else
+ {
+ mask = temp;
+ output = Math.Max(output, r - l + 1);
+ r++;
+ }
+ }
+
+ return output;
+ }
}
\ No newline at end of file
From 9898f4bbb596ee8d42a877820ac0293f24ea937e Mon Sep 17 00:00:00 2001
From: Yaseen Khan
Date: Sat, 30 Nov 2024 23:45:15 -0800
Subject: [PATCH 30/67] changed filename to match other submitted solutions for
this problem
---
csharp/{0069-sqrt.cs => 0069-sqrtx.cs} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename csharp/{0069-sqrt.cs => 0069-sqrtx.cs} (99%)
diff --git a/csharp/0069-sqrt.cs b/csharp/0069-sqrtx.cs
similarity index 99%
rename from csharp/0069-sqrt.cs
rename to csharp/0069-sqrtx.cs
index 103574432..a994a0f06 100644
--- a/csharp/0069-sqrt.cs
+++ b/csharp/0069-sqrtx.cs
@@ -18,4 +18,4 @@ public int MySqrt(int x)
}
return left - 1;
}
-}
\ No newline at end of file
+}
From 70c2bab48651f009f8690b0db532c275cee053b1 Mon Sep 17 00:00:00 2001
From: Bot-A0 <71089234+Ahmad-A0@users.noreply.github.com>
Date: Sun, 1 Dec 2024 08:07:57 +0000
Subject: [PATCH 31/67] =?UTF-8?q?=F0=9F=93=9C=20Update=20README=20table=20?=
=?UTF-8?q?(=F0=9F=9B=A0=EF=B8=8F=20from=20Github=20Actions)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index fbe35a7f3..621435471 100644
--- a/README.md
+++ b/README.md
@@ -166,7 +166,7 @@ If you would like to have collaborator permissions on the repo to merge your own
[0441 - Arranging Coins](https://leetcode.com/problems/arranging-coins/) | ❌
| ❌
| [✔️](cpp%2F0441-arranging-coins.cpp)
| ❌
| ❌
| ❌
| ❌
| [✔️](java%2F0441-arranging-coins.java)
| [✔️](javascript%2F0441-arranging-coins.js)
| [✔️](kotlin%2F0441-arranging-coins.kt)
| [✔️](python%2F0441-arranging-coins.py)
| ❌
| [✔️](rust%2F0441-arranging-coins.rs)
| ❌
| ❌
| ❌
[0977 - Squares of a Sorted Array](https://leetcode.com/problems/squares-of-a-sorted-array/) | ❌
| ❌
| [✔️](cpp%2F0977-squares-of-a-sorted-array.cpp)
| ❌
| ❌
| [✔️](go%2F0977-squares-of-a-sorted-array.go)
| ❌
| [✔️](java%2F0977-squares-of-a-sorted-array.java)
| [✔️](javascript%2F0977-squares-of-a-sorted-array.js)
| [✔️](kotlin%2F0977-squares-of-a-sorted-array.kt)
| [✔️](python%2F0977-squares-of-a-sorted-array.py)
| ❌
| [✔️](rust%2F0977-squares-of-a-sorted-array.rs)
| ❌
| [✔️](swift%2F0977-squares-of-a-sorted-array.swift)
| [✔️](typescript%2F0977-squares-of-a-sorted-array.ts)
[0367 - Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) | ❌
| [✔️](c%2F0367-valid-perfect-square.c)
| [✔️](cpp%2F0367-valid-perfect-square.cpp)
| ❌
| ❌
| [✔️](go%2F0367-valid-perfect-square.go)
| ❌
| [✔️](java%2F0367-valid-perfect-square.java)
| [✔️](javascript%2F0367-valid-perfect-square.js)
| [✔️](kotlin%2F0367-valid-perfect-square.kt)
| [✔️](python%2F0367-valid-perfect-square.py)
| ❌
| ❌
| ❌
| [✔️](swift%2F0367-valid-perfect-square.swift)
| ❌
-[0069 - Sqrt(x) ](https://leetcode.com/problems/sqrtx/) | ❌
| [✔️](c%2F0069-sqrtx.c)
| [✔️](cpp%2F0069-sqrtx.cpp)
| ❌
| ❌
| ❌
| ❌
| [✔️](java%2F0069-sqrtx.java)
| [✔️](javascript%2F0069-sqrtx.js)
| [✔️](kotlin%2F0069-sqrtx.kt)
| [✔️](python%2F0069-sqrtx.py)
| ❌
| ❌
| ❌
| ❌
| ❌
+[0069 - Sqrt(x) ](https://leetcode.com/problems/sqrtx/) | ❌
| [✔️](c%2F0069-sqrtx.c)
| [✔️](cpp%2F0069-sqrtx.cpp)
| [✔️](csharp%2F0069-sqrtx.cs)
| ❌
| ❌
| ❌
| [✔️](java%2F0069-sqrtx.java)
| [✔️](javascript%2F0069-sqrtx.js)
| [✔️](kotlin%2F0069-sqrtx.kt)
| [✔️](python%2F0069-sqrtx.py)
| ❌
| ❌
| ❌
| ❌
| ❌
[0540 - Single Element in a Sorted Array](https://leetcode.com/problems/single-element-in-a-sorted-array/) | ❌
| [✔️](c%2F0540-single-element-in-a-sorted-array.c)
| [✔️](cpp%2F0540-single-element-in-a-sorted-array.cpp)
| ❌
| ❌
| ❌
| ❌
| [✔️](java%2F0540-single-element-in-a-sorted-array.java)
| [✔️](javascript%2F0540-single-element-in-a-sorted-array.js)
| [✔️](kotlin%2F0540-single-element-in-a-sorted-array.kt)
| [✔️](python%2F0540-single-element-in-a-sorted-array.py)
| ❌
| ❌
| ❌
| ❌
| [✔️](typescript%2F0540-single-element-in-a-sorted-array.ts)
[1011 - Capacity to Ship Packages](https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/) | ❌
| ❌
| [✔️](cpp%2F1011-capacity-to-ship-packages-within-d-days.cpp)
| ❌
| ❌
| ❌
| ❌
| [✔️](java%2F1011-capacity-to-ship-packages-within-d-days.java)
| ❌
| [✔️](kotlin%2F1011-capacity-to-ship-packages-within-d-days.kt)
| [✔️](python%2F1011-capacity-to-ship-packages-within-d-days.py)
| ❌
| ❌
| ❌
| ❌
| ❌
[0162 - Find Peak Element](https://leetcode.com/problems/find-peak-element/) | ❌
| [✔️](c%2F0162-find-peak-element.c)
| [✔️](cpp%2F0162-find-peak-element.cpp)
| ❌
| ❌
| ❌
| ❌
| [✔️](java%2F0162-find-peak-element.java)
| [✔️](javascript%2F0162-find-peak-element.js)
| [✔️](kotlin%2F0162-find-peak-element.kt)
| [✔️](python%2F0162-find-peak-element.py)
| ❌
| ❌
| ❌
| ❌
| ❌
@@ -192,7 +192,7 @@ If you would like to have collaborator permissions on the repo to merge your own
[0206 - Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/) | ❌
| [✔️](c%2F0206-reverse-linked-list.c)
| [✔️](cpp%2F0206-reverse-linked-list.cpp)
| [✔️](csharp%2F0206-reverse-linked-list.cs)
| [✔️](dart%2F0206-reverse-linked-list.dart)
| [✔️](go%2F0206-reverse-linked-list.go)
| ❌
| [✔️](java%2F0206-reverse-linked-list.java)
| [✔️](javascript%2F0206-reverse-linked-list.js)
| [✔️](kotlin%2F0206-reverse-linked-list.kt)
| [✔️](python%2F0206-reverse-linked-list.py)
| [✔️](ruby%2F0206-reverse-linked-list.rb)
| [✔️](rust%2F0206-reverse-linked-list.rs)
| [✔️](scala%2F0206-reverse-linked-list.scala)
| [✔️](swift%2F0206-reverse-linked-list.swift)
| [✔️](typescript%2F0206-reverse-linked-list.ts)
[0021 - Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/) | ❌
| [✔️](c%2F0021-merge-two-sorted-lists.c)
| [✔️](cpp%2F0021-merge-two-sorted-lists.cpp)
| [✔️](csharp%2F0021-merge-two-sorted-lists.cs)
| [✔️](dart%2F0021-merge-two-sorted-lists.dart)
| [✔️](go%2F0021-merge-two-sorted-lists.go)
| ❌
| [✔️](java%2F0021-merge-two-sorted-lists.java)
| [✔️](javascript%2F0021-merge-two-sorted-lists.js)
| [✔️](kotlin%2F0021-merge-two-sorted-lists.kt)
| [✔️](python%2F0021-merge-two-sorted-lists.py)
| [✔️](ruby%2F0021-merge-two-sorted-lists.rb)
| [✔️](rust%2F0021-merge-two-sorted-lists.rs)
| [✔️](scala%2F0021-merge-two-sorted-lists.scala)
| [✔️](swift%2F0021-merge-two-sorted-lists.swift)
| [✔️](typescript%2F0021-merge-two-sorted-lists.ts)
[0234 - Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list/) | ❌
| [✔️](c%2F0234-palindrome-linked-list.c)
| [✔️](cpp%2F0234-palindrome-linked-list.cpp)
| ❌
| ❌
| [✔️](go%2F0234-palindrome-linked-list.go)
| ❌
| [✔️](java%2F0234-palindrome-linked-list.java)
| [✔️](javascript%2F0234-palindrome-linked-list.js)
| [✔️](kotlin%2F0234-palindrome-linked-list.kt)
| [✔️](python%2F0234-palindrome-linked-list.py)
| ❌
| ❌
| ❌
| ❌
| ❌
-[0203 - Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements/) | ❌
| ❌
| [✔️](cpp%2F0203-remove-linked-list-elements.cpp)
| ❌
| ❌
| [✔️](go%2F0203-remove-linked-list-elements.go)
| ❌
| [✔️](java%2F0203-remove-linked-list-elements.java)
| [✔️](javascript%2F0203-remove-linked-list-elements.js)
| [✔️](kotlin%2F0203-remove-linked-list-elements.kt)
| [✔️](python%2F0203-remove-linked-list-elements.py)
| ❌
| ❌
| ❌
| ❌
| [✔️](typescript%2F0203-remove-linked-list-elements.ts)
+[0203 - Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements/) | ❌
| ❌
| [✔️](cpp%2F0203-remove-linked-list-elements.cpp)
| [✔️](csharp%2F0203-remove-linked-list-elements.cs)
| ❌
| [✔️](go%2F0203-remove-linked-list-elements.go)
| ❌
| [✔️](java%2F0203-remove-linked-list-elements.java)
| [✔️](javascript%2F0203-remove-linked-list-elements.js)
| [✔️](kotlin%2F0203-remove-linked-list-elements.kt)
| [✔️](python%2F0203-remove-linked-list-elements.py)
| ❌
| ❌
| ❌
| ❌
| [✔️](typescript%2F0203-remove-linked-list-elements.ts)
[0083 - Remove Duplicates From Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list/) | ❌
| [✔️](c%2F0083-remove-duplicates-from-sorted-list.c)
| [✔️](cpp%2F0083-remove-duplicates-from-sorted-list.cpp)
| ❌
| ❌
| [✔️](go%2F0083-remove-duplicates-from-sorted-list.go)
| ❌
| [✔️](java%2F0083-remove-duplicates-from-sorted-list.java)
| [✔️](javascript%2F0083-remove-duplicates-from-sorted-list.js)
| [✔️](kotlin%2F0083-remove-duplicates-from-sorted-list.kt)
| [✔️](python%2F0083-remove-duplicates-from-sorted-list.py)
| ❌
| ❌
| ❌
| [✔️](swift%2F0083-remove-duplicates-from-sorted-list.swift)
| ❌
[0876 - Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list/) | ❌
| [✔️](c%2F0876-middle-of-the-linked-list.c)
| [✔️](cpp%2F0876-middle-of-the-linked-list.cpp)
| [✔️](csharp%2F0876-middle-of-the-linked-list.cs)
| ❌
| [✔️](go%2F0876-middle-of-the-linked-list.go)
| ❌
| [✔️](java%2F0876-middle-of-the-linked-list.java)
| [✔️](javascript%2F0876-middle-of-the-linked-list.js)
| [✔️](kotlin%2F0876-middle-of-the-linked-list.kt)
| [✔️](python%2F0876-middle-of-the-linked-list.py)
| ❌
| [✔️](rust%2F0876-middle-of-the-linked-list.rs)
| ❌
| [✔️](swift%2F0876-middle-of-the-linked-list.swift)
| [✔️](typescript%2F0876-middle-of-the-linked-list.ts)
[0160 - Intersection of Two Linked Lists](https://leetcode.com/problems/intersection-of-two-linked-lists/) | ❌
| [✔️](c%2F0160-intersection-of-two-linked-lists.c)
| [✔️](cpp%2F0160-intersection-of-two-linked-lists.cpp)
| ❌
| ❌
| [✔️](go%2F0160-intersection-of-two-linked-lists.go)
| ❌
| [✔️](java%2F0160-intersection-of-two-linked-lists.java)
| [✔️](javascript%2F0160-intersection-of-two-linked-lists.js)
| [✔️](kotlin%2F0160-intersection-of-two-linked-lists.kt)
| [✔️](python%2F0160-intersection-of-two-linked-lists.py)
| ❌
| ❌
| ❌
| ❌
| ❌
From a0098a6a0fe56a9168f75367937d01f667358bdb Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Sat, 7 Dec 2024 02:06:25 +0530
Subject: [PATCH 32/67] Batch-3/Neetcode-All/Added (#3759)
---
hints/count-connected-components.md | 31 +++++++++++++++++++++++
hints/course-schedule-ii.md | 31 +++++++++++++++++++++++
hints/course-schedule.md | 2 +-
hints/min-cost-to-connect-points.md | 31 +++++++++++++++++++++++
hints/network-delay-time.md | 31 +++++++++++++++++++++++
hints/reconstruct-flight-path.md | 39 +++++++++++++++++++++++++++++
hints/redundant-connection.md | 31 +++++++++++++++++++++++
hints/swim-in-rising-water.md | 31 +++++++++++++++++++++++
hints/valid-tree.md | 31 +++++++++++++++++++++++
hints/word-ladder.md | 31 +++++++++++++++++++++++
10 files changed, 288 insertions(+), 1 deletion(-)
create mode 100644 hints/count-connected-components.md
create mode 100644 hints/course-schedule-ii.md
create mode 100644 hints/min-cost-to-connect-points.md
create mode 100644 hints/network-delay-time.md
create mode 100644 hints/reconstruct-flight-path.md
create mode 100644 hints/redundant-connection.md
create mode 100644 hints/swim-in-rising-water.md
create mode 100644 hints/valid-tree.md
create mode 100644 hints/word-ladder.md
diff --git a/hints/count-connected-components.md b/hints/count-connected-components.md
new file mode 100644
index 000000000..4998f22ad
--- /dev/null
+++ b/hints/count-connected-components.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(V + E)
time and O(V + E)
space, where V
is the number vertices and E
is the number of edges in the graph.
+
+
+
+
+
+ Hint 1
+
+ Assume there are no edges initially, so we have n
components, as there are that many nodes given. Now, we should add the given edges between the nodes. Can you think of an algorithm to add the edges between the nodes? Also, after adding an edge, how do you determine the number of components left?
+
+
+
+
+
+ Hint 2
+
+ We can use the Union-Find (DSU) algorithm to add the given edges. For simplicity, we use Union-Find by size, where we merge the smaller component into the larger one. The Union-Find algorithm inserts the edge only between two nodes from different components. It does not add the edge if the nodes are from the same component. How do you find the number of components after adding the edges? For example, consider that nodes 0
and 1
are not connected, so there are initially two components. After adding an edge between these nodes, they become part of the same component, leaving us with one component.
+
+
+
+
+
+ Hint 3
+
+ We create an object of the DSU and initialize the result variable res = n
, which indicates that there are n
components initially. We then iterate through the given edges. For each edge, we attempt to connect the nodes using the union function of the DSU. If the union is successful, we decrement res
; otherwise, we continue. Finally, we return res
as the number of components.
+
+
\ No newline at end of file
diff --git a/hints/course-schedule-ii.md b/hints/course-schedule-ii.md
new file mode 100644
index 000000000..e187980f9
--- /dev/null
+++ b/hints/course-schedule-ii.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(V + E)
time and O(V + E)
space, where V
is the number of courses (nodes) and E
is the number of prerequisites (edges).
+
+
+
+
+
+ Hint 1
+
+ Consider the problem as a graph where courses represent the nodes, and prerequisite[i] = [a, b]
represents a directed edge from a
to b
. We need to determine whether the graph contains a cycle. Why? Because if there is a cycle, it is impossible to complete the courses involved in the cycle. Can you think of an algorithm to detect a cycle in a graph and also find the valid ordering if a cycle doesn't exist?
+
+
+
+
+
+ Hint 2
+
+ We can use DFS to detect a cycle in a graph. However, we also need to find the valid ordering of the courses, which can also be achieved using DFS. Alternatively, we can use the Topological Sort algorithm to find the valid ordering in this directed graph, where the graph must be acyclic to complete all the courses, and the prerequisite of a course acts as the parent node of that course. How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We compute the indegrees of all the nodes. Then, we perform a BFS starting from the nodes that have no parents (indegree[node] == 0
). At each level, we traverse these nodes, decrement the indegree of their child nodes, and append those child nodes to the queue if their indegree becomes 0
. We only append nodes whose indegree is 0
or becomes 0
during the BFS to our result array. If the length of the result array is not equal to the number of courses, we return an empty array.
+
+
\ No newline at end of file
diff --git a/hints/course-schedule.md b/hints/course-schedule.md
index 1660429b5..1392ac134 100644
--- a/hints/course-schedule.md
+++ b/hints/course-schedule.md
@@ -2,7 +2,7 @@
Recommended Time & Space Complexity
- You should aim for a solution with O(V + E)
time and O(V + E)
space, where V
is the number of courses (nodes) and E
is the number of prerequisites (edges).
+ You should aim for a solution with O(V + E)
time and O(V + E)
space, where V
is the number of courses (nodes) and E
is the number of prerequisites (edges).
diff --git a/hints/min-cost-to-connect-points.md b/hints/min-cost-to-connect-points.md
new file mode 100644
index 000000000..cc585977d
--- /dev/null
+++ b/hints/min-cost-to-connect-points.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O((n^2)logn)
time and O(n^2)
space, where n
is the number of points.
+
+
+
+
+
+ Hint 1
+
+ Think of this problem as a graph, where the given points represent nodes. We need to connect these nodes into a single component by creating edges. Can you think of an advanced graph algorithm that can be used to connect all points into one component?
+
+
+
+
+
+ Hint 2
+
+ We use Kruskal's algorithm along with Union-Find (DSU) to connect nodes into components. The final component forms the minimum spanning tree (MST), where the edges between nodes are weighted by the Manhattan distance, and the total weight of the tree is minimized. How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We create the possible edges by iterating through every pair of points and calculating the weights as the Manhattan distance between them. Next, we sort the edges in ascending order based on their weights, as we aim to minimize the cost. Then, we traverse through these edges, connecting the nodes and adding the weight of the edge to the total cost if the edge is successfully added. The final result will be the minimum cost.
+
+
\ No newline at end of file
diff --git a/hints/network-delay-time.md b/hints/network-delay-time.md
new file mode 100644
index 000000000..901cefb98
--- /dev/null
+++ b/hints/network-delay-time.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(ElogV)
time and O(V + E)
space, where E
is the number of edges and V
is the number of vertices (nodes).
+
+
+
+
+
+ Hint 1
+
+ As we are given the source node and we need to find the minimum time to reach all nodes, this represents the shortest path from the source node to all nodes. Can you think of a standard algorithm to find the shortest path from a source to a destination? Maybe a heap-based algorithm is helpful.
+
+
+
+
+
+ Hint 2
+
+ We can use Dijkstra's algorithm to find the shortest path from a source to destination. We end up finding the shortest paths from the source to the nodes that we encounter in finding the destination. So, to find shortest path for all nodes from the source, we need to perform Dijkstra's algorithm until the heap in this algorithm becomes empty. How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We use a Min-Heap as we need to find the minimum time. We create an adjacency list for the given times (weighted edges). We also initialize an array dist[]
of size n
(number of nodes) which represents the distance from the source to all nodes, initialized with infinity. We put dist[source] = 0
. Then we continue the algorithm. After the heap becomes empty, if we don't visit any node, we return -1
; otherwise, we return the time.
+
+
\ No newline at end of file
diff --git a/hints/reconstruct-flight-path.md b/hints/reconstruct-flight-path.md
new file mode 100644
index 000000000..43f336c17
--- /dev/null
+++ b/hints/reconstruct-flight-path.md
@@ -0,0 +1,39 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O(ElogE)
time and O(E)
space, where E
is the number of tickets (edges).
+
+
+
+
+
+ Hint 1
+
+ Consider this problem as a graph where airports are the nodes and tickets are the edges. Since we need to utilize all the tickets exactly once, can you think of an algorithm that visits every edge exactly once? Additionally, how do you ensure the smallest lexical order is maintained?
+
+
+
+
+
+ Hint 2
+
+ We build an adjacency list from the given tickets, which represent directed edges. We perform a DFS to construct the result, but we first sort the neighbors' list of each node to ensure the smallest lexical order. Why? Sorting guarantees that during DFS, we visit the node with the smallest lexical order first.
+
+
+
+
+
+ Hint 3
+
+ DFS would be a naive solution, as it takes O(E * V)
time, where E
is the number of tickets (edges) and V
is the number of airports (nodes). In this approach, we traverse from the given source airport JFK
, perform DFS by removing the neighbor, traversing it, and then reinserting it back. Can you think of a better way? Perhaps an advanced algorithm that incorporates DFS might be helpful?
+
+
+
+
+
+ Hint 4
+
+ We can use Hierholzer's algorithm, a modified DFS approach. Instead of appending the node to the result list immediately, we first visit all its neighbors. This results in a post-order traversal. After completing all the DFS calls, we reverse the path to obtain the final path, which is also called Euler's path.
+
+
\ No newline at end of file
diff --git a/hints/redundant-connection.md b/hints/redundant-connection.md
new file mode 100644
index 000000000..cdd3217fe
--- /dev/null
+++ b/hints/redundant-connection.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(V + E)
time and O(V + E)
space, where V
is the number vertices and E
is the number of edges in the graph.
+
+
+
+
+
+ Hint 1
+
+ There will be only one edge that creates the cycle in the given problem. Why? Because the graph is initially acyclic, and a cycle is formed only after adding one extra edge that was not present in the graph initially. Can you think of an algorithm that helps determine whether the current connecting edge forms a cycle? Perhaps a component-oriented algorithm?
+
+
+
+
+
+ Hint 2
+
+ We can use the Union-Find (DSU) algorithm to create the graph from the given edges. While connecting the edges, if we fail to connect any edge, it means this is the redundant edge, and we return it. How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We create an instance of the DSU object and traverse through the given edges. For each edge, we attempt to connect the nodes using the union function. If the union function returns false
, indicating that the current edge forms a cycle, we immediately return that edge.
+
+
\ No newline at end of file
diff --git a/hints/swim-in-rising-water.md b/hints/swim-in-rising-water.md
new file mode 100644
index 000000000..5e098b6f0
--- /dev/null
+++ b/hints/swim-in-rising-water.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O((n^2)logn)
time and O(n^2)
space, where n
is the number of rows or columns of the square matrix.
+
+
+
+
+
+ Hint 1
+
+ Think of this problem as a graph where each cell represents a node. You can move from one cell to its adjacent cell if the time is greater than or equal to the adjacent cell's elevation. Note that swimming does not cost time, but you may need to wait at a cell for the time to reach the required elevation. What do you notice about the path from (0, 0)
to (n - 1, n - 1)
? Perhaps a greedy approach would be useful here.
+
+
+
+
+
+ Hint 2
+
+ We can observe that the maximum elevation value along the path determines the time taken for that path. Therefore, we need to find the path where the maximum elevation is minimized. Can you think of an algorithm to find such a path from the source (0, 0)
to the destination (n - 1, n - 1)
? Perhaps a shortest path algorithm could be useful here.
+
+
+
+
+
+ Hint 3
+
+ We can use Dijkstra's algorithm. We initialize a Min-heap and a matrix with infinity. We run the algorithm starting from the source (0, 0)
, and we track the maximum elevation encountered along the paths. This maximum elevation is used as the key for comparison in Dijkstra's algorithm. If we encounter the destination (n - 1, n - 1)
, we return the maximum elevation of the path that reached the destination.
+
+
\ No newline at end of file
diff --git a/hints/valid-tree.md b/hints/valid-tree.md
new file mode 100644
index 000000000..7e7d37358
--- /dev/null
+++ b/hints/valid-tree.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution as good or better than O(V + E)
time and O(V + E)
space, where V
is the number vertices and E
is the number of edges in the graph.
+
+
+
+
+
+ Hint 1
+
+ According to the definition of a tree, a tree is an undirected graph with no cycles, all the nodes are connected as one component, and any two nodes have exactly one path. Can you think of a recursive algorithm to detect a cycle in the given graph and ensure it is a tree?
+
+
+
+
+
+ Hint 2
+
+ We can use the Depth First Search (DFS) algorithm to detect a cycle in the graph. Since a tree has only one component, we can start the DFS from any node, say node 0
. During the traversal, we recursively visit its neighbors (children). If we encounter any already visited node that is not the parent of the current node, we return false as it indicates a cycle. How would you implement this?
+
+
+
+
+
+ Hint 3
+
+ We start DFS from node 0
, assuming -1
as its parent. We initialize a hash set visit
to track the visited nodes in the graph. During the DFS, we first check if the current node is already in visit
. If it is, we return false, detecting a cycle. Otherwise, we mark the node as visited and perform DFS on its neighbors, skipping the parent node to avoid revisiting it. After all DFS calls, if we have visited all nodes, we return true, as the graph is connected. Otherwise, we return false because a tree must contain all nodes.
+
+
\ No newline at end of file
diff --git a/hints/word-ladder.md b/hints/word-ladder.md
new file mode 100644
index 000000000..efdd32a2c
--- /dev/null
+++ b/hints/word-ladder.md
@@ -0,0 +1,31 @@
+
+
+ Recommended Time & Space Complexity
+
+ You should aim for a solution with O((m ^ 2) * n)
time and O((m ^ 2) * n)
space, where n
is the number of words and m
is the length of the word.
+
+
+
+
+
+ Hint 1
+
+ Consider the given problem in terms of a graph, treating strings as nodes. Think of a way to build edges where two strings have an edge if they differ by a single character. A naive approach would be to consider each pair of strings and check whether an edge can be formed. Can you think of an efficient way? For example, consider a string hot
and think about the strings that can be formed from it by changing a single letter.
+
+
+
+
+
+ Hint 2
+
+ To efficiently build edges, consider transforming each word into intermediate states by replacing one character with a wildcard, like *
. For example, the word hot
can be transformed into *ot
, h*t
, and ho*
. These intermediate states act as "parents" that connect words differing by one character. For instance, *ot
can connect to words like cot
. For each word in the list, generate all possible patterns by replacing each character with *
and store the word as a child of these patterns. We can run a BFS
starting from the beginWord
, visiting other words while avoiding revisiting by using a hash set.
+
+
+
+
+
+ Hint 3
+
+ When visiting a node during BFS, if the word matches the endWord
, we immediately return true
. Otherwise, we generate the pattern words that can be formed from the current word and attempt to visit the words connected to these pattern words. We add only unvisited words to the queue. If we exhaust all possibilities without finding the endWord
, we return false
.
+
+
\ No newline at end of file
From 232acfa353f770d8658edc38eba93dd12bf86978 Mon Sep 17 00:00:00 2001
From: Sri Hari <94112314+Srihari2222@users.noreply.github.com>
Date: Sat, 7 Dec 2024 02:08:52 +0530
Subject: [PATCH 33/67] SriHari: Batch-3/Neetcode-All/Added articles (#3760)
* small changes
* Batch-3/Neetcode-All/Added-articles
* Batch-3/Neetcode-All/Added-articles
* Batch-3/Neetcode-All/Added-articles
* Batch-3/Neetcode-All/Added-articles
* Batch-3/Neetcode-All/Added-articles
* Batch-3/Neetcode-All/Added-articles
* Batch-3/Neetcode-All/Added-articles
---
.../best-time-to-buy-and-sell-stock-ii.md | 458 +++++++
articles/brick-wall.md | 245 ++++
articles/continuous-subarray-sum.md | 177 +++
articles/design-hashmap.md | 365 ++++++
articles/design-hashset.md | 1028 +++++++++++++++
articles/destination-city.md | 253 ++++
articles/find-all-anagrams-in-a-string.md | 581 +++++++++
...ind-all-numbers-disappeared-in-an-array.md | 358 ++++++
...dex-of-the-first-occurrence-in-a-string.md | 633 ++++++++++
...-words-that-can-be-formed-by-characters.md | 391 ++++++
.../first-unique-character-in-a-string.md | 365 ++++++
articles/grid-game.md | 354 ++++++
articles/intersection-of-two-arrays.md | 566 +++++++++
.../largest-3-same-digit-number-in-string.md | 255 ++++
articles/largest-number.md | 188 +++
...-substring-between-two-equal-characters.md | 380 ++++++
articles/longest-common-prefix.md | 4 +-
...um-product-difference-between-two-pairs.md | 255 ++++
...-length-of-two-palindromic-subsequences.md | 854 +++++++++++++
.../maximum-score-after-splitting-a-string.md | 495 ++++++++
...anges-to-make-alternating-binary-string.md | 207 +++
...er-of-swaps-to-make-the-string-balanced.md | 219 ++++
articles/monotonic-array.md | 305 +++++
articles/number-of-good-pairs.md | 221 ++++
...-of-pairs-of-interchangeable-rectangles.md | 364 ++++++
.../number-of-students-unable-to-eat-lunch.md | 348 ++++++
articles/pascals-triangle-ii.md | 375 ++++++
articles/pascals-triangle.md | 6 +-
articles/path-crossing.md | 242 ++++
articles/products-of-array-discluding-self.md | 7 +-
articles/push-dominoes.md | 749 +++++++++++
articles/range-sum-query-immutable.md | 452 +++++++
articles/reconstruct-flight-path.md | 6 +-
...te-characters-to-make-all-strings-equal.md | 228 ++++
articles/redundant-connection.md | 2 +-
articles/set-mismatch.md | 721 +++++++++++
articles/sort-an-array.md | 1105 +++++++++++++++++
articles/sort-colors.md | 437 +++++++
...with-x-elements-greater-than-or-equal-x.md | 506 ++++++++
articles/subarray-sum-equals-k.md | 169 +++
articles/time-needed-to-buy-tickets.md | 329 +++++
...nique-length-3-palindromic-subsequences.md | 863 +++++++++++++
articles/word-pattern.md | 533 ++++++++
43 files changed, 16586 insertions(+), 13 deletions(-)
create mode 100644 articles/best-time-to-buy-and-sell-stock-ii.md
create mode 100644 articles/brick-wall.md
create mode 100644 articles/continuous-subarray-sum.md
create mode 100644 articles/design-hashmap.md
create mode 100644 articles/design-hashset.md
create mode 100644 articles/destination-city.md
create mode 100644 articles/find-all-anagrams-in-a-string.md
create mode 100644 articles/find-all-numbers-disappeared-in-an-array.md
create mode 100644 articles/find-the-index-of-the-first-occurrence-in-a-string.md
create mode 100644 articles/find-words-that-can-be-formed-by-characters.md
create mode 100644 articles/first-unique-character-in-a-string.md
create mode 100644 articles/grid-game.md
create mode 100644 articles/intersection-of-two-arrays.md
create mode 100644 articles/largest-3-same-digit-number-in-string.md
create mode 100644 articles/largest-number.md
create mode 100644 articles/largest-substring-between-two-equal-characters.md
create mode 100644 articles/maximum-product-difference-between-two-pairs.md
create mode 100644 articles/maximum-product-of-the-length-of-two-palindromic-subsequences.md
create mode 100644 articles/maximum-score-after-splitting-a-string.md
create mode 100644 articles/minimum-changes-to-make-alternating-binary-string.md
create mode 100644 articles/minimum-number-of-swaps-to-make-the-string-balanced.md
create mode 100644 articles/monotonic-array.md
create mode 100644 articles/number-of-good-pairs.md
create mode 100644 articles/number-of-pairs-of-interchangeable-rectangles.md
create mode 100644 articles/number-of-students-unable-to-eat-lunch.md
create mode 100644 articles/pascals-triangle-ii.md
create mode 100644 articles/path-crossing.md
create mode 100644 articles/push-dominoes.md
create mode 100644 articles/range-sum-query-immutable.md
create mode 100644 articles/redistribute-characters-to-make-all-strings-equal.md
create mode 100644 articles/set-mismatch.md
create mode 100644 articles/sort-an-array.md
create mode 100644 articles/sort-colors.md
create mode 100644 articles/special-array-with-x-elements-greater-than-or-equal-x.md
create mode 100644 articles/subarray-sum-equals-k.md
create mode 100644 articles/time-needed-to-buy-tickets.md
create mode 100644 articles/unique-length-3-palindromic-subsequences.md
create mode 100644 articles/word-pattern.md
diff --git a/articles/best-time-to-buy-and-sell-stock-ii.md b/articles/best-time-to-buy-and-sell-stock-ii.md
new file mode 100644
index 000000000..e6abb861a
--- /dev/null
+++ b/articles/best-time-to-buy-and-sell-stock-ii.md
@@ -0,0 +1,458 @@
+## 1. Recursion
+
+::tabs-start
+
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ def rec(i, bought):
+ if i == len(prices):
+ return 0
+ res = rec(i + 1, bought)
+ if bought:
+ res = max(res, prices[i] + rec(i + 1, False))
+ else:
+ res = max(res, -prices[i] + rec(i + 1, True))
+ return res
+ return rec(0, False)
+```
+
+```java
+public class Solution {
+ public int maxProfit(int[] prices) {
+ return rec(prices, 0, false);
+ }
+
+ private int rec(int[] prices, int i, boolean 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;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int maxProfit(vector& prices) {
+ return rec(prices, 0, false);
+ }
+
+private:
+ int rec(vector& prices, int i, bool bought) {
+ if (i == prices.size()) {
+ return 0;
+ }
+ int res = rec(prices, i + 1, bought);
+ if (bought) {
+ res = max(res, prices[i] + rec(prices, i + 1, false));
+ } else {
+ res = max(res, -prices[i] + rec(prices, i + 1, true));
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} prices
+ * @return {number}
+ */
+ maxProfit(prices) {
+ const rec = (i, bought) => {
+ if (i === prices.length) {
+ return 0;
+ }
+ let res = rec(i + 1, bought);
+ if (bought) {
+ res = Math.max(res, prices[i] + rec(i + 1, false));
+ } else {
+ res = Math.max(res, -prices[i] + rec(i + 1, true));
+ }
+ return res;
+ };
+ return rec(0, false);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(2 ^ n)$
+* Space complexity: $O(n)$
+
+---
+
+## 2. Dynamic Programming (Top-Down)
+
+::tabs-start
+
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ dp = {}
+
+ def rec(i, bought):
+ if i == len(prices):
+ return 0
+ if (i, bought) in dp:
+ return dp[(i, bought)]
+ res = rec(i + 1, bought)
+ if bought:
+ res = max(res, prices[i] + rec(i + 1, False))
+ else:
+ res = max(res, -prices[i] + rec(i + 1, True))
+ dp[(i, bought)] = res
+ return res
+
+ return rec(0, False)
+```
+
+```java
+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;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int maxProfit(vector& prices) {
+ int n = prices.size();
+ vector> dp(n, vector(2, -1));
+ return rec(prices, 0, 0, dp);
+ }
+
+private:
+ int rec(vector& prices, int i, int bought, vector>& dp) {
+ if (i == prices.size()) {
+ return 0;
+ }
+ if (dp[i][bought] != -1) {
+ return dp[i][bought];
+ }
+ int res = rec(prices, i + 1, bought, dp);
+ if (bought == 1) {
+ res = max(res, prices[i] + rec(prices, i + 1, 0, dp));
+ } else {
+ res = max(res, -prices[i] + rec(prices, i + 1, 1, dp));
+ }
+ dp[i][bought] = res;
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} prices
+ * @return {number}
+ */
+ maxProfit(prices) {
+ const n = prices.length;
+ const dp = Array.from({ length: n }, () => Array(2).fill(-1));
+
+ const rec = (i, bought) => {
+ if (i === n) {
+ return 0;
+ }
+ if (dp[i][bought] !== -1) {
+ return dp[i][bought];
+ }
+ let res = rec(i + 1, bought);
+ if (bought) {
+ res = Math.max(res, prices[i] + rec(i + 1, 0));
+ } else {
+ res = Math.max(res, -prices[i] + rec(i + 1, 1));
+ }
+ dp[i][bought] = res;
+ return res;
+ };
+
+ return rec(0, 0);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 3. Dynamic Programming (Bottom-Up)
+
+::tabs-start
+
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ n = len(prices)
+ dp = [[0] * 2 for _ in range(n + 1)]
+
+ for i in range(n - 1, -1, -1):
+ dp[i][0] = max(dp[i + 1][0], -prices[i] + dp[i + 1][1])
+ dp[i][1] = max(dp[i + 1][1], prices[i] + dp[i + 1][0])
+
+ return dp[0][0]
+```
+
+```java
+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];
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int maxProfit(vector& prices) {
+ int n = prices.size();
+ vector> dp(n + 1, vector(2, 0));
+
+ for (int i = n - 1; i >= 0; i--) {
+ dp[i][0] = max(dp[i + 1][0], -prices[i] + dp[i + 1][1]);
+ dp[i][1] = max(dp[i + 1][1], prices[i] + dp[i + 1][0]);
+ }
+
+ return dp[0][0];
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} prices
+ * @return {number}
+ */
+ maxProfit(prices) {
+ const n = prices.length;
+ const dp = Array.from({ length: n + 1 }, () => Array(2).fill(0));
+
+ for (let 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
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 4. Dynamic Programming (Space Optimized)
+
+::tabs-start
+
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ n = len(prices)
+ next_buy = next_sell = 0
+ cur_buy = cur_sell = 0
+
+ for i in range(n - 1, -1, -1):
+ cur_buy = max(next_buy, -prices[i] + next_sell)
+ cur_sell = max(next_sell, prices[i] + next_buy)
+ next_buy = cur_buy
+ next_sell = cur_sell
+
+ return cur_buy
+```
+
+```java
+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;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int maxProfit(vector& prices) {
+ int nextBuy = 0, nextSell = 0;
+ int curBuy = 0, curSell = 0;
+
+ for (int i = prices.size() - 1; i >= 0; i--) {
+ curBuy = max(nextBuy, -prices[i] + nextSell);
+ curSell = max(nextSell, prices[i] + nextBuy);
+ nextBuy = curBuy;
+ nextSell = curSell;
+ }
+
+ return curBuy;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} prices
+ * @return {number}
+ */
+ maxProfit(prices) {
+ let nextBuy = 0, nextSell = 0;
+ let curBuy = 0, curSell = 0;
+
+ for (let 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
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
+
+---
+
+## 5. Greedy
+
+::tabs-start
+
+```python
+class Solution:
+ def maxProfit(self, prices: List[int]) -> int:
+ profit = 0
+
+ for i in range(1, len(prices)):
+ if prices[i] > prices[i - 1]:
+ profit += (prices[i] - prices[i - 1])
+
+ return profit
+```
+
+```java
+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;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int maxProfit(vector& prices) {
+ int profit = 0;
+ for (int i = 1; i < prices.size(); i++) {
+ if (prices[i] > prices[i - 1]) {
+ profit += (prices[i] - prices[i - 1]);
+ }
+ }
+ return profit;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} prices
+ * @return {number}
+ */
+ maxProfit(prices) {
+ let profit = 0;
+ for (let 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
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
\ No newline at end of file
diff --git a/articles/brick-wall.md b/articles/brick-wall.md
new file mode 100644
index 000000000..991f98ce3
--- /dev/null
+++ b/articles/brick-wall.md
@@ -0,0 +1,245 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def leastBricks(self, wall: List[List[int]]) -> int:
+ n = len(wall)
+ m = 0
+ for brick in wall[0]:
+ m += brick
+
+ gaps = [[] for _ in range(n)]
+ for i in range(n):
+ gap = 0
+ for brick in wall[i]:
+ gap += brick
+ gaps[i].append(gap)
+
+ res = n
+ for line in range(1, m):
+ cuts = 0
+ for i in range(n):
+ if line not in gaps[i]:
+ cuts += 1
+
+ res = min(res, cuts)
+ return res
+```
+
+```java
+public class Solution {
+ public int leastBricks(List> wall) {
+ int n = wall.size();
+ int m = 0;
+ for (int brick : wall.get(0)) {
+ m += brick;
+ }
+
+ List> gaps = new ArrayList<>();
+ for (int i = 0; i < n; i++) {
+ gaps.add(new ArrayList<>());
+ int gap = 0;
+ for (int brick : wall.get(i)) {
+ gap += brick;
+ gaps.get(i).add(gap);
+ }
+ }
+
+ int res = n;
+ for (int line = 1; line < m; line++) {
+ int cuts = 0;
+ for (int i = 0; i < n; i++) {
+ if (!gaps.get(i).contains(line)) {
+ cuts++;
+ }
+ }
+ res = Math.min(res, cuts);
+ }
+
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int leastBricks(vector>& wall) {
+ int n = wall.size();
+ int m = 0;
+ for (int brick : wall[0]) {
+ m += brick;
+ }
+
+ vector> gaps(n);
+ for (int i = 0; i < n; i++) {
+ int gap = 0;
+ for (int brick : wall[i]) {
+ gap += brick;
+ gaps[i].push_back(gap);
+ }
+ }
+
+ int res = n;
+ for (int line = 1; line < m; line++) {
+ int cuts = 0;
+ for (int i = 0; i < n; i++) {
+ if (find(gaps[i].begin(), gaps[i].end(), line) == gaps[i].end()) {
+ cuts++;
+ }
+ }
+ res = min(res, cuts);
+ }
+
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[][]} wall
+ * @return {number}
+ */
+ leastBricks(wall) {
+ const n = wall.length;
+ let m = 0;
+ for (const brick of wall[0]) {
+ m += brick;
+ }
+
+ const gaps = Array.from({ length: n }, () => []);
+ for (let i = 0; i < n; i++) {
+ let gap = 0;
+ for (const brick of wall[i]) {
+ gap += brick;
+ gaps[i].push(gap);
+ }
+ }
+
+ let res = n;
+ for (let line = 1; line < m; line++) {
+ let cuts = 0;
+ for (let i = 0; i < n; i++) {
+ if (!gaps[i].includes(line)) {
+ cuts++;
+ }
+ }
+ res = Math.min(res, cuts);
+ }
+
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(m * n * g)$
+* Space complexity: $O(n * g)$
+
+> Where $m$ is the sum of widths of the bricks in the first row, $n$ is the number of rows and $g$ is the average number of gaps in each row.
+
+---
+
+## 2. Hash Map
+
+::tabs-start
+
+```python
+class Solution:
+ def leastBricks(self, wall: List[List[int]]) -> int:
+ countGap = {0: 0}
+
+ for r in wall:
+ total = 0
+ for i in range(len(r) - 1):
+ total += r[i]
+ countGap[total] = 1 + countGap.get(total, 0)
+
+ return len(wall) - max(countGap.values())
+```
+
+```java
+public class Solution {
+ public int leastBricks(List> wall) {
+ HashMap countGap = new HashMap<>();
+ countGap.put(0, 0);
+
+ for (List row : wall) {
+ int total = 0;
+ for (int i = 0; i < row.size() - 1; i++) {
+ total += row.get(i);
+ countGap.put(total, countGap.getOrDefault(total, 0) + 1);
+ }
+ }
+
+ int maxGaps = 0;
+ for (int count : countGap.values()) {
+ maxGaps = Math.max(maxGaps, count);
+ }
+
+ return wall.size() - maxGaps;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int leastBricks(vector>& wall) {
+ unordered_map countGap;
+ countGap[0] = 0;
+
+ for (const auto& row : wall) {
+ int total = 0;
+ for (size_t i = 0; i < row.size() - 1; ++i) {
+ total += row[i];
+ countGap[total]++;
+ }
+ }
+
+ int maxGaps = 0;
+ for (const auto& [key, value] : countGap) {
+ maxGaps = max(maxGaps, value);
+ }
+
+ return wall.size() - maxGaps;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[][]} wall
+ * @return {number}
+ */
+ leastBricks(wall) {
+ const countGap = new Map();
+ countGap.set(0, 0);
+ for (const row of wall) {
+ let total = 0;
+ for (let i = 0; i < row.length - 1; i++) {
+ total += row[i];
+ countGap.set(total, (countGap.get(total) || 0) + 1);
+ }
+ }
+ return wall.length - Math.max(...countGap.values());
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(N)$
+* Space complexity: $O(g)$
+
+> Where $N$ is the total number of bricks in the wall and $g$ is the total number of gaps in all the rows.
\ No newline at end of file
diff --git a/articles/continuous-subarray-sum.md b/articles/continuous-subarray-sum.md
new file mode 100644
index 000000000..a6509f498
--- /dev/null
+++ b/articles/continuous-subarray-sum.md
@@ -0,0 +1,177 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def checkSubarraySum(self, nums: List[int], k: int) -> bool:
+ for i in range(len(nums) - 1):
+ sum = nums[i]
+ for j in range(i + 1, len(nums)):
+ sum += nums[j]
+ if sum % k == 0:
+ return True
+ return False
+```
+
+```java
+public class Solution {
+ public boolean checkSubarraySum(int[] nums, int k) {
+ for (int i = 0; i < nums.length - 1; i++) {
+ int sum = nums[i];
+ for (int j = i + 1; j < nums.length; j++) {
+ sum += nums[j];
+ if (sum % k == 0) return true;
+ }
+ }
+ return false;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool checkSubarraySum(vector& nums, int k) {
+ for (int i = 0; i < nums.size() - 1; i++) {
+ int sum = nums[i];
+ for (int j = i + 1; j < nums.size(); j++) {
+ sum += nums[j];
+ if (sum % k == 0) return true;
+ }
+ }
+ return false;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {boolean}
+ */
+ checkSubarraySum(nums, k) {
+ for (let i = 0; i < nums.length - 1; i++) {
+ let sum = nums[i];
+ for (let j = i + 1; j < nums.length; j++) {
+ sum += nums[j];
+ if (sum % k == 0) return true;
+ }
+ }
+ return false;
+ }
+}
+```
+
+::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 checkSubarraySum(self, nums: List[int], k: int) -> bool:
+ remainder = {0: -1} # remainder -> end index
+ total = 0
+
+ for i, num in enumerate(nums):
+ total += num
+ r = total % k
+ if r not in remainder:
+ remainder[r] = i
+ elif i - remainder[r] > 1:
+ return True
+
+ return False
+```
+
+```java
+public class Solution {
+ public boolean checkSubarraySum(int[] nums, int k) {
+ HashMap remainder = new HashMap<>();
+ remainder.put(0, -1);
+ int total = 0;
+
+ for (int i = 0; i < nums.length; i++) {
+ total += nums[i];
+ int r = total % k;
+ if (!remainder.containsKey(r)) {
+ remainder.put(r, i);
+ } else if (i - remainder.get(r) > 1) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ bool checkSubarraySum(vector& nums, int k) {
+ unordered_map remainder;
+ remainder[0] = -1;
+ int total = 0;
+
+ for (int i = 0; i < nums.size(); i++) {
+ total += nums[i];
+ int r = total % k;
+ if (remainder.find(r) == remainder.end()) {
+ remainder[r] = i;
+ } else if (i - remainder[r] > 1) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {boolean}
+ */
+ checkSubarraySum(nums, k) {
+ const remainder = new Map();
+ remainder.set(0, -1);
+ let total = 0;
+
+ for (let i = 0; i < nums.length; i++) {
+ total += nums[i];
+ let r = total % k;
+ if (!remainder.has(r)) {
+ remainder.set(r, i);
+ } else if (i - remainder.get(r) > 1) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(k)$
+
+> Where $n$ is the size of the array $nums$ and $k$ is the number that a subarray sum needs to be multiple of.
\ No newline at end of file
diff --git a/articles/design-hashmap.md b/articles/design-hashmap.md
new file mode 100644
index 000000000..4a64bdee1
--- /dev/null
+++ b/articles/design-hashmap.md
@@ -0,0 +1,365 @@
+## 1. Array
+
+::tabs-start
+
+```python
+class MyHashMap:
+
+ def __init__(self):
+ self.map = [-1] * 1000001
+
+ def put(self, key: int, value: int) -> None:
+ self.map[key] = value
+
+ def get(self, key: int) -> int:
+ return self.map[key]
+
+ def remove(self, key: int) -> None:
+ self.map[key] = -1
+```
+
+```java
+public class MyHashMap {
+ private int[] map;
+
+ public MyHashMap() {
+ map = new int[1000001];
+ Arrays.fill(map, -1);
+ }
+
+ public void put(int key, int value) {
+ map[key] = value;
+ }
+
+ public int get(int key) {
+ return map[key];
+ }
+
+ public void remove(int key) {
+ map[key] = -1;
+ }
+}
+```
+
+```cpp
+class MyHashMap {
+private:
+ vector map;
+
+public:
+ MyHashMap() : map(1000001, -1) {}
+
+ void put(int key, int value) {
+ map[key] = value;
+ }
+
+ int get(int key) {
+ return map[key];
+ }
+
+ void remove(int key) {
+ map[key] = -1;
+ }
+};
+```
+
+```javascript
+class MyHashMap {
+ constructor() {
+ this.map = new Array(1000001).fill(-1);
+ }
+
+ /**
+ * @param {number} key
+ * @param {number} value
+ * @return {void}
+ */
+ put(key, value) {
+ this.map[key] = value;
+ }
+
+ /**
+ * @param {number} key
+ * @return {number}
+ */
+ get(key) {
+ return this.map[key];
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ remove(key) {
+ this.map[key] = -1;
+ }
+}
+
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(1)$ for each function call.
+* Space complexity: $O(1000000)$ since the key is in the range $[0, 1000000]$.
+
+---
+
+## 2. Linked List
+
+::tabs-start
+
+```python
+class ListNode:
+ def __init__(self, key = -1, val = -1, next = None):
+ self.key = key
+ self.val = val
+ self.next = next
+
+class MyHashMap:
+
+ def __init__(self):
+ self.map = [ListNode() for _ in range(1000)]
+
+ def hash(self, key: int) -> int:
+ return key % len(self.map)
+
+ def put(self, key: int, value: int) -> None:
+ cur = self.map[self.hash(key)]
+ while cur.next:
+ if cur.next.key == key:
+ cur.next.val = value
+ return
+ cur = cur.next
+ cur.next = ListNode(key, value)
+
+ def get(self, key: int) -> int:
+ cur = self.map[self.hash(key)].next
+ while cur:
+ if cur.key == key:
+ return cur.val
+ cur = cur.next
+ return -1
+
+ def remove(self, key: int) -> None:
+ cur = self.map[self.hash(key)]
+ while cur.next:
+ if cur.next.key == key:
+ cur.next = cur.next.next
+ return
+ cur = cur.next
+```
+
+```java
+class ListNode {
+ int key, val;
+ ListNode next;
+
+ public ListNode(int key, int val, ListNode next) {
+ this.key = key;
+ this.val = val;
+ this.next = next;
+ }
+
+ public ListNode() {
+ this(-1, -1, null);
+ }
+}
+
+public class MyHashMap {
+ private ListNode[] map;
+
+ public MyHashMap() {
+ map = new ListNode[1000];
+ for (int i = 0; i < 1000; i++) {
+ map[i] = new ListNode();
+ }
+ }
+
+ private int hash(int key) {
+ return key % map.length;
+ }
+
+ public void put(int key, int value) {
+ ListNode cur = map[hash(key)];
+ while (cur.next != null) {
+ if (cur.next.key == key) {
+ cur.next.val = value;
+ return;
+ }
+ cur = cur.next;
+ }
+ cur.next = new ListNode(key, value, null);
+ }
+
+ public int get(int key) {
+ ListNode cur = map[hash(key)].next;
+ while (cur != null) {
+ if (cur.key == key) {
+ return cur.val;
+ }
+ cur = cur.next;
+ }
+ return -1;
+ }
+
+ public void remove(int key) {
+ ListNode cur = map[hash(key)];
+ while (cur.next != null) {
+ if (cur.next.key == key) {
+ cur.next = cur.next.next;
+ return;
+ }
+ cur = cur.next;
+ }
+ }
+}
+```
+
+```cpp
+class MyHashMap {
+private:
+ struct ListNode {
+ int key, val;
+ ListNode* next;
+
+ ListNode(int key = -1, int val = -1, ListNode* next = nullptr)
+ : key(key), val(val), next(next) {}
+ };
+
+ vector map;
+ int hash(int key) {
+ return key % map.size();
+ }
+
+public:
+ MyHashMap() {
+ map.resize(1000);
+ for (auto& bucket : map) {
+ bucket = new ListNode(0);
+ }
+ }
+
+ void put(int key, int value) {
+ ListNode* cur = map[hash(key)];
+ while (cur->next) {
+ if (cur->next->key == key) {
+ cur->next->val = value;
+ return;
+ }
+ cur = cur->next;
+ }
+ cur->next = new ListNode(key, value);
+ }
+
+ int get(int key) {
+ ListNode* cur = map[hash(key)]->next;
+ while (cur) {
+ if (cur->key == key) {
+ return cur->val;
+ }
+ cur = cur->next;
+ }
+ return -1;
+ }
+
+ void remove(int key) {
+ ListNode* cur = map[hash(key)];
+ while (cur->next) {
+ if (cur->next->key == key) {
+ ListNode* tmp = cur->next;
+ cur->next = cur->next->next;
+ delete tmp;
+ return;
+ }
+ cur = cur->next;
+ }
+ }
+};
+```
+
+```javascript
+class ListNode {
+ /**
+ * @param {number} key
+ * @param {number} val
+ * @param {ListNode} next
+ */
+ constructor(key = -1, val = -1, next = null) {
+ this.key = key;
+ this.val = val;
+ this.next = next;
+ }
+}
+
+class MyHashMap {
+ constructor() {
+ this.map = Array.from({ length: 1000 }, () => new ListNode());
+ }
+
+ /**
+ * @param {number} key
+ * @return {number}
+ */
+ hash(key) {
+ return key % this.map.length;
+ }
+
+ /**
+ * @param {number} key
+ * @param {number} value
+ * @return {void}
+ */
+ put(key, value) {
+ let cur = this.map[this.hash(key)];
+ while (cur.next) {
+ if (cur.next.key === key) {
+ cur.next.val = value;
+ return;
+ }
+ cur = cur.next;
+ }
+ cur.next = new ListNode(key, value);
+ }
+
+ /**
+ * @param {number} key
+ * @return {number}
+ */
+ get(key) {
+ let cur = this.map[this.hash(key)].next;
+ while (cur) {
+ if (cur.key === key) {
+ return cur.val;
+ }
+ cur = cur.next;
+ }
+ return -1;
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ remove(key) {
+ let cur = this.map[this.hash(key)];
+ while (cur.next) {
+ if (cur.next.key === key) {
+ cur.next = cur.next.next;
+ return;
+ }
+ cur = cur.next;
+ }
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(\frac{n}{k})$ for each function call.
+* Space complexity: $O(k + m)$
+
+> Where $n$ is the number of keys, $k$ is the size of the map ($1000$) and $m$ is the number of unique keys.
\ No newline at end of file
diff --git a/articles/design-hashset.md b/articles/design-hashset.md
new file mode 100644
index 000000000..9ee3f0884
--- /dev/null
+++ b/articles/design-hashset.md
@@ -0,0 +1,1028 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class MyHashSet:
+
+ def __init__(self):
+ self.data = []
+
+ def add(self, key: int) -> None:
+ if key not in self.data:
+ self.data.append(key)
+
+ def remove(self, key: int) -> None:
+ if key in self.data:
+ self.data.remove(key)
+
+ def contains(self, key: int) -> bool:
+ return key in self.data
+```
+
+```java
+public class MyHashSet {
+ private List data;
+
+ public MyHashSet() {
+ data = new ArrayList<>();
+ }
+
+ public void add(int key) {
+ if (!data.contains(key)) {
+ data.add(key);
+ }
+ }
+
+ public void remove(int key) {
+ data.remove(Integer.valueOf(key));
+ }
+
+ public boolean contains(int key) {
+ return data.contains(key);
+ }
+}
+```
+
+```cpp
+class MyHashSet {
+private:
+ vector data;
+public:
+ MyHashSet() {}
+
+ void add(int key) {
+ if (find(data.begin(), data.end(), key) == data.end()) {
+ data.push_back(key);
+ }
+ }
+
+ void remove(int key) {
+ auto it = find(data.begin(), data.end(), key);
+ if (it != data.end()) {
+ data.erase(it);
+ }
+ }
+
+ bool contains(int key) {
+ return find(data.begin(), data.end(), key) != data.end();
+ }
+};
+```
+
+```javascript
+class MyHashSet {
+ constructor() {
+ this.data = [];
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ add(key) {
+ if (!this.data.includes(key)) {
+ this.data.push(key);
+ }
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ remove(key) {
+ const index = this.data.indexOf(key);
+ if (index !== -1) {
+ this.data.splice(index, 1);
+ }
+ }
+
+ /**
+ * @param {number} key
+ * @return {boolean}
+ */
+ contains(key) {
+ return this.data.includes(key);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$ for each function call.
+* Space complexity: $O(n)$
+
+---
+
+## 2. Boolean Array
+
+::tabs-start
+
+```python
+class MyHashSet:
+
+ def __init__(self):
+ self.data = [False] * 1000001
+
+ def add(self, key: int) -> None:
+ self.data[key] = True
+
+ def remove(self, key: int) -> None:
+ self.data[key] = False
+
+ def contains(self, key: int) -> bool:
+ return self.data[key]
+```
+
+```java
+public class MyHashSet {
+ private boolean[] data;
+
+ public MyHashSet() {
+ data = new boolean[1000001];
+ }
+
+ public void add(int key) {
+ data[key] = true;
+ }
+
+ public void remove(int key) {
+ data[key] = false;
+ }
+
+ public boolean contains(int key) {
+ return data[key];
+ }
+}
+```
+
+```cpp
+class MyHashSet {
+private:
+ vector data;
+public:
+ MyHashSet() : data(1000001, false) {}
+
+ void add(int key) {
+ data[key] = true;
+ }
+
+ void remove(int key) {
+ data[key] = false;
+ }
+
+ bool contains(int key) {
+ return data[key];
+ }
+};
+```
+
+```javascript
+class MyHashSet {
+ constructor() {
+ this.data = new Array(1000001).fill(false);
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ add(key) {
+ this.data[key] = true;
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ remove(key) {
+ this.data[key] = false;
+ }
+
+ /**
+ * @param {number} key
+ * @return {boolean}
+ */
+ contains(key) {
+ return this.data[key];
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(1)$ for each function call.
+* Space complexity: $O(1000000)$ since the key is in the range $[0, 1000000]$.
+
+---
+
+## 3. Linked List
+
+::tabs-start
+
+```python
+class ListNode:
+ def __init__(self, key: int):
+ self.key = key
+ self.next = None
+
+class MyHashSet:
+
+ def __init__(self):
+ self.set = [ListNode(0) for _ in range(10**4)]
+
+ def add(self, key: int) -> None:
+ cur = self.set[key % len(self.set)]
+ while cur.next:
+ if cur.next.key == key:
+ return
+ cur = cur.next
+ cur.next = ListNode(key)
+
+ def remove(self, key: int) -> None:
+ cur = self.set[key % len(self.set)]
+ while cur.next:
+ if cur.next.key == key:
+ cur.next = cur.next.next
+ return
+ cur = cur.next
+
+ def contains(self, key: int) -> bool:
+ cur = self.set[key % len(self.set)]
+ while cur.next:
+ if cur.next.key == key:
+ return True
+ cur = cur.next
+ return False
+```
+
+```java
+public class MyHashSet {
+
+ private static class ListNode {
+ int key;
+ ListNode next;
+
+ ListNode(int key) {
+ this.key = key;
+ }
+ }
+
+ private final ListNode[] set;
+
+ public MyHashSet() {
+ set = new ListNode[10000];
+ for (int i = 0; i < set.length; i++) {
+ set[i] = new ListNode(0);
+ }
+ }
+
+ public void add(int key) {
+ ListNode cur = set[key % set.length];
+ while (cur.next != null) {
+ if (cur.next.key == key) {
+ return;
+ }
+ cur = cur.next;
+ }
+ cur.next = new ListNode(key);
+ }
+
+ public void remove(int key) {
+ ListNode cur = set[key % set.length];
+ while (cur.next != null) {
+ if (cur.next.key == key) {
+ cur.next = cur.next.next;
+ return;
+ }
+ cur = cur.next;
+ }
+ }
+
+ public boolean contains(int key) {
+ ListNode cur = set[key % set.length];
+ while (cur.next != null) {
+ if (cur.next.key == key) {
+ return true;
+ }
+ cur = cur.next;
+ }
+ return false;
+ }
+}
+```
+
+```cpp
+class MyHashSet {
+private:
+ struct ListNode {
+ int key;
+ ListNode* next;
+ ListNode(int k) : key(k), next(nullptr) {}
+ };
+
+ vector set;
+
+ int hash(int key) {
+ return key % set.size();
+ }
+
+public:
+ MyHashSet() {
+ set.resize(10000);
+ for (auto& bucket : set) {
+ bucket = new ListNode(0);
+ }
+ }
+
+ void add(int key) {
+ ListNode* cur = set[hash(key)];
+ while (cur->next) {
+ if (cur->next->key == key) {
+ return;
+ }
+ cur = cur->next;
+ }
+ cur->next = new ListNode(key);
+ }
+
+ void remove(int key) {
+ ListNode* cur = set[hash(key)];
+ while (cur->next) {
+ if (cur->next->key == key) {
+ ListNode* temp = cur->next;
+ cur->next = temp->next;
+ delete temp;
+ return;
+ }
+ cur = cur->next;
+ }
+ }
+
+ bool contains(int key) {
+ ListNode* cur = set[hash(key)];
+ while (cur->next) {
+ if (cur->next->key == key) {
+ return true;
+ }
+ cur = cur->next;
+ }
+ return false;
+ }
+};
+```
+
+```javascript
+class ListNode {
+ /**
+ * @param {number} key
+ */
+ constructor(key) {
+ this.key = key;
+ this.next = null;
+ }
+}
+
+class MyHashSet {
+ constructor() {
+ this.set = Array.from({ length: 10000 }, () => new ListNode(0));
+ }
+
+ /**
+ * @param {number} key
+ * @return {number}
+ */
+ hash(key) {
+ return key % this.set.length;
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ add(key) {
+ let cur = this.set[this.hash(key)];
+ while (cur.next) {
+ if (cur.next.key === key) {
+ return;
+ }
+ cur = cur.next;
+ }
+ cur.next = new ListNode(key);
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ remove(key) {
+ let cur = this.set[this.hash(key)];
+ while (cur.next) {
+ if (cur.next.key === key) {
+ cur.next = cur.next.next;
+ return;
+ }
+ cur = cur.next;
+ }
+ }
+
+ /**
+ * @param {number} key
+ * @return {boolean}
+ */
+ contains(key) {
+ let cur = this.set[this.hash(key)];
+ while (cur.next) {
+ if (cur.next.key === key) {
+ return true;
+ }
+ cur = cur.next;
+ }
+ return false;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(\frac{n}{k})$ for each function call.
+* Space complexity: $O(k + m)$
+
+> Where $n$ is the number of keys, $k$ is the size of the set ($10000$) and $m$ is the number of unique keys.
+
+---
+
+## 4. Binary Search Tree
+
+::tabs-start
+
+```python
+class TreeNode:
+ def __init__(self, key):
+ self.key = key
+ self.left = None
+ self.right = None
+
+class BST:
+ def __init__(self):
+ self.root = None
+
+ def insert(self, root, key):
+ if not root:
+ return TreeNode(key)
+ if key < root.key:
+ root.left = self.insert(root.left, key)
+ elif key > root.key:
+ root.right = self.insert(root.right, key)
+ return root
+
+ def delete(self, root, key):
+ if not root:
+ return None
+ if key < root.key:
+ root.left = self.delete(root.left, key)
+ elif key > root.key:
+ root.right = self.delete(root.right, key)
+ else:
+ if not root.left:
+ return root.right
+ if not root.right:
+ return root.left
+ temp = self.minValueNode(root.right)
+ root.key = temp.key
+ root.right = self.delete(root.right, temp.key)
+ return root
+
+ def minValueNode(self, root):
+ while root.left:
+ root = root.left
+ return root
+
+ def search(self, root, key):
+ if not root:
+ return False
+ if key == root.key:
+ return True
+ elif key < root.key:
+ return self.search(root.left, key)
+ else:
+ return self.search(root.right, key)
+
+ def add(self, key):
+ self.root = self.insert(self.root, key)
+
+ def remove(self, key):
+ self.root = self.delete(self.root, key)
+
+ def contains(self, key):
+ return self.search(self.root, key)
+
+class MyHashSet:
+ def __init__(self):
+ self.size = 10000
+ self.buckets = [BST() for _ in range(self.size)]
+
+ def _hash(self, key):
+ return key % self.size
+
+ def add(self, key: int) -> None:
+ idx = self._hash(key)
+ if not self.contains(key):
+ self.buckets[idx].add(key)
+
+ def remove(self, key: int) -> None:
+ idx = self._hash(key)
+ self.buckets[idx].remove(key)
+
+ def contains(self, key: int) -> bool:
+ idx = self._hash(key)
+ return self.buckets[idx].contains(key)
+```
+
+```java
+class TreeNode {
+ int key;
+ TreeNode left, right;
+
+ TreeNode(int key) {
+ this.key = key;
+ }
+}
+
+class BST {
+ private TreeNode root;
+
+ private TreeNode insert(TreeNode node, int key) {
+ if (node == null) return new TreeNode(key);
+ if (key < node.key) node.left = insert(node.left, key);
+ else if (key > node.key) node.right = insert(node.right, key);
+ return node;
+ }
+
+ private TreeNode delete(TreeNode node, int key) {
+ if (node == null) return null;
+ if (key < node.key) node.left = delete(node.left, key);
+ else if (key > node.key) node.right = delete(node.right, key);
+ else {
+ if (node.left == null) return node.right;
+ if (node.right == null) return node.left;
+ TreeNode temp = minValueNode(node.right);
+ node.key = temp.key;
+ node.right = delete(node.right, temp.key);
+ }
+ return node;
+ }
+
+ private TreeNode minValueNode(TreeNode node) {
+ while (node.left != null) node = node.left;
+ return node;
+ }
+
+ private boolean search(TreeNode node, int key) {
+ if (node == null) return false;
+ if (key == node.key) return true;
+ return key < node.key ? search(node.left, key) : search(node.right, key);
+ }
+
+ public void add(int key) {
+ root = insert(root, key);
+ }
+
+ public void remove(int key) {
+ root = delete(root, key);
+ }
+
+ public boolean contains(int key) {
+ return search(root, key);
+ }
+}
+
+public class MyHashSet {
+ private final int size = 10000;
+ private BST[] buckets;
+
+ public MyHashSet() {
+ buckets = new BST[size];
+ for (int i = 0; i < size; i++) {
+ buckets[i] = new BST();
+ }
+ }
+
+ private int hash(int key) {
+ return key % size;
+ }
+
+ public void add(int key) {
+ int idx = hash(key);
+ if (!buckets[idx].contains(key)) {
+ buckets[idx].add(key);
+ }
+ }
+
+ public void remove(int key) {
+ int idx = hash(key);
+ buckets[idx].remove(key);
+ }
+
+ public boolean contains(int key) {
+ int idx = hash(key);
+ return buckets[idx].contains(key);
+ }
+}
+```
+
+```cpp
+class BST {
+private:
+ struct TreeNode {
+ int key;
+ TreeNode* left;
+ TreeNode* right;
+ TreeNode(int k) : key(k), left(nullptr), right(nullptr) {}
+ };
+
+ TreeNode* insert(TreeNode* root, int key) {
+ if (!root) return new TreeNode(key);
+ if (key < root->key)
+ root->left = insert(root->left, key);
+ else if (key > root->key)
+ root->right = insert(root->right, key);
+ return root;
+ }
+
+ TreeNode* deleteNode(TreeNode* root, int key) {
+ if (!root) return nullptr;
+ if (key < root->key)
+ root->left = deleteNode(root->left, key);
+ else if (key > root->key)
+ root->right = deleteNode(root->right, key);
+ else {
+ if (!root->left) {
+ TreeNode* temp = root->right;
+ delete root;
+ return temp;
+ }
+ if (!root->right) {
+ TreeNode* temp = root->left;
+ delete root;
+ return temp;
+ }
+ TreeNode* temp = minValueNode(root->right);
+ root->key = temp->key;
+ root->right = deleteNode(root->right, temp->key);
+ }
+ return root;
+ }
+
+ TreeNode* minValueNode(TreeNode* root) {
+ while (root->left) root = root->left;
+ return root;
+ }
+
+ bool search(TreeNode* root, int key) {
+ if (!root) return false;
+ if (key == root->key) return true;
+ return key < root->key ? search(root->left, key) : search(root->right, key);
+ }
+
+ TreeNode* root;
+
+public:
+ BST() : root(nullptr) {}
+
+ void add(int key) {
+ root = insert(root, key);
+ }
+
+ void remove(int key) {
+ root = deleteNode(root, key);
+ }
+
+ bool contains(int key) {
+ return search(root, key);
+ }
+};
+
+class MyHashSet {
+private:
+ const int size = 10000;
+ vector buckets;
+
+ int hash(int key) {
+ return key % size;
+ }
+
+public:
+ MyHashSet() : buckets(size) {}
+
+ void add(int key) {
+ int idx = hash(key);
+ if (!contains(key)) {
+ buckets[idx].add(key);
+ }
+ }
+
+ void remove(int key) {
+ int idx = hash(key);
+ buckets[idx].remove(key);
+ }
+
+ bool contains(int key) {
+ int idx = hash(key);
+ return buckets[idx].contains(key);
+ }
+};
+```
+
+```javascript
+class TreeNode {
+ /**
+ * @param {number} key
+ */
+ constructor(key) {
+ this.key = key;
+ this.left = null;
+ this.right = null;
+ }
+}
+
+class BST {
+ constructor() {
+ this.root = null;
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ add(key) {
+ this.root = this._insert(this.root, key);
+ }
+
+ /**
+ * @param {TreeNode} node
+ * @param {number} key
+ * @return {TreeNode}
+ */
+ _insert(node, key) {
+ if (!node) return new TreeNode(key);
+ if (key < node.key) node.left = this._insert(node.left, key);
+ else if (key > node.key) node.right = this._insert(node.right, key);
+ return node;
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ remove(key) {
+ this.root = this._deleteNode(this.root, key);
+ }
+
+ /**
+ * @param {TreeNode} node
+ * @param {number} key
+ * @return {TreeNode}
+ */
+ _deleteNode(node, key) {
+ if (!node) return null;
+ if (key < node.key) node.left = this._deleteNode(node.left, key);
+ else if (key > node.key) node.right = this._deleteNode(node.right, key);
+ else {
+ if (!node.left) return node.right;
+ if (!node.right) return node.left;
+ let minNode = this._minValueNode(node.right);
+ node.key = minNode.key;
+ node.right = this._deleteNode(node.right, minNode.key);
+ }
+ return node;
+ }
+
+ /**
+ * @param {TreeNode} node
+ * @return {TreeNode}
+ */
+ _minValueNode(node) {
+ while (node.left) node = node.left;
+ return node;
+ }
+
+ /**
+ * @param {number} key
+ * @return {boolean}
+ */
+ contains(key) {
+ return this._search(this.root, key);
+ }
+
+ /**
+ * @param {TreeNode} node
+ * @param {number} key
+ * @return {boolean}
+ */
+ _search(node, key) {
+ if (!node) return false;
+ if (key === node.key) return true;
+ if (key < node.key) return this._search(node.left, key);
+ return this._search(node.right, key);
+ }
+}
+
+class MyHashSet {
+ constructor() {
+ this.size = 10000;
+ this.buckets = Array.from({ length: this.size }, () => new BST());
+ }
+
+ _hash(key) {
+ return key % this.size;
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ add(key) {
+ const idx = this._hash(key);
+ if (!this.buckets[idx].contains(key)) {
+ this.buckets[idx].add(key);
+ }
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ remove(key) {
+ const idx = this._hash(key);
+ this.buckets[idx].remove(key);
+ }
+
+ /**
+ * @param {number} key
+ * @return {boolean}
+ */
+ contains(key) {
+ const idx = this._hash(key);
+ return this.buckets[idx].contains(key);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(\log (\frac{n}{k}))$ in average case, $O(\frac{n}{k})$ in worst case for each function call.
+* Space complexity: $O(k + m)$
+
+> Where $n$ is the number of keys, $k$ is the size of the set ($10000$) and $m$ is the number of unique keys.
+
+---
+
+## 5. Bit Manipulation
+
+::tabs-start
+
+```python
+class MyHashSet:
+
+ def __init__(self):
+ # key is in the range [1, 1000000]
+ # 31251 * 32 = 1000032
+ self.set = [0] * 31251
+
+ def add(self, key: int) -> None:
+ self.set[key // 32] |= self.getMask(key)
+
+ def remove(self, key: int) -> None:
+ if self.contains(key):
+ self.set[key // 32] ^= self.getMask(key)
+
+ def contains(self, key: int) -> bool:
+ return self.set[key // 32] & self.getMask(key) != 0
+
+ def getMask(self, key: int) -> int:
+ return 1 << (key % 32)
+```
+
+```java
+public class MyHashSet {
+ private int[] set;
+
+ public MyHashSet() {
+ // key is in the range [1, 1000000]
+ // 31251 * 32 = 1000032
+ set = new int[31251];
+ }
+
+ public void add(int key) {
+ set[key / 32] |= getMask(key);
+ }
+
+ public void remove(int key) {
+ if (contains(key)) {
+ set[key / 32] ^= getMask(key);
+ }
+ }
+
+ public boolean contains(int key) {
+ return (set[key / 32] & getMask(key)) != 0;
+ }
+
+ private int getMask(int key) {
+ return 1 << (key % 32);
+ }
+}
+```
+
+```cpp
+class MyHashSet {
+private:
+ int set[31251];
+
+ int getMask(int key) {
+ return 1 << (key % 32);
+ }
+
+public:
+ MyHashSet() {
+ // key is in the range [1, 1000000]
+ // 31251 * 32 = 1000032
+ memset(set, 0, sizeof(set));
+ }
+
+ void add(int key) {
+ set[key / 32] |= getMask(key);
+ }
+
+ void remove(int key) {
+ if (contains(key)) {
+ set[key / 32] ^= getMask(key);
+ }
+ }
+
+ bool contains(int key) {
+ return (set[key / 32] & getMask(key)) != 0;
+ }
+};
+```
+
+```javascript
+class MyHashSet {
+ constructor() {
+ // key is in the range [1, 1000000]
+ // 31251 * 32 = 1000032
+ this.set = new Array(31251).fill(0);
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ add(key) {
+ this.set[Math.floor(key / 32)] |= this.getMask(key);
+ }
+
+ /**
+ * @param {number} key
+ * @return {void}
+ */
+ remove(key) {
+ if (this.contains(key)) {
+ this.set[Math.floor(key / 32)] ^= this.getMask(key);
+ }
+ }
+
+ /**
+ * @param {number} key
+ * @return {boolean}
+ */
+ contains(key) {
+ return (this.set[Math.floor(key / 32)] & this.getMask(key)) !== 0;
+ }
+
+ /**
+ * @param {number} key
+ * @return {number}
+ */
+ getMask(key) {
+ return 1 << (key % 32);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(1)$ for each function call.
+* Space complexity: $O(k)$
+
+> Where $k$ is the size of the set $(31251)$.
\ No newline at end of file
diff --git a/articles/destination-city.md b/articles/destination-city.md
new file mode 100644
index 000000000..0dc585b2b
--- /dev/null
+++ b/articles/destination-city.md
@@ -0,0 +1,253 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def destCity(self, paths: List[List[str]]) -> str:
+ for i in range(len(paths)):
+ flag = True
+ for j in range(len(paths)):
+ if paths[i][1] == paths[j][0]:
+ flag = False
+ break
+ if flag:
+ return paths[i][1]
+ return ""
+```
+
+```java
+public class Solution {
+ public String destCity(List> paths) {
+ for (int i = 0; i < paths.size(); i++) {
+ boolean flag = true;
+ for (int j = 0; j < paths.size(); j++) {
+ if (paths.get(i).get(1).equals(paths.get(j).get(0))) {
+ flag = false;
+ break;
+ }
+ }
+ if (flag) {
+ return paths.get(i).get(1);
+ }
+ }
+ return "";
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ string destCity(vector>& paths) {
+ for (int i = 0; i < paths.size(); i++) {
+ bool flag = true;
+ for (int j = 0; j < paths.size(); j++) {
+ if (paths[i][1] == paths[j][0]) {
+ flag = false;
+ break;
+ }
+ }
+ if (flag) {
+ return paths[i][1];
+ }
+ }
+ return "";
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[][]} paths
+ * @return {string}
+ */
+ destCity(paths) {
+ for (let i = 0; i < paths.length; i++) {
+ let flag = true;
+ for (let j = 0; j < paths.length; j++) {
+ if (paths[i][1] === paths[j][0]) {
+ flag = false;
+ break;
+ }
+ }
+ if (flag) {
+ return paths[i][1];
+ }
+ }
+ return "";
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n ^ 2)$
+* Space complexity: $O(1)$
+
+---
+
+## 2. Hash Set
+
+::tabs-start
+
+```python
+class Solution:
+ def destCity(self, paths: List[List[str]]) -> str:
+ s = set()
+ for p in paths:
+ s.add(p[0])
+
+ for p in paths:
+ if p[1] not in s:
+ return p[1]
+```
+
+```java
+public class Solution {
+ public String destCity(List> paths) {
+ Set s = new HashSet<>();
+ for (List p : paths) {
+ s.add(p.get(0));
+ }
+
+ for (List p : paths) {
+ if (!s.contains(p.get(1))) {
+ return p.get(1);
+ }
+ }
+ return "";
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ string destCity(vector>& paths) {
+ unordered_set s;
+ for (auto& p : paths) {
+ s.insert(p[0]);
+ }
+
+ for (auto& p : paths) {
+ if (s.find(p[1]) == s.end()) {
+ return p[1];
+ }
+ }
+ return "";
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[][]} paths
+ * @return {string}
+ */
+ destCity(paths) {
+ const s = new Set();
+ for (const p of paths) {
+ s.add(p[0]);
+ }
+
+ for (const p of paths) {
+ if (!s.has(p[1])) {
+ return p[1];
+ }
+ }
+ return "";
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 3. Hash Map
+
+::tabs-start
+
+```python
+class Solution:
+ def destCity(self, paths: List[List[str]]) -> str:
+ mp = {p[0]: p[1] for p in paths}
+
+ start = paths[0][0]
+ while start in mp:
+ start = mp[start]
+ return start
+```
+
+```java
+public class Solution {
+ public String destCity(List> paths) {
+ Map mp = new HashMap<>();
+ for (List p : paths) {
+ mp.put(p.get(0), p.get(1));
+ }
+
+ String start = paths.get(0).get(0);
+ while (mp.containsKey(start)) {
+ start = mp.get(start);
+ }
+ return start;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ string destCity(vector>& paths) {
+ unordered_map mp;
+ for (auto& p : paths) {
+ mp[p[0]] = p[1];
+ }
+
+ string start = paths[0][0];
+ while (mp.find(start) != mp.end()) {
+ start = mp[start];
+ }
+ return start;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[][]} paths
+ * @return {string}
+ */
+ destCity(paths) {
+ const mp = new Map();
+ for (const p of paths) {
+ mp.set(p[0], p[1]);
+ }
+
+ let start = paths[0][0];
+ while (mp.has(start)) {
+ start = mp.get(start);
+ }
+ return start;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
\ No newline at end of file
diff --git a/articles/find-all-anagrams-in-a-string.md b/articles/find-all-anagrams-in-a-string.md
new file mode 100644
index 000000000..4201b94ed
--- /dev/null
+++ b/articles/find-all-anagrams-in-a-string.md
@@ -0,0 +1,581 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def findAnagrams(self, s: str, p: str) -> List[int]:
+ n, m = len(s), len(p)
+ p = sorted(p)
+ res = []
+ for i in range(n - m + 1):
+ sub = sorted(s[i : i + m])
+ if sub == p:
+ res.append(i)
+ return res
+```
+
+```java
+public class Solution {
+ public List findAnagrams(String s, String p) {
+ int n = s.length(), m = p.length();
+ List res = new ArrayList<>();
+ char[] pArr = p.toCharArray();
+ Arrays.sort(pArr);
+ String sortedP = new String(pArr);
+
+ for (int i = 0; i <= n - m; i++) {
+ char[] subArr = s.substring(i, i + m).toCharArray();
+ Arrays.sort(subArr);
+ if (new String(subArr).equals(sortedP)) {
+ res.add(i);
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector findAnagrams(string s, string p) {
+ int n = s.size(), m = p.size();
+ vector res;
+ sort(p.begin(), p.end());
+
+ for (int i = 0; i <= n - m; i++) {
+ string sub = s.substr(i, m);
+ sort(sub.begin(), sub.end());
+ if (sub == p) {
+ res.push_back(i);
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} p
+ * @return {number[]}
+ */
+ findAnagrams(s, p) {
+ const n = s.length, m = p.length;
+ const res = [];
+ const sortedP = p.split('').sort().join('');
+
+ for (let i = 0; i <= n - m; i++) {
+ const sub = s.substring(i, i + m).split('').sort().join('');
+ if (sub === sortedP) {
+ res.push(i);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m \log m)$
+* Space complexity: $O(m)$
+
+> Where $n$ is the length of the string $s$ and $m$ is the length of the string $p$.
+
+---
+
+## 2. Prefix Count + Sliding Window
+
+::tabs-start
+
+```python
+class Solution:
+ def findAnagrams(self, s: str, p: str) -> List[int]:
+ n, m = len(s), len(p)
+ if m > n:
+ return []
+ pCount = [0] * 26
+ for c in p:
+ pCount[ord(c) - ord('a')] += 1
+
+ prefix = [[0] * 26 for _ in range(n + 1)]
+ for i in range(1, n + 1):
+ for j in range(26):
+ prefix[i][j] = prefix[i - 1][j]
+ prefix[i][ord(s[i - 1]) - ord('a')] += 1
+
+ i, j = 0, m - 1
+ res = []
+ while j < n:
+ isValid = True
+ for c in range(26):
+ if prefix[j + 1][c] - prefix[i][c] != pCount[c]:
+ isValid = False
+ break
+ if isValid:
+ res.append(i)
+ i += 1
+ j += 1
+
+ return res
+```
+
+```java
+public class Solution {
+ public List findAnagrams(String s, String p) {
+ int n = s.length(), m = p.length();
+ if (m > n) return new ArrayList<>();
+
+ int[] pCount = new int[26];
+ for (char c : p.toCharArray()) {
+ pCount[c - 'a']++;
+ }
+
+ int[][] prefix = new int[n + 1][26];
+ for (int i = 1; i <= n; i++) {
+ System.arraycopy(prefix[i - 1], 0, prefix[i], 0, 26);
+ prefix[i][s.charAt(i - 1) - 'a']++;
+ }
+
+ List res = new ArrayList<>();
+ int i = 0, j = m - 1;
+ while (j < n) {
+ boolean isValid = true;
+ for (int c = 0; c < 26; c++) {
+ if (prefix[j + 1][c] - prefix[i][c] != pCount[c]) {
+ isValid = false;
+ break;
+ }
+ }
+ if (isValid) res.add(i);
+ i++;
+ j++;
+ }
+
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector findAnagrams(string s, string p) {
+ int n = s.size(), m = p.size();
+ if (m > n) return {};
+
+ vector pCount(26, 0);
+ for (char c : p) pCount[c - 'a']++;
+
+ vector> prefix(n + 1, vector(26, 0));
+ for (int i = 1; i <= n; i++) {
+ prefix[i] = prefix[i - 1];
+ prefix[i][s[i - 1] - 'a']++;
+ }
+
+ vector res;
+ int i = 0, j = m - 1;
+ while (j < n) {
+ bool isValid = true;
+ for (int c = 0; c < 26; c++) {
+ if (prefix[j + 1][c] - prefix[i][c] != pCount[c]) {
+ isValid = false;
+ break;
+ }
+ }
+ if (isValid) res.push_back(i);
+ i++;
+ j++;
+ }
+
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} p
+ * @return {number[]}
+ */
+ findAnagrams(s, p) {
+ const n = s.length, m = p.length;
+ if (m > n) return [];
+
+ const pCount = Array(26).fill(0);
+ for (const c of p) {
+ pCount[c.charCodeAt(0) - 97]++;
+ }
+
+ const prefix = Array.from({ length: n + 1 }, () => Array(26).fill(0));
+ for (let i = 1; i <= n; i++) {
+ for (let j = 0; j < 26; j++) {
+ prefix[i][j] = prefix[i - 1][j];
+ }
+ prefix[i][s.charCodeAt(i - 1) - 97]++;
+ }
+
+ const res = [];
+ let i = 0, j = m - 1;
+ while (j < n) {
+ let isValid = true;
+ for (let c = 0; c < 26; c++) {
+ if (prefix[j + 1][c] - prefix[i][c] !== pCount[c]) {
+ isValid = false;
+ break;
+ }
+ }
+ if (isValid) res.push(i);
+ i++;
+ j++;
+ }
+
+ return res;
+ }
+}
+```
+
+::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 length of the string $p$.
+
+---
+
+## 3. Sliding Window
+
+::tabs-start
+
+```python
+class Solution:
+ def findAnagrams(self, s: str, p: str) -> List[int]:
+ if len(p) > len(s): return []
+ pCount, sCount = {}, {}
+ for i in range(len(p)):
+ pCount[p[i]] = 1 + pCount.get(p[i], 0)
+ sCount[s[i]] = 1+ sCount.get(s[i], 0)
+
+ res = [0] if sCount == pCount else []
+ l = 0
+ for r in range(len(p), len(s)):
+ sCount[s[r]] = 1+ sCount.get(s[r], 0)
+ sCount[s[l]] -= 1
+
+ if sCount[s[l]] == 0:
+ sCount.pop(s[l])
+ l += 1
+ if sCount == pCount:
+ res.append(l)
+ return res
+```
+
+```java
+public class Solution {
+ public List findAnagrams(String s, String p) {
+ if (p.length() > s.length()) return new ArrayList<>();
+
+ int[] pCount = new int[26];
+ int[] sCount = new int[26];
+
+ for (char c : p.toCharArray()) {
+ pCount[c - 'a']++;
+ }
+ for (int i = 0; i < p.length(); i++) {
+ sCount[s.charAt(i) - 'a']++;
+ }
+
+ List res = new ArrayList<>();
+ if (Arrays.equals(pCount, sCount)) res.add(0);
+
+ int l = 0;
+ for (int r = p.length(); r < s.length(); r++) {
+ sCount[s.charAt(r) - 'a']++;
+ sCount[s.charAt(l) - 'a']--;
+ l++;
+ if (Arrays.equals(pCount, sCount)) {
+ res.add(l);
+ }
+ }
+
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector findAnagrams(string s, string p) {
+ if (p.size() > s.size()) return {};
+
+ vector pCount(26, 0), sCount(26, 0);
+ for (char c : p) {
+ pCount[c - 'a']++;
+ }
+ for (int i = 0; i < p.size(); i++) {
+ sCount[s[i] - 'a']++;
+ }
+
+ vector res;
+ if (pCount == sCount) res.push_back(0);
+
+ int l = 0;
+ for (int r = p.size(); r < s.size(); r++) {
+ sCount[s[r] - 'a']++;
+ sCount[s[l] - 'a']--;
+ l++;
+ if (pCount == sCount) {
+ res.push_back(l);
+ }
+ }
+
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} p
+ * @return {number[]}
+ */
+ findAnagrams(s, p) {
+ if (p.length > s.length) return [];
+
+ const pCount = new Array(26).fill(0);
+ const sCount = new Array(26).fill(0);
+
+ for (const char of p) {
+ pCount[char.charCodeAt(0) - 97]++;
+ }
+ for (let i = 0; i < p.length; i++) {
+ sCount[s.charCodeAt(i) - 97]++;
+ }
+
+ const res = [];
+ if (pCount.toString() === sCount.toString()) res.push(0);
+
+ let l = 0;
+ for (let r = p.length; r < s.length; r++) {
+ sCount[s.charCodeAt(r) - 97]++;
+ sCount[s.charCodeAt(l) - 97]--;
+ l++;
+ if (pCount.toString() === sCount.toString()) {
+ res.push(l);
+ }
+ }
+
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
+
+> Where $n$ is the length of the string $s$ and $m$ is the length of the string $p$.
+
+---
+
+## 4. Sliding Window (Optimal)
+
+::tabs-start
+
+```python
+class Solution:
+ def findAnagrams(self, s: str, p: str) -> List[int]:
+ n, m = len(s), len(p)
+ if m > n:
+ return []
+
+ pCount = [0] * 26
+ sCount = [0] * 26
+ for i in range(m):
+ pCount[ord(p[i]) - ord('a')] += 1
+ sCount[ord(s[i]) - ord('a')] += 1
+
+ match = sum(1 for i in range(26) if pCount[i] == sCount[i])
+ res = []
+ if match == 26:
+ res.append(0)
+
+ l = 0
+ for r in range(m, n):
+ c = ord(s[l]) - ord('a')
+ if sCount[c] == pCount[c]:
+ match -= 1
+ sCount[c] -= 1
+ l += 1
+ if sCount[c] == pCount[c]:
+ match += 1
+
+ c = ord(s[r]) - ord('a')
+ if sCount[c] == pCount[c]:
+ match -= 1
+ sCount[c] += 1
+ if sCount[c] == pCount[c]:
+ match += 1
+
+ if match == 26:
+ res.append(l)
+
+ return res
+```
+
+```java
+public class Solution {
+ public List findAnagrams(String s, String p) {
+ int n = s.length(), m = p.length();
+ if (m > n) return new ArrayList<>();
+
+ int[] pCount = new int[26], sCount = new int[26];
+ for (int i = 0; i < m; i++) {
+ pCount[p.charAt(i) - 'a']++;
+ sCount[s.charAt(i) - 'a']++;
+ }
+
+ int match = 0;
+ for (int i = 0; i < 26; i++) {
+ if (pCount[i] == sCount[i]) match++;
+ }
+
+ List res = new ArrayList<>();
+ if (match == 26) res.add(0);
+
+ int l = 0;
+ for (int r = m; r < n; r++) {
+ int c = s.charAt(l) - 'a';
+ if (sCount[c] == pCount[c]) match--;
+ sCount[c]--;
+ l++;
+ if (sCount[c] == pCount[c]) match++;
+
+ c = s.charAt(r) - 'a';
+ if (sCount[c] == pCount[c]) match--;
+ sCount[c]++;
+ if (sCount[c] == pCount[c]) match++;
+
+ if (match == 26) res.add(l);
+ }
+
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector findAnagrams(string s, string p) {
+ int n = s.size(), m = p.size();
+ if (m > n) return {};
+
+ vector pCount(26, 0), sCount(26, 0);
+ for (int i = 0; i < m; i++) {
+ pCount[p[i] - 'a']++;
+ sCount[s[i] - 'a']++;
+ }
+
+ int match = 0;
+ for (int i = 0; i < 26; i++) {
+ if (pCount[i] == sCount[i]) match++;
+ }
+
+ vector res;
+ if (match == 26) res.push_back(0);
+
+ int l = 0;
+ for (int r = m; r < n; r++) {
+ int c = s[l] - 'a';
+ if (sCount[c] == pCount[c]) match--;
+ sCount[c]--;
+ l++;
+ if (sCount[c] == pCount[c]) match++;
+
+ c = s[r] - 'a';
+ if (sCount[c] == pCount[c]) match--;
+ sCount[c]++;
+ if (sCount[c] == pCount[c]) match++;
+
+ if (match == 26) res.push_back(l);
+ }
+
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @param {string} p
+ * @return {number[]}
+ */
+ findAnagrams(s, p) {
+ const n = s.length, m = p.length;
+ if (m > n) return [];
+
+ const pCount = new Array(26).fill(0);
+ const sCount = new Array(26).fill(0);
+
+ for (let i = 0; i < m; i++) {
+ pCount[p.charCodeAt(i) - 97]++;
+ sCount[s.charCodeAt(i) - 97]++;
+ }
+
+ let match = 0;
+ for (let i = 0; i < 26; i++) {
+ if (pCount[i] === sCount[i]) match++;
+ }
+
+ const res = [];
+ if (match === 26) res.push(0);
+
+ let l = 0;
+ for (let r = m; r < n; r++) {
+ let c = s.charCodeAt(l) - 97;
+ if (sCount[c] === pCount[c]) match--;
+ sCount[c]--;
+ l++;
+ if (sCount[c] === pCount[c]) match++;
+
+ c = s.charCodeAt(r) - 97;
+ if (sCount[c] === pCount[c]) match--;
+ sCount[c]++;
+ if (sCount[c] === pCount[c]) match++;
+
+ if (match === 26) res.push(l);
+ }
+
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
+
+> Where $n$ is the length of the string $s$ and $m$ is the length of the string $p$.
\ No newline at end of file
diff --git a/articles/find-all-numbers-disappeared-in-an-array.md b/articles/find-all-numbers-disappeared-in-an-array.md
new file mode 100644
index 000000000..f0462dc4f
--- /dev/null
+++ b/articles/find-all-numbers-disappeared-in-an-array.md
@@ -0,0 +1,358 @@
+## 1. Hash Set
+
+::tabs-start
+
+```python
+class Solution:
+ def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
+ n = len(nums)
+ store = set(range(1, n + 1))
+
+ for num in nums:
+ store.discard(num)
+
+ return list(store)
+```
+
+```java
+public class Solution {
+ public List findDisappearedNumbers(int[] nums) {
+ int n = nums.length;
+ Set store = new HashSet<>();
+ for (int i = 1; i <= n; i++) store.add(i);
+
+ for (int num : nums) {
+ store.remove(num);
+ }
+
+ return new ArrayList<>(store);
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector findDisappearedNumbers(vector& nums) {
+ int n = nums.size();
+ unordered_set store;
+ for (int i = 1; i <= n; i++) store.insert(i);
+
+ for (int num : nums) {
+ store.erase(num);
+ }
+
+ vector result(store.begin(), store.end());
+ return result;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+ findDisappearedNumbers(nums) {
+ const n = nums.length;
+ const store = new Set();
+ for (let i = 1; i <= n; i++) store.add(i);
+
+ for (let num of nums) {
+ store.delete(num);
+ }
+
+ return Array.from(store);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 2. Boolean Array
+
+::tabs-start
+
+```python
+class Solution:
+ def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
+ n = len(nums)
+ mark = [False] * n
+
+ for num in nums:
+ mark[num - 1] = True
+
+ res = []
+ for i in range(1, n + 1):
+ if not mark[i - 1]:
+ res.append(i)
+ return res
+```
+
+```java
+public class Solution {
+ public List findDisappearedNumbers(int[] nums) {
+ int n = nums.length;
+ boolean[] mark = new boolean[n];
+
+ for (int num : nums) {
+ mark[num - 1] = true;
+ }
+
+ List res = new ArrayList<>();
+ for (int i = 1; i <= n; i++) {
+ if (!mark[i - 1]) {
+ res.add(i);
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector findDisappearedNumbers(vector& nums) {
+ int n = nums.size();
+ vector mark(n, false);
+
+ for (int num : nums) {
+ mark[num - 1] = true;
+ }
+
+ vector res;
+ for (int i = 1; i <= n; i++) {
+ if (!mark[i - 1]) {
+ res.push_back(i);
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+ findDisappearedNumbers(nums) {
+ const n = nums.length;
+ const mark = new Array(n).fill(false);
+
+ for (let num of nums) {
+ mark[num - 1] = true;
+ }
+
+ const res = [];
+ for (let i = 1; i <= n; i++) {
+ if (!mark[i - 1]) {
+ res.push(i);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 3. Sorting
+
+::tabs-start
+
+```python
+class Solution:
+ def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
+ n = len(nums)
+ nums.sort()
+
+ res = []
+ idx = 0
+ for num in range(1, n + 1):
+ while idx < n and nums[idx] < num:
+ idx += 1
+ if idx == n or nums[idx] > num:
+ res.append(num)
+ return res
+```
+
+```java
+public class Solution {
+ public List findDisappearedNumbers(int[] nums) {
+ int n = nums.length;
+ Arrays.sort(nums);
+
+ List res = new ArrayList<>();
+ int idx = 0;
+ for (int num = 1; num <= n; num++) {
+ while (idx < n && nums[idx] < num) {
+ idx++;
+ }
+ if (idx == n || nums[idx] > num) {
+ res.add(num);
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector findDisappearedNumbers(vector& nums) {
+ int n = nums.size();
+ sort(nums.begin(), nums.end());
+
+ vector res;
+ int idx = 0;
+ for (int num = 1; num <= n; num++) {
+ while (idx < n && nums[idx] < num) {
+ idx++;
+ }
+ if (idx == n || nums[idx] > num) {
+ res.push_back(num);
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+ findDisappearedNumbers(nums) {
+ nums.sort((a, b) => a - b);
+
+ const res = [];
+ let idx = 0;
+ for (let num = 1; num <= nums.length; num++) {
+ while (idx < nums.length && nums[idx] < num) {
+ idx++;
+ }
+ if (idx === nums.length || nums[idx] > num) {
+ res.push(num);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n \log n)$
+* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm.
+
+---
+
+## 4. Negative Marking
+
+::tabs-start
+
+```python
+class Solution:
+ def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
+ for num in nums:
+ i = abs(num) - 1
+ nums[i] = -1 * abs(nums[i])
+
+ res = []
+ for i, num in enumerate(nums):
+ if num > 0:
+ res.append(i + 1)
+ return res
+```
+
+```java
+public class Solution {
+ public List findDisappearedNumbers(int[] nums) {
+ for (int num : nums) {
+ int i = Math.abs(num) - 1;
+ nums[i] = -Math.abs(nums[i]);
+ }
+
+ List res = new ArrayList<>();
+ for (int i = 0; i < nums.length; i++) {
+ if (nums[i] > 0) {
+ res.add(i + 1);
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector findDisappearedNumbers(vector& nums) {
+ for (int num : nums) {
+ int i = abs(num) - 1;
+ nums[i] = -abs(nums[i]);
+ }
+
+ vector res;
+ for (int i = 0; i < nums.size(); i++) {
+ if (nums[i] > 0) {
+ res.push_back(i + 1);
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+ findDisappearedNumbers(nums) {
+ for (let num of nums) {
+ let i = Math.abs(num) - 1;
+ nums[i] = -Math.abs(nums[i]);
+ }
+
+ const res = [];
+ for (let i = 0; i < nums.length; i++) {
+ if (nums[i] > 0) {
+ res.push(i + 1);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$ since we modified the input array without using extra space.
\ No newline at end of file
diff --git a/articles/find-the-index-of-the-first-occurrence-in-a-string.md b/articles/find-the-index-of-the-first-occurrence-in-a-string.md
new file mode 100644
index 000000000..beb5b5893
--- /dev/null
+++ b/articles/find-the-index-of-the-first-occurrence-in-a-string.md
@@ -0,0 +1,633 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def strStr(self, haystack: str, needle: str) -> int:
+ n, m = len(haystack), len(needle)
+ for i in range(n - m + 1):
+ j = 0
+ while j < m:
+ if haystack[i + j] != needle[j]:
+ break
+ j += 1
+ if j == m:
+ return i
+ return -1
+```
+
+```java
+public class Solution {
+ public int strStr(String haystack, String needle) {
+ int n = haystack.length(), m = needle.length();
+ for (int i = 0; i < n - m + 1; i++) {
+ int j = 0;
+ while (j < m) {
+ if (haystack.charAt(i + j) != needle.charAt(j)) {
+ break;
+ }
+ j++;
+ }
+ if (j == m) return i;
+ }
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int strStr(string haystack, string needle) {
+ int n = haystack.length(), m = needle.length();
+ for (int i = 0; i < n - m + 1; i++) {
+ int j = 0;
+ while (j < m) {
+ if (haystack[i + j] != needle[j]) {
+ break;
+ }
+ j++;
+ }
+ if (j == m) return i;
+ }
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} haystack
+ * @param {string} needle
+ * @return {number}
+ */
+ strStr(haystack, needle) {
+ let n = haystack.length, m = needle.length;
+ for (let i = 0; i < n - m + 1; i++) {
+ let j = 0;
+ while (j < m) {
+ if (haystack[i + j] !== needle[j]) {
+ break;
+ }
+ j++;
+ }
+ if (j === m) return i;
+ }
+ return -1;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m)$
+* Space complexity: $O(1)$
+
+> Where $n$ is the length of the string $heystack$ and $m$ is the length of the string $needle$.
+
+---
+
+## 2. Knuth-Morris-Pratt (KMP) Algorithm
+
+::tabs-start
+
+```python
+class Solution:
+ def strStr(self, haystack: str, needle: str) -> int:
+ if needle == "": return 0
+ lps = [0] * len(needle)
+
+ prevLPS, i = 0, 1
+ while i < len(needle):
+ if needle[i] == needle[prevLPS]:
+ lps[i] = prevLPS + 1
+ prevLPS += 1
+ i += 1
+ elif prevLPS == 0:
+ lps[i] = 0
+ i += 1
+ else:
+ prevLPS = lps[prevLPS - 1]
+
+ i = 0 # ptr for haystack
+ j = 0 # ptr for needle
+ while i < len(haystack):
+ if haystack[i] == needle[j]:
+ i, j = i + 1, j + 1
+ else:
+ if j == 0:
+ i += 1
+ else:
+ j = lps[j - 1]
+
+ if j == len(needle):
+ return i - len(needle)
+
+ return -1
+```
+
+```java
+public class Solution {
+ public int strStr(String haystack, String needle) {
+ if (needle.isEmpty()) return 0;
+
+ int m = needle.length();
+ int[] lps = new int[m];
+ int prevLPS = 0, i = 1;
+
+ while (i < m) {
+ if (needle.charAt(i) == needle.charAt(prevLPS)) {
+ lps[i] = prevLPS + 1;
+ prevLPS++;
+ i++;
+ } else if (prevLPS == 0) {
+ lps[i] = 0;
+ i++;
+ } else {
+ prevLPS = lps[prevLPS - 1];
+ }
+ }
+
+ i = 0; // ptr for haystack
+ int j = 0; // ptr for needle
+ while (i < haystack.length()) {
+ if (haystack.charAt(i) == needle.charAt(j)) {
+ i++;
+ j++;
+ } else {
+ if (j == 0) {
+ i++;
+ } else {
+ j = lps[j - 1];
+ }
+ }
+
+ if (j == m) {
+ return i - m;
+ }
+ }
+
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int strStr(string haystack, string needle) {
+ if (needle.empty()) return 0;
+
+ int m = needle.size();
+ vector lps(m, 0);
+ int prevLPS = 0, i = 1;
+
+ while (i < m) {
+ if (needle[i] == needle[prevLPS]) {
+ lps[i] = prevLPS + 1;
+ prevLPS++;
+ i++;
+ } else if (prevLPS == 0) {
+ lps[i] = 0;
+ i++;
+ } else {
+ prevLPS = lps[prevLPS - 1];
+ }
+ }
+
+ i = 0; // ptr for haystack
+ int j = 0; // ptr for needle
+ while (i < haystack.size()) {
+ if (haystack[i] == needle[j]) {
+ i++;
+ j++;
+ } else {
+ if (j == 0) {
+ i++;
+ } else {
+ j = lps[j - 1];
+ }
+ }
+
+ if (j == m) {
+ return i - m;
+ }
+ }
+
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} haystack
+ * @param {string} needle
+ * @return {number}
+ */
+ strStr(haystack, needle) {
+ if (needle === "") return 0;
+
+ const m = needle.length;
+ const lps = new Array(m).fill(0);
+
+ let prevLPS = 0, i = 1;
+ while (i < m) {
+ if (needle[i] === needle[prevLPS]) {
+ lps[i] = prevLPS + 1;
+ prevLPS++;
+ i++;
+ } else if (prevLPS === 0) {
+ lps[i] = 0;
+ i++;
+ } else {
+ prevLPS = lps[prevLPS - 1];
+ }
+ }
+
+ i = 0; // ptr for haystack
+ let j = 0; // ptr for needle
+ while (i < haystack.length) {
+ if (haystack[i] === needle[j]) {
+ i++;
+ j++;
+ } else {
+ if (j === 0) {
+ i++;
+ } else {
+ j = lps[j - 1];
+ }
+ }
+
+ if (j === m) {
+ return i - m;
+ }
+ }
+
+ return -1;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(m)$
+
+> Where $n$ is the length of the string $heystack$ and $m$ is the length of the string $needle$.
+
+---
+
+## 3. Z-Algorithm
+
+::tabs-start
+
+```python
+class Solution:
+ def strStr(self, haystack: str, needle: str) -> int:
+ if not needle:
+ return 0
+
+ s = needle + "$" + haystack
+ 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(needle) + 1, n):
+ if z[i] == len(needle):
+ return i - len(needle) - 1
+
+ return -1
+```
+
+```java
+public class Solution {
+ public int strStr(String haystack, String needle) {
+ if (needle.isEmpty()) return 0;
+
+ String s = needle + "$" + haystack;
+ 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 = needle.length() + 1; i < n; i++) {
+ if (z[i] == needle.length()) {
+ return i - needle.length() - 1;
+ }
+ }
+
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int strStr(string haystack, string needle) {
+ if (needle.empty()) return 0;
+
+ string s = needle + "$" + haystack;
+ 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 = needle.size() + 1; i < n; i++) {
+ if (z[i] == needle.size()) {
+ return i - needle.size() - 1;
+ }
+ }
+
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} haystack
+ * @param {string} needle
+ * @return {number}
+ */
+ strStr(haystack, needle) {
+ if (needle === "") return 0;
+
+ const s = needle + "$" + haystack;
+ const n = s.length;
+ const z = new 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 = needle.length + 1; i < n; i++) {
+ if (z[i] === needle.length) {
+ return i - needle.length - 1;
+ }
+ }
+
+ return -1;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(n + m)$
+
+> Where $n$ is the length of the string $heystack$ and $m$ is the length of the string $needle$.
+
+---
+
+## 4. Rabin-Karp Algorithm (Rolling Hash)
+
+::tabs-start
+
+```python
+class Solution:
+ def strStr(self, haystack: str, needle: str) -> int:
+ if not needle:
+ return 0
+
+ base1, mod1 = 31, 768258391
+ base2, mod2 = 37, 685683731
+
+ n, m = len(haystack), len(needle)
+ if m > n:
+ return -1
+
+ power1, power2 = 1, 1
+ for _ in range(m):
+ power1 = (power1 * base1) % mod1
+ power2 = (power2 * base2) % mod2
+
+ needle_hash1, needle_hash2 = 0, 0
+ haystack_hash1, haystack_hash2 = 0, 0
+
+ for i in range(m):
+ needle_hash1 = (needle_hash1 * base1 + ord(needle[i])) % mod1
+ needle_hash2 = (needle_hash2 * base2 + ord(needle[i])) % mod2
+ haystack_hash1 = (haystack_hash1 * base1 + ord(haystack[i])) % mod1
+ haystack_hash2 = (haystack_hash2 * base2 + ord(haystack[i])) % mod2
+
+ for i in range(n - m + 1):
+ if haystack_hash1 == needle_hash1 and haystack_hash2 == needle_hash2:
+ return i
+
+ if i + m < n:
+ haystack_hash1 = (haystack_hash1 * base1 - ord(haystack[i]) * power1 + ord(haystack[i + m])) % mod1
+ haystack_hash2 = (haystack_hash2 * base2 - ord(haystack[i]) * power2 + ord(haystack[i + m])) % mod2
+
+ haystack_hash1 = (haystack_hash1 + mod1) % mod1
+ haystack_hash2 = (haystack_hash2 + mod2) % mod2
+
+ return -1
+```
+
+```java
+public class Solution {
+ public int strStr(String haystack, String needle) {
+ if (needle.isEmpty()) return 0;
+
+ int base1 = 31, mod1 = 768258391;
+ int base2 = 37, mod2 = 685683731;
+
+ int n = haystack.length(), m = needle.length();
+ if (m > n) return -1;
+
+ long power1 = 1, power2 = 1;
+ for (int i = 0; i < m; i++) {
+ power1 = (power1 * base1) % mod1;
+ power2 = (power2 * base2) % mod2;
+ }
+
+ long needleHash1 = 0, needleHash2 = 0;
+ long haystackHash1 = 0, haystackHash2 = 0;
+
+ for (int i = 0; i < m; i++) {
+ needleHash1 = (needleHash1 * base1 + needle.charAt(i)) % mod1;
+ needleHash2 = (needleHash2 * base2 + needle.charAt(i)) % mod2;
+ haystackHash1 = (haystackHash1 * base1 + haystack.charAt(i)) % mod1;
+ haystackHash2 = (haystackHash2 * base2 + haystack.charAt(i)) % mod2;
+ }
+
+ for (int i = 0; i <= n - m; i++) {
+ if (haystackHash1 == needleHash1 && haystackHash2 == needleHash2) {
+ return i;
+ }
+
+ if (i + m < n) {
+ haystackHash1 = (haystackHash1 * base1 - haystack.charAt(i) * power1 + haystack.charAt(i + m)) % mod1;
+ haystackHash2 = (haystackHash2 * base2 - haystack.charAt(i) * power2 + haystack.charAt(i + m)) % mod2;
+
+ if (haystackHash1 < 0) haystackHash1 += mod1;
+ if (haystackHash2 < 0) haystackHash2 += mod2;
+ }
+ }
+
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int strStr(string haystack, string needle) {
+ if (needle.empty()) return 0;
+
+ long long base1 = 31, mod1 = 768258391;
+ long long base2 = 37, mod2 = 685683731;
+
+ int n = haystack.size(), m = needle.size();
+ if (m > n) return -1;
+
+ long long power1 = 1, power2 = 1;
+ for (int i = 0; i < m; i++) {
+ power1 = (power1 * base1) % mod1;
+ power2 = (power2 * base2) % mod2;
+ }
+
+ long long needleHash1 = 0, needleHash2 = 0;
+ long long haystackHash1 = 0, haystackHash2 = 0;
+
+ for (int i = 0; i < m; i++) {
+ needleHash1 = (needleHash1 * base1 + needle[i]) % mod1;
+ needleHash2 = (needleHash2 * base2 + needle[i]) % mod2;
+ haystackHash1 = (haystackHash1 * base1 + haystack[i]) % mod1;
+ haystackHash2 = (haystackHash2 * base2 + haystack[i]) % mod2;
+ }
+
+ for (int i = 0; i <= n - m; i++) {
+ if (haystackHash1 == needleHash1 && haystackHash2 == needleHash2) {
+ return i;
+ }
+
+ if (i + m < n) {
+ haystackHash1 = (haystackHash1 * base1 - haystack[i] * power1 + haystack[i + m]) % mod1;
+ haystackHash2 = (haystackHash2 * base2 - haystack[i] * power2 + haystack[i + m]) % mod2;
+
+ if (haystackHash1 < 0) haystackHash1 += mod1;
+ if (haystackHash2 < 0) haystackHash2 += mod2;
+ }
+ }
+
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} haystack
+ * @param {string} needle
+ * @return {number}
+ */
+ strStr(haystack, needle) {
+ if (needle === "") return 0;
+
+ const base1 = 31, mod1 = 768258391;
+ const base2 = 37, mod2 = 685683731;
+
+ const n = haystack.length, m = needle.length;
+ if (m > n) return -1;
+
+ let power1 = 1, power2 = 1;
+ for (let i = 0; i < m; i++) {
+ power1 = (power1 * base1) % mod1;
+ power2 = (power2 * base2) % mod2;
+ }
+
+ let needleHash1 = 0, needleHash2 = 0;
+ let haystackHash1 = 0, haystackHash2 = 0;
+
+ for (let i = 0; i < m; i++) {
+ needleHash1 = (needleHash1 * base1 + needle.charCodeAt(i)) % mod1;
+ needleHash2 = (needleHash2 * base2 + needle.charCodeAt(i)) % mod2;
+ haystackHash1 = (haystackHash1 * base1 + haystack.charCodeAt(i)) % mod1;
+ haystackHash2 = (haystackHash2 * base2 + haystack.charCodeAt(i)) % mod2;
+ }
+
+ for (let i = 0; i <= n - m; i++) {
+ if (haystackHash1 === needleHash1 && haystackHash2 === needleHash2) {
+ return i;
+ }
+
+ if (i + m < n) {
+ haystackHash1 = (haystackHash1 * base1 - haystack.charCodeAt(i) * power1 + haystack.charCodeAt(i + m)) % mod1;
+ haystackHash2 = (haystackHash2 * base2 - haystack.charCodeAt(i) * power2 + haystack.charCodeAt(i + m)) % mod2;
+
+ if (haystackHash1 < 0) haystackHash1 += mod1;
+ if (haystackHash2 < 0) haystackHash2 += mod2;
+ }
+ }
+
+ return -1;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(1)$
+
+> Where $n$ is the length of the string $heystack$ and $m$ is the length of the string $needle$.
\ No newline at end of file
diff --git a/articles/find-words-that-can-be-formed-by-characters.md b/articles/find-words-that-can-be-formed-by-characters.md
new file mode 100644
index 000000000..4dfdf7b44
--- /dev/null
+++ b/articles/find-words-that-can-be-formed-by-characters.md
@@ -0,0 +1,391 @@
+## 1. Hash Map (Two Pass)
+
+::tabs-start
+
+```python
+class Solution:
+ def countCharacters(self, words: List[str], chars: str) -> int:
+ count = Counter(chars)
+ res = 0
+
+ for w in words:
+ cur_word = Counter(w)
+ good = True
+ for c in cur_word:
+ if cur_word[c] > count[c]:
+ good = False
+ break
+ if good:
+ res += len(w)
+ return res
+```
+
+```java
+public class Solution {
+ public int countCharacters(String[] words, String chars) {
+ Map count = new HashMap<>();
+ for (char c : chars.toCharArray()) {
+ count.put(c, count.getOrDefault(c, 0) + 1);
+ }
+ int res = 0;
+ for (String w : words) {
+ Map curWord = new HashMap<>();
+ for (char c : w.toCharArray()) {
+ curWord.put(c, curWord.getOrDefault(c, 0) + 1);
+ }
+ boolean good = true;
+ for (char c : curWord.keySet()) {
+ if (curWord.get(c) > count.getOrDefault(c, 0)) {
+ good = false;
+ break;
+ }
+ }
+ if (good) {
+ res += w.length();
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int countCharacters(vector& words, string chars) {
+ unordered_map count;
+ for (char c : chars) {
+ count[c]++;
+ }
+ int res = 0;
+ for (const string& w : words) {
+ unordered_map curWord;
+ for (char c : w) {
+ curWord[c]++;
+ }
+ bool good = true;
+ for (const auto& p : curWord) {
+ if (p.second > count[p.first]) {
+ good = false;
+ break;
+ }
+ }
+ if (good) {
+ res += w.size();
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[]} words
+ * @param {string} chars
+ * @return {number}
+ */
+ countCharacters(words, chars) {
+ const count = {};
+ for (const c of chars) {
+ count[c] = (count[c] || 0) + 1;
+ }
+ let res = 0;
+ for (const w of words) {
+ const curWord = {};
+ for (const c of w) {
+ curWord[c] = (curWord[c] || 0) + 1;
+ }
+ let good = true;
+ for (const c in curWord) {
+ if (curWord[c] > (count[c] || 0)) {
+ good = false;
+ break;
+ }
+ }
+ if (good) {
+ res += w.length;
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + (m * k))$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
+
+> Where $n$ is the length of $chars$, $m$ is the number of words and $k$ is the average length of each word.
+
+---
+
+## 2. Hash Map (One Pass)
+
+::tabs-start
+
+```python
+class Solution:
+ def countCharacters(self, words: List[str], chars: str) -> int:
+ count = Counter(chars)
+ res = 0
+
+ for w in words:
+ cur_word = defaultdict(int)
+ good = True
+ for c in w:
+ cur_word[c] += 1
+ if cur_word[c] > count[c]:
+ good = False
+ break
+ if good:
+ res += len(w)
+ return res
+```
+
+```java
+public class Solution {
+ public int countCharacters(String[] words, String chars) {
+ Map count = new HashMap<>();
+ for (char c : chars.toCharArray()) {
+ count.put(c, count.getOrDefault(c, 0) + 1);
+ }
+ int res = 0;
+ for (String w : words) {
+ Map curWord = new HashMap<>();
+ boolean good = true;
+ for (char c : w.toCharArray()) {
+ curWord.put(c, curWord.getOrDefault(c, 0) + 1);
+ if (curWord.get(c) > count.getOrDefault(c, 0)) {
+ good = false;
+ break;
+ }
+ }
+ if (good) {
+ res += w.length();
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int countCharacters(vector& words, string chars) {
+ unordered_map count;
+ for (char c : chars) {
+ count[c]++;
+ }
+ int res = 0;
+ for (const string& w : words) {
+ unordered_map curWord;
+ bool good = true;
+ for (char c : w) {
+ curWord[c]++;
+ if (curWord[c] > count[c]) {
+ good = false;
+ break;
+ }
+ }
+ if (good) {
+ res += w.size();
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[]} words
+ * @param {string} chars
+ * @return {number}
+ */
+ countCharacters(words, chars) {
+ const count = {};
+ for (const c of chars) {
+ count[c] = (count[c] || 0) + 1;
+ }
+ let res = 0;
+ for (const w of words) {
+ const curWord = {};
+ let good = true;
+ for (const c of w) {
+ curWord[c] = (curWord[c] || 0) + 1;
+ if (curWord[c] > (count[c] || 0)) {
+ good = false;
+ break;
+ }
+ }
+ if (good) {
+ res += w.length;
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + (m * k))$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
+
+> Where $n$ is the length of $chars$, $m$ is the number of words and $k$ is the average length of each word.
+
+---
+
+## 3. Hash Table
+
+::tabs-start
+
+```python
+class Solution:
+ def countCharacters(self, words: List[str], chars: str) -> int:
+ count = [0] * 26
+ for c in chars:
+ count[ord(c) - ord('a')] += 1
+
+ org = count[:]
+ res = 0
+
+ for w in words:
+ good = True
+ for c in w:
+ i = ord(c) - ord('a')
+ count[i] -= 1
+ if count[i] < 0:
+ good = False
+ break
+ if good:
+ res += len(w)
+
+ for i in range(26):
+ count[i] = org[i]
+ return res
+```
+
+```java
+public class Solution {
+ public int countCharacters(String[] words, String chars) {
+ int[] count = new int[26];
+ for (char c : chars.toCharArray()) {
+ count[c - 'a']++;
+ }
+
+ int[] org = count.clone();
+ int res = 0;
+
+ for (String w : words) {
+ boolean good = true;
+ for (int i = 0; i < w.length(); i++) {
+ int j = w.charAt(i) - 'a';
+ count[j]--;
+ if (count[j] < 0) {
+ good = false;
+ break;
+ }
+ }
+ if (good) {
+ res += w.length();
+ }
+ for (int i = 0; i < 26; i++) {
+ count[i] = org[i];
+ }
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int countCharacters(vector& words, string chars) {
+ vector count(26, 0);
+ for (char c : chars) {
+ count[c - 'a']++;
+ }
+
+ vector org = count;
+ int res = 0;
+
+ for (string& w : words) {
+ bool good = true;
+ for (char& c : w) {
+ int i = c - 'a';
+ count[i]--;
+ if (count[i] < 0) {
+ good = false;
+ break;
+ }
+ }
+ if (good) {
+ res += w.length();
+ }
+ for (int i = 0; i < 26; i++) {
+ count[i] = org[i];
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string[]} words
+ * @param {string} chars
+ * @return {number}
+ */
+ countCharacters(words, chars) {
+ const count = new Array(26).fill(0);
+ for (let c of chars) {
+ count[c.charCodeAt(0) - 'a'.charCodeAt(0)]++;
+ }
+
+ const org = [...count];
+ let res = 0;
+
+ for (let w of words) {
+ let good = true;
+ for (let c of w) {
+ const i = c.charCodeAt(0) - 'a'.charCodeAt(0);
+ count[i]--;
+ if (count[i] < 0) {
+ good = false;
+ break;
+ }
+ }
+
+ if (good) {
+ res += w.length;
+ }
+ for (let i = 0; i < 26; i++) {
+ count[i] = org[i];
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + (m * k))$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
+
+> Where $n$ is the length of $chars$, $m$ is the number of words and $k$ is the average length of each word.
\ No newline at end of file
diff --git a/articles/first-unique-character-in-a-string.md b/articles/first-unique-character-in-a-string.md
new file mode 100644
index 000000000..b60c2e4f6
--- /dev/null
+++ b/articles/first-unique-character-in-a-string.md
@@ -0,0 +1,365 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def firstUniqChar(self, s: str) -> int:
+ for i in range(len(s)):
+ flag = True
+ for j in range(len(s)):
+ if i == j:
+ continue
+ if s[i] == s[j]:
+ flag = False
+ break
+ if flag:
+ return i
+ return -1
+```
+
+```java
+public class Solution {
+ public int firstUniqChar(String s) {
+ for (int i = 0; i < s.length(); i++) {
+ boolean flag = true;
+ for (int j = 0; j < s.length(); j++) {
+ if (i == j) continue;
+ if (s.charAt(i) == s.charAt(j)) {
+ flag = false;
+ break;
+ }
+ }
+ if (flag) return i;
+ }
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int firstUniqChar(string s) {
+ for (int i = 0; i < s.size(); i++) {
+ bool flag = true;
+ for (int j = 0; j < s.size(); j++) {
+ if (i == j) continue;
+ if (s[i] == s[j]) {
+ flag = false;
+ break;
+ }
+ }
+ if (flag) return i;
+ }
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @return {number}
+ */
+ firstUniqChar(s) {
+ for (let i = 0; i < s.length; i++) {
+ let flag = true;
+ for (let j = 0; j < s.length; j++) {
+ if (i === j) continue;
+ if (s[i] === s[j]) {
+ flag = false;
+ break;
+ }
+ }
+ if (flag) return i;
+ }
+ return -1;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n ^ 2)$
+* Space complexity: $O(1)$
+
+---
+
+## 2. Hash Map
+
+::tabs-start
+
+```python
+class Solution:
+ def firstUniqChar(self, s: str) -> int:
+ count = defaultdict(int)
+ for c in s:
+ count[c] += 1
+
+ for i, c in enumerate(s):
+ if count[c] == 1:
+ return i
+ return -1
+```
+
+```java
+public class Solution {
+ public int firstUniqChar(String s) {
+ Map count = new HashMap<>();
+ for (char c : s.toCharArray()) {
+ count.put(c, count.getOrDefault(c, 0) + 1);
+ }
+
+ for (int i = 0; i < s.length(); i++) {
+ if (count.get(s.charAt(i)) == 1) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int firstUniqChar(string s) {
+ unordered_map count;
+ for (char c : s) {
+ count[c]++;
+ }
+
+ for (int i = 0; i < s.size(); i++) {
+ if (count[s[i]] == 1) {
+ return i;
+ }
+ }
+ return -1;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @return {number}
+ */
+ firstUniqChar(s) {
+ const count = new Map();
+ for (const c of s) {
+ count.set(c, (count.get(c) || 0) + 1);
+ }
+
+ for (let i = 0; i < s.length; i++) {
+ if (count.get(s[i]) === 1) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
+
+---
+
+## 3. Hash Map (Optimal)
+
+::tabs-start
+
+```python
+class Solution:
+ def firstUniqChar(self, s: str) -> int:
+ n = len(s)
+ count = defaultdict(int)
+ for i, c in enumerate(s):
+ if c not in count:
+ count[c] = i
+ else:
+ count[c] = n
+
+ res = n
+ for c in count:
+ res = min(res, count[c])
+
+ return -1 if res == n else res
+```
+
+```java
+public class Solution {
+ public int firstUniqChar(String s) {
+ int n = s.length();
+ Map count = new HashMap<>();
+
+ for (int i = 0; i < n; i++) {
+ char c = s.charAt(i);
+ if (!count.containsKey(c)) {
+ count.put(c, i);
+ } else {
+ count.put(c, n);
+ }
+ }
+
+ int res = n;
+ for (int index : count.values()) {
+ res = Math.min(res, index);
+ }
+
+ return res == n ? -1 : res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int firstUniqChar(string s) {
+ int n = s.size();
+ unordered_map count;
+
+ for (int i = 0; i < n; i++) {
+ if (count.find(s[i]) == count.end()) {
+ count[s[i]] = i;
+ } else {
+ count[s[i]] = n;
+ }
+ }
+
+ int res = n;
+ for (auto& [key, index] : count) {
+ res = min(res, index);
+ }
+
+ return res == n ? -1 : res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @return {number}
+ */
+ firstUniqChar(s) {
+ const n = s.length;
+ const count = new Map();
+
+ for (let i = 0; i < n; i++) {
+ const c = s[i];
+ if (!count.has(c)) {
+ count.set(c, i);
+ } else {
+ count.set(c, n);
+ }
+ }
+
+ let res = n;
+ for (const index of count.values()) {
+ res = Math.min(res, index);
+ }
+
+ return res === n ? -1 : res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$ since we have at most $26$ different characters.
+
+---
+
+## 4. Iteration
+
+::tabs-start
+
+```python
+class Solution:
+ def firstUniqChar(self, s: str) -> int:
+ res = n = len(s)
+ for ch in range(ord('a'), ord('z') + 1):
+ index = s.find(chr(ch))
+ if index != -1 and s.rfind(chr(ch)) == index:
+ res = min(res, index)
+
+ return -1 if res == n else res
+```
+
+```java
+public class Solution {
+ public int firstUniqChar(String s) {
+ int res = s.length();
+
+ for (char ch = 'a'; ch <= 'z'; ch++) {
+ int firstIndex = s.indexOf(ch);
+ if (firstIndex != -1 && s.lastIndexOf(ch) == firstIndex) {
+ res = Math.min(res, firstIndex);
+ }
+ }
+
+ return res == s.length() ? -1 : res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ int firstUniqChar(string s) {
+ int res = s.size();
+
+ for (char ch = 'a'; ch <= 'z'; ch++) {
+ int firstIndex = s.find(ch);
+ if (firstIndex != string::npos && s.rfind(ch) == firstIndex) {
+ res = min(res, firstIndex);
+ }
+ }
+
+ return res == s.size() ? -1 : res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {string} s
+ * @return {number}
+ */
+ firstUniqChar(s) {
+ let res = s.length;
+
+ for (let ch = 'a'.charCodeAt(0); ch <= 'z'.charCodeAt(0); ch++) {
+ const char = String.fromCharCode(ch);
+ const firstIndex = s.indexOf(char);
+ if (firstIndex !== -1 && s.lastIndexOf(char) === firstIndex) {
+ res = Math.min(res, firstIndex);
+ }
+ }
+
+ return res === s.length ? -1 : res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(26 * n)$ since we have at most $26$ different characters.
+* Space complexity: $O(1)$
\ No newline at end of file
diff --git a/articles/grid-game.md b/articles/grid-game.md
new file mode 100644
index 000000000..236f53012
--- /dev/null
+++ b/articles/grid-game.md
@@ -0,0 +1,354 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def gridGame(self, grid: List[List[int]]) -> int:
+ cols = len(grid[0])
+ res = float('inf')
+
+ top1 = 0
+ for i in range(cols):
+ top1 += grid[0][i]
+ bottom1 = 0
+ for j in range(i, cols):
+ bottom1 += grid[1][j]
+
+ top2 = robot2 = 0
+ for j in range(cols):
+ if j > i:
+ top2 += grid[0][j]
+
+ bottom2 = 0
+ for k in range(j, i):
+ bottom2 += grid[1][k]
+ robot2 = max(robot2, top2 + bottom2)
+
+ res = min(res, robot2)
+
+ return res
+```
+
+```java
+public class Solution {
+ public long gridGame(int[][] grid) {
+ int cols = grid[0].length;
+ long res = Long.MAX_VALUE;
+
+ long top1 = 0;
+ for (int i = 0; i < cols; i++) {
+ top1 += grid[0][i];
+ long bottom1 = 0;
+ for (int j = i; j < cols; j++) {
+ bottom1 += grid[1][j];
+ }
+
+ long top2 = 0, robot2 = 0;
+ for (int j = 0; j < cols; j++) {
+ if (j > i) {
+ top2 += grid[0][j];
+ }
+
+ long bottom2 = 0;
+ for (int k = j; k < i; k++) {
+ bottom2 += grid[1][k];
+ }
+ robot2 = Math.max(robot2, top2 + bottom2);
+ }
+
+ res = Math.min(res, robot2);
+ }
+
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ long long gridGame(vector>& grid) {
+ int cols = grid[0].size();
+ long long res = LLONG_MAX;
+
+ long long top1 = 0;
+ for (int i = 0; i < cols; i++) {
+ top1 += grid[0][i];
+ long long bottom1 = 0;
+ for (int j = i; j < cols; j++) {
+ bottom1 += grid[1][j];
+ }
+
+ long long top2 = 0, robot2 = 0;
+ for (int j = 0; j < cols; j++) {
+ if (j > i) {
+ top2 += grid[0][j];
+ }
+
+ long long bottom2 = 0;
+ for (int k = j; k < i; k++) {
+ bottom2 += grid[1][k];
+ }
+ robot2 = max(robot2, top2 + bottom2);
+ }
+
+ res = min(res, robot2);
+ }
+
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+ gridGame(grid) {
+ let cols = grid[0].length;
+ let res = Infinity;
+
+ let top1 = 0;
+ for (let i = 0; i < cols; i++) {
+ top1 += grid[0][i];
+ let bottom1 = 0;
+ for (let j = i; j < cols; j++) {
+ bottom1 += grid[1][j];
+ }
+
+ let top2 = 0, robot2 = 0;
+ for (let j = 0; j < cols; j++) {
+ if (j > i) {
+ top2 += grid[0][j];
+ }
+
+ let bottom2 = 0;
+ for (let k = j; k < i; k++) {
+ bottom2 += grid[1][k];
+ }
+ robot2 = Math.max(robot2, top2 + bottom2);
+ }
+
+ res = Math.min(res, robot2);
+ }
+
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n ^ 3)$
+* Space complexity: $O(1)$
+
+---
+
+## 2. Prefix Sum
+
+::tabs-start
+
+```python
+class Solution:
+ def gridGame(self, grid: List[List[int]]) -> int:
+ N = len(grid[0])
+ preRow1, preRow2 = grid[0].copy(), grid[1].copy()
+
+ for i in range(1, N):
+ preRow1[i] += preRow1[i - 1]
+ preRow2[i] += preRow2[i - 1]
+
+ res = float("inf")
+ for i in range(N):
+ top = preRow1[-1] - preRow1[i]
+ bottom = preRow2[i - 1] if i > 0 else 0
+ secondRobot = max(top, bottom)
+ res = min(res, secondRobot)
+ return res
+```
+
+```java
+class Solution {
+ public long gridGame(int[][] grid) {
+ int N = grid[0].length;
+ long[] preRow1 = new long[N];
+ long[] preRow2 = new long[N];
+ for (int i = 0; i < N; i++) {
+ preRow1[i] = (long)grid[0][i];
+ preRow2[i] = (long)grid[1][i];
+ }
+
+ for (int i = 1; i < N; i++) {
+ preRow1[i] += preRow1[i - 1];
+ preRow2[i] += preRow2[i - 1];
+ }
+
+ long res = Long.MAX_VALUE;
+ for (int i = 0; i < N; i++) {
+ long top = preRow1[N - 1] - preRow1[i];
+ long bottom = i > 0 ? preRow2[i - 1] : 0;
+ long secondRobot = Math.max(top, bottom);
+ res = Math.min(res, secondRobot);
+ }
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ long long gridGame(vector>& grid) {
+ int N = grid[0].size();
+ vector preRow1, preRow2;
+ for (int i = 0; i < N; i++) {
+ preRow1.push_back((long)grid[0][i]);
+ preRow2.push_back((long)grid[1][i]);
+ }
+
+ for (int i = 1; i < N; i++) {
+ preRow1[i] += preRow1[i - 1];
+ preRow2[i] += preRow2[i - 1];
+ }
+
+ long long res = LLONG_MAX;
+ for (int i = 0; i < N; i++) {
+ long long top = preRow1[N - 1] - preRow1[i];
+ long long bottom = i > 0 ? preRow2[i - 1] : 0;
+ long long secondRobot = max(top, bottom);
+ res = min(res, secondRobot);
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+ gridGame(grid) {
+ const N = grid[0].length;
+ const preRow1 = [...grid[0]];
+ const preRow2 = [...grid[1]];
+
+ for (let i = 1; i < N; i++) {
+ preRow1[i] += preRow1[i - 1];
+ preRow2[i] += preRow2[i - 1];
+ }
+
+ let res = Infinity;
+ for (let i = 0; i < N; i++) {
+ const top = preRow1[N - 1] - preRow1[i];
+ const bottom = i > 0 ? preRow2[i - 1] : 0;
+ const secondRobot = Math.max(top, bottom);
+ res = Math.min(res, secondRobot);
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(n)$
+
+---
+
+## 3. Prefix Sum (Space Optimized)
+
+::tabs-start
+
+```python
+class Solution:
+ def gridGame(self, grid: List[List[int]]) -> int:
+ res = float("inf")
+ topSum = sum(grid[0])
+ bottomSum = 0
+
+ for i in range(len(grid[0])):
+ topSum -= grid[0][i]
+ res = min(res, max(topSum, bottomSum))
+ bottomSum += grid[1][i]
+
+ return res
+```
+
+```java
+public class Solution {
+ public long gridGame(int[][] grid) {
+ long res = Long.MAX_VALUE;
+ long topSum = 0, bottomSum = 0;
+
+ for (int i = 0; i < grid[0].length; i++) {
+ topSum += grid[0][i];
+ }
+
+ for (int i = 0; i < grid[0].length; i++) {
+ topSum -= grid[0][i];
+ res = Math.min(res, Math.max(topSum, bottomSum));
+ bottomSum += grid[1][i];
+ }
+
+ return res;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ long long gridGame(vector>& grid) {
+ long long res = LLONG_MAX;
+ long long topSum = accumulate(grid[0].begin(), grid[0].end(), 0LL);
+ long long bottomSum = 0;
+
+ for (int i = 0; i < grid[0].size(); i++) {
+ topSum -= grid[0][i];
+ res = min(res, max(topSum, bottomSum));
+ bottomSum += grid[1][i];
+ }
+
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+ gridGame(grid) {
+ let res = Infinity;
+ let topSum = grid[0].reduce((a, b) => a + b, 0);
+ let bottomSum = 0;
+
+ for (let i = 0; i < grid[0].length; i++) {
+ topSum -= grid[0][i];
+ res = Math.min(res, Math.max(topSum, bottomSum));
+ bottomSum += grid[1][i];
+ }
+
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n)$
+* Space complexity: $O(1)$
\ No newline at end of file
diff --git a/articles/intersection-of-two-arrays.md b/articles/intersection-of-two-arrays.md
new file mode 100644
index 000000000..5892704ec
--- /dev/null
+++ b/articles/intersection-of-two-arrays.md
@@ -0,0 +1,566 @@
+## 1. Brute Force
+
+::tabs-start
+
+```python
+class Solution:
+ def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ res = set()
+ for i in nums1:
+ for j in nums2:
+ if i == j:
+ res.add(i)
+ break
+ return list(res)
+```
+
+```java
+public class Solution {
+ public int[] intersection(int[] nums1, int[] nums2) {
+ Set res = new HashSet<>();
+ for (int i : nums1) {
+ for (int j : nums2) {
+ if (i == j) {
+ res.add(i);
+ break;
+ }
+ }
+ }
+ int[] result = new int[res.size()];
+ int idx = 0;
+ for (int num : res) {
+ result[idx++] = num;
+ }
+ return result;
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector intersection(vector& nums1, vector& nums2) {
+ unordered_set res;
+ for (int i : nums1) {
+ for (int j : nums2) {
+ if (i == j) {
+ res.insert(i);
+ break;
+ }
+ }
+ }
+ return vector(res.begin(), res.end());
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number[]}
+ */
+ intersection(nums1, nums2) {
+ const res = new Set();
+ for (const i of nums1) {
+ for (const j of nums2) {
+ if (i === j) {
+ res.add(i);
+ break;
+ }
+ }
+ }
+ return Array.from(res);
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n * m)$
+* Space complexity: $O(n)$
+
+> Where $n$ is the size of the array $nums1$ and $m$ is the size of the array $nums2$.
+
+---
+
+## 2. Sorting + Two Pointers
+
+::tabs-start
+
+```python
+class Solution:
+ def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ nums1.sort()
+ nums2.sort()
+
+ n, m = len(nums1), len(nums2)
+ res, i, j = [], 0, 0
+
+ while i < n and j < m:
+ while j < m and nums2[j] < nums1[i]:
+ j += 1
+ if j < m:
+ if nums1[i] == nums2[j]:
+ res.append(nums1[i])
+ i += 1
+ while i < n and nums1[i] == nums1[i - 1]:
+ i += 1
+
+ return res
+```
+
+```java
+public class Solution {
+ public int[] intersection(int[] nums1, int[] nums2) {
+ Arrays.sort(nums1);
+ Arrays.sort(nums2);
+
+ List res = new ArrayList<>();
+ int i = 0, j = 0;
+
+ while (i < nums1.length && j < nums2.length) {
+ while (j < nums2.length && nums2[j] < nums1[i]) {
+ j++;
+ }
+ if (j < nums2.length) {
+ if (nums1[i] == nums2[j]) {
+ res.add(nums1[i]);
+ }
+ i++;
+ while (i < nums1.length && nums1[i] == nums1[i - 1]) {
+ i++;
+ }
+ }
+ }
+
+ return res.stream().mapToInt(Integer::intValue).toArray();
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector intersection(vector& nums1, vector& nums2) {
+ sort(nums1.begin(), nums1.end());
+ sort(nums2.begin(), nums2.end());
+
+ int n = nums1.size(), m = nums2.size();
+ vector res;
+ int i = 0, j = 0;
+
+ while (i < n && j < m) {
+ while (j < m && nums2[j] < nums1[i]) {
+ ++j;
+ }
+ if (j < m) {
+ if (nums1[i] == nums2[j]) {
+ res.push_back(nums1[i]);
+ }
+ ++i;
+ while (i < n && nums1[i] == nums1[i - 1]) {
+ ++i;
+ }
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number[]}
+ */
+ intersection(nums1, nums2) {
+ nums1.sort((a, b) => a - b);
+ nums2.sort((a, b) => a - b);
+
+ const res = [];
+ let i = 0, j = 0;
+
+ while (i < nums1.length && j < nums2.length) {
+ while (j < nums2.length && nums2[j] < nums1[i]) {
+ j++;
+ }
+ if (j < nums2.length) {
+ if (nums1[i] === nums2[j]) {
+ res.push(nums1[i]);
+ }
+ i++;
+ while (i < nums1.length && nums1[i] === nums1[i - 1]) {
+ i++;
+ }
+ }
+ }
+
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n \log n + m \log m)$
+* Space complexity: $O(n)$
+
+> Where $n$ is the size of the array $nums1$ and $m$ is the size of the array $nums2$.
+
+---
+
+## 3. Hash Set
+
+::tabs-start
+
+```python
+class Solution:
+ def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ set1 = set(nums1)
+ set2 = set(nums2)
+
+ res = []
+ for num in set1:
+ if num in set2:
+ res.append(num)
+ return res
+```
+
+```java
+public class Solution {
+ public int[] intersection(int[] nums1, int[] nums2) {
+ Set set1 = new HashSet<>();
+ for (int num : nums1) {
+ set1.add(num);
+ }
+
+ Set set2 = new HashSet<>();
+ for (int num : nums2) {
+ set2.add(num);
+ }
+
+ List res = new ArrayList<>();
+ for (int num : set1) {
+ if (set2.contains(num)) {
+ res.add(num);
+ }
+ }
+
+ return res.stream().mapToInt(Integer::intValue).toArray();
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector intersection(vector& nums1, vector& nums2) {
+ unordered_set set1(nums1.begin(), nums1.end());
+ unordered_set set2(nums2.begin(), nums2.end());
+
+ vector res;
+ for (int num : set1) {
+ if (set2.find(num) != set2.end()) {
+ res.push_back(num);
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number[]}
+ */
+ intersection(nums1, nums2) {
+ const set1 = new Set(nums1);
+ const set2 = new Set(nums2);
+
+ const res = [];
+ for (const num of set1) {
+ if (set2.has(num)) {
+ res.push(num);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(n + m)$
+
+> Where $n$ is the size of the array $nums1$ and $m$ is the size of the array $nums2$.
+
+---
+
+## 4. Hash Map
+
+::tabs-start
+
+```python
+class Solution:
+ def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ seen = defaultdict(int)
+ for num in nums1:
+ seen[num] = 1
+
+ res = []
+ for num in nums2:
+ if seen[num] == 1:
+ seen[num] = 0
+ res.append(num)
+ return res
+```
+
+```java
+public class Solution {
+ public int[] intersection(int[] nums1, int[] nums2) {
+ Map seen = new HashMap<>();
+ for (int num : nums1) {
+ seen.put(num, 1);
+ }
+
+ List res = new ArrayList<>();
+ for (int num : nums2) {
+ if (seen.getOrDefault(num, 0) == 1) {
+ seen.put(num, 0);
+ res.add(num);
+ }
+ }
+
+ return res.stream().mapToInt(Integer::intValue).toArray();
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector intersection(vector& nums1, vector& nums2) {
+ unordered_map seen;
+ for (int num : nums1) {
+ seen[num] = 1;
+ }
+
+ vector res;
+ for (int num : nums2) {
+ if (seen[num] == 1) {
+ seen[num] = 0;
+ res.push_back(num);
+ }
+ }
+ return res;
+ }
+};
+```
+
+```javascript
+class Solution {
+ /**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number[]}
+ */
+ intersection(nums1, nums2) {
+ const seen = {};
+ for (const num of nums1) {
+ seen[num] = 1;
+ }
+
+ const res = [];
+ for (const num of nums2) {
+ if (seen[num] === 1) {
+ seen[num] = 0;
+ res.push(num);
+ }
+ }
+ return res;
+ }
+}
+```
+
+::tabs-end
+
+### Time & Space Complexity
+
+* Time complexity: $O(n + m)$
+* Space complexity: $O(n)$
+
+> Where $n$ is the size of the array $nums1$ and $m$ is the size of the array $nums2$.
+
+---
+
+## 5. Hash Set (Optimal)
+
+::tabs-start
+
+```python
+class Solution:
+ def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
+ seen = set(nums1)
+
+ res = []
+ for num in nums2:
+ if num in seen:
+ res.append(num)
+ seen.remove(num)
+ return res
+```
+
+```java
+public class Solution {
+ public int[] intersection(int[] nums1, int[] nums2) {
+ Set seen = new HashSet<>();
+ for (int num : nums1) {
+ seen.add(num);
+ }
+
+ List res = new ArrayList<>();
+ for (int num : nums2) {
+ if (seen.contains(num)) {
+ res.add(num);
+ seen.remove(num);
+ }
+ }
+
+ return res.stream().mapToInt(Integer::intValue).toArray();
+ }
+}
+```
+
+```cpp
+class Solution {
+public:
+ vector intersection(vector& nums1, vector