Skip to content

Commit 6391d3e

Browse files
authored
Update articles (#5045)
1 parent ad648c5 commit 6391d3e

13 files changed

+911
-0
lines changed

articles/anagram-groups.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
## 1. Sorting
22

3+
### Intuition
4+
5+
Anagrams become identical when their characters are sorted.
6+
For example, `"eat"`, `"tea"`, and `"ate"` all become `"aet"` after sorting.
7+
By using the sorted version of each string as a key, we can group all anagrams together.
8+
Strings that share the same sorted form must be anagrams, so placing them in the same group is both natural and efficient.
9+
10+
### Algorithm
11+
12+
1. Create a hash map where each key is the sorted version of a string, and the value is a list of strings belonging to that anagram group.
13+
2. Iterate through each string in the input list:
14+
- Sort the characters of the string to form a key.
15+
- Append the original string to the list corresponding to this key.
16+
3. After processing all strings, return all values from the hash map, which represent the grouped anagrams.
17+
318
::tabs-start
419

520
```python
@@ -153,6 +168,23 @@ class Solution {
153168

154169
## 2. Hash Table
155170

171+
### Intuition
172+
173+
Instead of sorting each string, we can represent every string by the frequency of its characters.
174+
Since the problem uses lowercase English letters, a fixed-size array of length `26` can capture how many times each character appears.
175+
Two strings are anagrams if and only if their frequency arrays are identical.
176+
By using this frequency array (converted to a tuple so it can be a dictionary key), we can group all strings that share the same character counts.
177+
178+
### Algorithm
179+
180+
1. Create a hash map where each key is a `26`-length tuple representing character frequencies, and each value is a list of strings belonging to that anagram group.
181+
2. For each string in the input:
182+
- Initialize a frequency array of size `26` with all zeros.
183+
- For each character in the string, increment the count at the corresponding index.
184+
- Convert the frequency array to a tuple and use it as the key.
185+
- Append the string to the list associated with this key.
186+
3. After processing all strings, return all the lists stored in the hash map.
187+
156188
::tabs-start
157189

158190
```python

articles/duplicate-integer.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
## 1. Brute Force
22

3+
### Intuition
4+
5+
We can check every pair of different elements in the array and return `true` if any pair has equal values.
6+
This is the most intuitive approach because it directly compares all possible pairs, but it is also the least efficient since it examines every combination.
7+
8+
### Algorithm
9+
10+
1. Iterate through the array using two nested loops to check all possible pairs of distinct indices.
11+
2. If any pair of elements has the same value, return `true`.
12+
3. If all pairs are checked and no duplicates are found, return `false`.
13+
314
::tabs-start
415

516
```python
@@ -131,6 +142,20 @@ class Solution {
131142

132143
## 2. Sorting
133144

145+
### Intuition
146+
147+
If we sort the array, then any duplicate values will appear next to each other.
148+
Sorting groups identical elements together, so we can simply check adjacent positions to detect duplicates.
149+
This reduces the problem to a single linear scan after sorting, making it easy to identify if any value repeats.
150+
151+
### Algorithm
152+
153+
1. Sort the array in non-decreasing order.
154+
2. Iterate through the array starting from index `1`.
155+
3. Compare the current element with the previous element.
156+
4. If both elements are equal, we have found a duplicate — return `True`.
157+
5. If the loop finishes without detecting equal neighbors, return `False`.
158+
134159
::tabs-start
135160

136161
```python
@@ -255,6 +280,22 @@ class Solution {
255280

256281
## 3. Hash Set
257282

283+
### Intuition
284+
285+
We can use a hash set to efficiently keep track of the values we have already encountered.
286+
As we iterate through the array, we check whether the current value is already present in the set.
287+
If it is, that means we've seen this value before, so a duplicate exists.
288+
Using a hash set allows constant-time lookups, making this approach much more efficient than comparing every pair.
289+
290+
### Algorithm
291+
292+
1. Initialize an empty hash set to store seen values.
293+
2. Iterate through each number in the array.
294+
3. For each number:
295+
- If it is already in the set, return `True` because a duplicate has been found.
296+
- Otherwise, add it to the set.
297+
4. If the loop finishes without finding any duplicates, return `False`.
298+
258299
::tabs-start
259300

260301
```python
@@ -387,6 +428,20 @@ class Solution {
387428

388429
## 4. Hash Set Length
389430

431+
### Intuition
432+
433+
This approach uses the same idea as the previous hash set method: a set only stores unique values, so duplicates are automatically removed.
434+
Instead of checking each element manually, we simply compare the length of the set to the length of the original array.
435+
If duplicates exist, the set will contain fewer elements.
436+
The logic is identical to the earlier approach — this version is just a shorter and more concise implementation of it.
437+
438+
### Algorithm
439+
440+
1. Convert the array into a hash set, which removes duplicates.
441+
2. Compare the size of the set with the size of the original array.
442+
3. If the set is smaller, return `True` because duplicates must have been removed.
443+
4. Otherwise, return `False`.
444+
390445
::tabs-start
391446

392447
```python

articles/is-anagram.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
## 1. Sorting
22

3+
### Intuition
4+
5+
If two strings are anagrams, they must contain exactly the same characters with the same frequencies.
6+
By sorting both strings, all characters will be arranged in a consistent order.
7+
If the two sorted strings are identical, then every character and its count match, which means the strings are anagrams.
8+
9+
### Algorithm
10+
11+
1. If the lengths of the two strings differ, return `False` immediately because they cannot be anagrams.
12+
2. Sort both strings.
13+
3. Compare the sorted versions of the strings:
14+
- If they are equal, return `True`.
15+
- Otherwise, return `False`.
16+
317
::tabs-start
418

519
```python
@@ -133,6 +147,24 @@ class Solution {
133147

134148
## 2. Hash Map
135149

150+
### Intuition
151+
152+
If two strings are anagrams, they must use the same characters with the same frequencies.
153+
Instead of sorting, we can count how many times each character appears in both strings.
154+
By using two hash maps (or dictionaries), we track the frequency of every character in each string.
155+
If both frequency maps match exactly, then the strings contain the same characters with same frequencies, meaning they are anagrams.
156+
157+
### Algorithm
158+
159+
1. If the two strings have different lengths, return `False` immediately.
160+
2. Create two hash maps to store character frequencies for each string.
161+
3. Iterate through both strings at the same time:
162+
- Increase the character count for `s[i]` in the first map.
163+
- Increase the character count for `t[i]` in the second map.
164+
4. After building both maps, compare them:
165+
- If the maps are equal, return `True`.
166+
- Otherwise, return `False`.
167+
136168
::tabs-start
137169

138170
```python
@@ -310,6 +342,24 @@ class Solution {
310342

311343
## 3. Hash Table (Using Array)
312344

345+
### Intuition
346+
347+
Since the problem guarantees lowercase English letters, we can use a fixed-size array of length `26` to count character frequencies instead of a hash map.
348+
As we iterate through both strings simultaneously, we increment the count for each character in `s` and decrement the count for each character in `t`.
349+
If the strings are anagrams, every increment will be matched by a corresponding decrement, and all values in the array will end at zero.
350+
This approach is efficient because it avoids hashing and uses constant space.
351+
352+
### Algorithm
353+
354+
1. If the lengths of the strings differ, return `False` immediately.
355+
2. Create a frequency array `count` of size `26` initialized to zero.
356+
3. Iterate through both strings:
357+
- Increment the count at the index corresponding to `s[i]`.
358+
- Decrement the count at the index corresponding to `t[i]`.
359+
4. After processing both strings, scan through the `count` array:
360+
- If any value is not zero, return `False` because the frequencies differ.
361+
5. If all values are zero, return `True` since the strings are anagrams.
362+
313363
::tabs-start
314364

315365
```python

articles/is-palindrome.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
## 1. Reverse String
22

3+
### Intuition
4+
5+
To check if a string is a palindrome, we only care about letters and digits—everything else can be ignored.
6+
We can build a cleaned version of the string that contains only alphanumeric characters, all converted to lowercase for consistency.
7+
Once we have this cleaned string, the problem becomes very simple:
8+
a string is a palindrome if it is exactly the same as its reverse.
9+
10+
### Algorithm
11+
12+
1. Create an empty string `newStr`.
13+
2. Loop through each character `c` in the input string:
14+
- If `c` is alphanumeric, convert it to lowercase and add it to `newStr`.
15+
3. Compare `newStr` with its reverse (`newStr[::-1]`):
16+
- If they are equal, return `True`.
17+
- Otherwise, return `False`.
18+
319
::tabs-start
420

521
```python
@@ -152,6 +168,28 @@ class Solution {
152168

153169
## 2. Two Pointers
154170

171+
### Intuition
172+
173+
Instead of building a new string, we can check the palindrome directly in-place using two pointers.
174+
One pointer starts at the beginning (`l`) and the other at the end (`r`).
175+
We move both pointers inward, skipping any characters that are not letters or digits.
176+
Whenever both pointers point to valid characters, we compare them in lowercase form.
177+
If at any point they differ, the string is not a palindrome.
178+
This method avoids extra space and keeps the logic simple and efficient.
179+
180+
### Algorithm
181+
182+
1. Initialize two pointers:
183+
- `l` at the start of the string,
184+
- `r` at the end of the string.
185+
2. While `l` is less than `r`:
186+
- Move `l` forward until it points to an alphanumeric character.
187+
- Move `r` backward until it points to an alphanumeric character.
188+
- Compare the lowercase characters at `l` and `r`:
189+
- If they don’t match, return `False`.
190+
- Move both pointers inward: `l += 1`, `r -= 1`.
191+
3. If the loop finishes without mismatches, return `True`.
192+
155193
::tabs-start
156194

157195
```python

articles/longest-consecutive-sequence.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
## 1. Brute Force
22

3+
### Intuition
4+
5+
A consecutive sequence grows by checking whether the next number (`num + 1`, `num + 2`, …) exists in the set.
6+
The brute-force approach simply starts from every number in the list and tries to extend a consecutive streak as far as possible.
7+
For each number, we repeatedly check if the next number exists, increasing the streak length until the sequence breaks.
8+
Even though this method works, it does unnecessary repeated work because many sequences get recomputed multiple times.
9+
10+
### Algorithm
11+
12+
1. Convert the input list to a set for **O(1)** lookups.
13+
2. Initialize `res` to store the maximum streak length.
14+
3. For each number `num` in the original list:
15+
- Start a new streak count at 0.
16+
- Set `curr = num`.
17+
- While `curr` exists in the set:
18+
- Increase the streak count.
19+
- Move to the next number (`curr += 1`).
20+
- Update `res` with the longest streak found so far.
21+
4. Return `res` after checking all numbers.
22+
323
::tabs-start
424

525
```python
@@ -178,6 +198,33 @@ class Solution {
178198

179199
## 2. Sorting
180200

201+
### Intuition
202+
203+
If we sort the numbers first, then all consecutive values will appear next to each other.
204+
This makes it easy to walk through the sorted list and count how long each consecutive sequence is.
205+
We simply move forward while the current number matches the expected next value in the sequence.
206+
Duplicates don’t affect the result—they are just skipped—while gaps reset the streak count.
207+
This approach is simpler and more organized than the brute force method because sorting places all potential sequences in order.
208+
209+
### Algorithm
210+
211+
1. If the input list is empty, return `0`.
212+
2. Sort the array in non-decreasing order.
213+
3. Initialize:
214+
- `res` to track the longest streak,
215+
- `curr` as the first number,
216+
- `streak` as `0`,
217+
- index `i = 0`.
218+
4. While `i` is within bounds:
219+
- If `nums[i]` does not match `curr`, reset:
220+
- `curr = nums[i]`
221+
- `streak = 0`
222+
- Skip over all duplicates of `curr` by advancing `i` while `nums[i] == curr`.
223+
- Increase `streak` by `1` since we found the expected number.
224+
- Increase `curr` by `1` to expect the next number in the sequence.
225+
- Update `res` with the maximum streak found so far.
226+
5. Return `res` after scanning the entire list.
227+
181228
::tabs-start
182229

183230
```python
@@ -413,6 +460,27 @@ class Solution {
413460

414461
## 3. Hash Set
415462

463+
### Intuition
464+
465+
To avoid repeatedly recounting the same sequences, we only want to start counting when we find the **beginning** of a consecutive sequence.
466+
A number is the start of a sequence if `num - 1` is **not** in the set.
467+
This guarantees that each consecutive sequence is counted exactly once.
468+
469+
Once we identify such a starting number, we simply keep checking if `num + 1`, `num + 2`, … exist in the set and extend the streak as far as possible.
470+
This makes the solution efficient and clean because each number contributes to the sequence only one time.
471+
472+
### Algorithm
473+
474+
1. Convert the list into a set `numSet` for O(1) lookups.
475+
2. Initialize `longest` to track the length of the longest consecutive sequence.
476+
3. For each number `num` in `numSet`:
477+
- Check if `num - 1` is **not** in the set:
478+
- If true, `num` is the start of a sequence.
479+
- Initialize `length = 1`.
480+
- While `num + length` exists in the set, increase `length`.
481+
- Update `longest` with the maximum length found.
482+
4. Return `longest` after scanning all numbers.
483+
416484
::tabs-start
417485

418486
```python
@@ -597,6 +665,33 @@ class Solution {
597665

598666
## 4. Hash Map
599667

668+
### Intuition
669+
670+
When we place a new number into the map, it may connect two existing sequences or extend one of them.
671+
Instead of scanning forward or backward, we only look at the lengths stored at the **neighbors**:
672+
673+
- `mp[num - 1]` gives the length of the sequence ending right before `num`
674+
- `mp[num + 1]` gives the length of the sequence starting right after `num`
675+
676+
By adding these together and including the current number, we know the total length of the new merged sequence.
677+
We then update the **left boundary** and **right boundary** of this sequence so the correct length can be retrieved later.
678+
This keeps the whole operation very efficient and avoids repeated work.
679+
680+
### Algorithm
681+
682+
1. Create a hash map `mp` that stores sequence lengths at boundary positions.
683+
2. Initialize `res = 0` to store the longest sequence found.
684+
3. For each number `num` in the input:
685+
- If `num` is already in `mp`, skip it.
686+
- Compute the new sequence length:
687+
- `length = mp[num - 1] + mp[num + 1] + 1`
688+
- Store this length at `num`.
689+
- Update the boundaries:
690+
- Left boundary: `mp[num - mp[num - 1]] = length`
691+
- Right boundary: `mp[num + mp[num + 1]] = length`
692+
- Update `res` to keep track of the longest sequence.
693+
4. Return `res` after processing all numbers.
694+
600695
::tabs-start
601696

602697
```python

0 commit comments

Comments
 (0)