Skip to content

Commit 12d5805

Browse files
Merge pull request #127 from romankurnovskii/problems-955-3784-3783-3781-3780-3779-3776-3775-3774-3716
Add solutions and explanations for problems 955, 3784, 3783, 3781, 3780, 3779, 3776, 3775, 3774, 3716
2 parents cef971c + c538d48 commit 12d5805

File tree

390 files changed

+2665
-2120
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

390 files changed

+2665
-2120
lines changed

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
npm run format:json
2+
npm run format:python

data/leetcode-problems.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26444,5 +26444,40 @@
2644426444
"title": "Minimum Distance Excluding One Maximum Weighted Edge",
2644526445
"difficulty": "Medium",
2644626446
"link": "https://leetcode.com/problems/minimum-distance-excluding-one-maximum-weighted-edge/"
26447+
},
26448+
"3779": {
26449+
"id": 3779,
26450+
"category": "Array & Hashing",
26451+
"title": "Minimum Number of Operations to Have Distinct Elements",
26452+
"difficulty": "Medium",
26453+
"link": "https://leetcode.com/problems/minimum-number-of-operations-to-have-distinct-elements/"
26454+
},
26455+
"3780": {
26456+
"id": 3780,
26457+
"category": "Array & Hashing",
26458+
"title": "Maximum Sum of Three Numbers Divisible by Three",
26459+
"difficulty": "Medium",
26460+
"link": "https://leetcode.com/problems/maximum-sum-of-three-numbers-divisible-by-three/"
26461+
},
26462+
"3781": {
26463+
"id": 3781,
26464+
"category": "Greedy",
26465+
"title": "Maximum Score After Binary Swaps",
26466+
"difficulty": "Medium",
26467+
"link": "https://leetcode.com/problems/maximum-score-after-binary-swaps/"
26468+
},
26469+
"3783": {
26470+
"id": 3783,
26471+
"category": "Math & Geometry",
26472+
"title": "Mirror Distance of an Integer",
26473+
"difficulty": "Easy",
26474+
"link": "https://leetcode.com/problems/mirror-distance-of-an-integer/"
26475+
},
26476+
"3784": {
26477+
"id": 3784,
26478+
"category": "Greedy",
26479+
"title": "Minimum Deletion Cost to Make All Characters Equal",
26480+
"difficulty": "Medium",
26481+
"link": "https://leetcode.com/problems/minimum-deletion-cost-to-make-all-characters-equal/"
2644726482
}
2644826483
}

explanations/3774/en.md

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,59 @@
22

33
### Strategy (The "Why")
44

5-
**Restate the problem:** We need to find the absolute difference between the sum of the k largest elements and the sum of the k smallest elements in an array.
5+
**Restate the problem:** We are given an integer array `nums` and an integer `k`. We need to find the absolute difference between the sum of the k largest elements and the sum of the k smallest elements.
66

77
**1.1 Constraints & Complexity:**
88

9-
- **Input Size:** The array length n is at most 100, and each element is between 1 and 100. k is between 1 and n.
10-
- **Time Complexity:** O(n log n) - dominated by sorting the array.
11-
- **Space Complexity:** O(n) for the sorted array.
12-
- **Edge Case:** If k equals the array length, we're comparing the sum of all elements with itself, so the difference is 0.
9+
- **Input Size:** Up to 100 elements in the array, each value between 1 and 100.
10+
- **Time Complexity:** O(n log n) where n is the length of nums - we need to sort the array, which dominates the time complexity.
11+
- **Space Complexity:** O(1) if we sort in-place, or O(n) if we create a sorted copy.
12+
- **Edge Case:** If k equals the array length, we're comparing the sum of all elements with itself, so the result is 0.
1313

1414
**1.2 High-level approach:**
1515

16-
The goal is to sort the array, then calculate the sum of the first k elements (smallest) and the sum of the last k elements (largest), and return their absolute difference.
17-
18-
![Array sorting and selection visualization](https://assets.leetcode.com/static_assets/others/array-sorting.png)
16+
The goal is to sort the array, then take the k largest elements (from the end) and k smallest elements (from the beginning), sum them separately, and return the absolute difference.
1917

2018
**1.3 Brute force vs. optimized strategy:**
2119

22-
- **Brute Force:** Find k largest and k smallest elements without sorting, which would require multiple passes and be O(n*k) time.
23-
- **Optimized Strategy:** Sort the array once in O(n log n) time, then directly access the first k and last k elements. This is simpler and efficient for the given constraints.
24-
- **Optimization:** Sorting allows us to easily identify the k smallest (first k) and k largest (last k) elements in a single operation.
20+
- **Brute Force:** Find the k largest and k smallest elements by scanning the array multiple times, which would be O(n × k) time.
21+
- **Optimized Strategy:** Sort the array once, then directly access the first k and last k elements. This is O(n log n) time.
22+
- **Optimization:** Sorting allows us to efficiently access the k smallest and k largest elements in sorted order, making the solution simple and efficient.
2523

2624
**1.4 Decomposition:**
2725

2826
1. Sort the array in ascending order.
29-
2. Calculate the sum of the first k elements (smallest k).
30-
3. Calculate the sum of the last k elements (largest k).
27+
2. Calculate the sum of the k smallest elements (first k elements).
28+
3. Calculate the sum of the k largest elements (last k elements).
3129
4. Return the absolute difference between these two sums.
3230

3331
### Steps (The "How")
3432

3533
**2.1 Initialization & Example Setup:**
3634

37-
Let's use the example: `nums = [5, 2, 2, 4]`, `k = 2`.
35+
Let's use the example: `nums = [5, 2, 2, 4]`, `k = 2`
3836

39-
- After sorting: `sorted_nums = [2, 2, 4, 5]`
37+
- Original array: `[5, 2, 2, 4]`
38+
- After sorting: `[2, 2, 4, 5]`
4039

4140
**2.2 Start Processing:**
4241

43-
We calculate the sums of the smallest and largest k elements.
42+
We sort the array to easily access the smallest and largest elements.
4443

4544
**2.3 Trace Walkthrough:**
4645

47-
| Step | Operation | Values | Result |
48-
|------|-----------|--------|--------|
49-
| 1 | Sort array | [5, 2, 2, 4] | [2, 2, 4, 5] |
50-
| 2 | Sum of k smallest | sorted_nums[:2] = [2, 2] | 2 + 2 = 4 |
51-
| 3 | Sum of k largest | sorted_nums[2:] = [4, 5] | 4 + 5 = 9 |
52-
| 4 | Absolute difference | \|9 - 4\| | 5 |
46+
| Step | Operation | Value | Description |
47+
| ---- | --------- | ----- | ----------- |
48+
| 1 | Sort array | `[2, 2, 4, 5]` | Sort in ascending order |
49+
| 2 | k smallest | `[2, 2]` | First k=2 elements |
50+
| 3 | Sum smallest | `2 + 2 = 4` | Sum of k smallest |
51+
| 4 | k largest | `[4, 5]` | Last k=2 elements |
52+
| 5 | Sum largest | `4 + 5 = 9` | Sum of k largest |
53+
| 6 | Difference | `abs(9 - 4) = 5` | Absolute difference |
5354

5455
**2.4 Increment and Loop:**
5556

56-
The calculation is straightforward after sorting - no loops needed for the sum calculation.
57+
This is a single-pass operation after sorting, with no additional loop needed.
5758

5859
**2.5 Return Result:**
5960

explanations/3775/en.md

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,61 @@
22

33
### Strategy (The "Why")
44

5-
**Restate the problem:** We need to count the vowels in the first word, then reverse each subsequent word that has the same vowel count as the first word. Words are separated by single spaces.
5+
**Restate the problem:** We are given a string of lowercase English words separated by single spaces. We need to count the vowels in the first word, then reverse each following word that has the same vowel count. Vowels are 'a', 'e', 'i', 'o', and 'u'.
66

77
**1.1 Constraints & Complexity:**
88

9-
- **Input Size:** The string length can be up to 10^5 characters.
10-
- **Time Complexity:** O(n) where n is the string length - we iterate through the string once to split and process words.
11-
- **Space Complexity:** O(n) for storing the words array and result.
12-
- **Edge Case:** If there's only one word, no words need to be reversed, so we return the original string.
9+
- **Input Size:** The string can be up to 10^5 characters long.
10+
- **Time Complexity:** O(n) where n is the length of the string - we process each character once to count vowels and reverse words.
11+
- **Space Complexity:** O(n) to store the words and result string.
12+
- **Edge Case:** If there's only one word, we return it unchanged since there are no following words to process.
1313

1414
**1.2 High-level approach:**
1515

16-
The goal is to process words sequentially: count vowels in the first word, then for each subsequent word, check if it has the same vowel count and reverse it if so.
17-
18-
![Word processing visualization](https://assets.leetcode.com/static_assets/others/word-processing.png)
16+
The goal is to split the string into words, count vowels in the first word, then for each subsequent word, check if it has the same vowel count and reverse it if it does.
1917

2018
**1.3 Brute force vs. optimized strategy:**
2119

22-
- **Brute Force:** Process each word multiple times, counting vowels separately for comparison and reversal, which would be less efficient.
23-
- **Optimized Strategy:** Split the string into words once, count vowels in the first word, then iterate through remaining words, counting vowels and reversing when needed. This is O(n) time.
24-
- **Optimization:** By processing words in a single pass and reusing the vowel counting logic, we avoid redundant operations.
20+
- **Brute Force:** For each word after the first, count its vowels and compare with the first word's count, then reverse if needed. This is O(n) time which is already optimal.
21+
- **Optimized Strategy:** Same approach - split into words, count vowels in first word, then process remaining words. This is O(n) time.
22+
- **Optimization:** By splitting once and processing words sequentially, we avoid multiple string scans and make the solution straightforward.
2523

2624
**1.4 Decomposition:**
2725

2826
1. Split the string into words.
2927
2. Count vowels in the first word.
30-
3. For each subsequent word, count its vowels.
31-
4. If the vowel count matches the first word's count, reverse the word.
32-
5. Join all words back into a string.
28+
3. For each remaining word:
29+
- Count its vowels.
30+
- If the count matches the first word's count, reverse the word.
31+
- Otherwise, keep it unchanged.
32+
4. Join all words back together with spaces.
3333

3434
### Steps (The "How")
3535

3636
**2.1 Initialization & Example Setup:**
3737

38-
Let's use the example: `s = "cat and mice"`.
38+
Let's use the example: `s = "cat and mice"`
3939

40-
- Words: ["cat", "and", "mice"]
41-
- First word: "cat" has 1 vowel ('a')
40+
- Words: `["cat", "and", "mice"]`
41+
- First word: `"cat"` with 1 vowel ('a')
42+
- Result list: `["cat"]`
4243

4344
**2.2 Start Processing:**
4445

45-
We process each word after the first one, checking vowel counts and reversing when needed.
46+
We begin processing words from the second word onwards.
4647

4748
**2.3 Trace Walkthrough:**
4849

49-
| Word | Vowel Count | Matches First? | Action | Result |
50-
|------|-------------|----------------|--------|--------|
51-
| "cat" | 1 | - | Keep as is | "cat" |
52-
| "and" | 1 | Yes | Reverse | "dna" |
53-
| "mice" | 2 | No | Keep as is | "mice" |
50+
| Step | Word | Vowel Count | Matches First? | Action | Result List |
51+
| ---- | ---- | ----------- | -------------- | ------ | ----------- |
52+
| 1 | "cat" | 1 | N/A (first word) | Keep as is | `["cat"]` |
53+
| 2 | "and" | 1 | Yes | Reverse to "dna" | `["cat", "dna"]` |
54+
| 3 | "mice" | 2 | No | Keep as is | `["cat", "dna", "mice"]` |
5455

5556
**2.4 Increment and Loop:**
5657

57-
After processing all words, we join them with spaces.
58+
After processing each word, we move to the next word. We continue until all words are processed.
5859

5960
**2.5 Return Result:**
6061

61-
The result is `"cat dna mice"`, where "and" (1 vowel) was reversed to "dna" because it matches the first word's vowel count, while "mice" (2 vowels) remained unchanged.
62+
The result is `"cat dna mice"`, where "and" was reversed to "dna" because it has the same vowel count (1) as "cat".

explanations/3776/en.md

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,64 +2,70 @@
22

33
### Strategy (The "Why")
44

5-
**Restate the problem:** We have a circular array where each person has a balance. In one move, a person can transfer exactly 1 unit to either neighbor. We need to find the minimum moves to make all balances non-negative. If impossible, return -1.
5+
**Restate the problem:** We are given a circular array `balance` where `balance[i]` is the net balance of person i. In one move, a person can transfer exactly 1 unit to either their left or right neighbor. We need to find the minimum number of moves required so that every person has a non-negative balance. If impossible, return -1.
66

77
**1.1 Constraints & Complexity:**
88

9-
- **Input Size:** The array length n can be up to 10^5, and each balance can be between -10^9 and 10^9.
10-
- **Time Complexity:** O(n log n) - we need to sort positive balances by distance, which dominates the complexity.
11-
- **Space Complexity:** O(n) for storing positive balances with their distances.
12-
- **Edge Case:** If the total sum is negative, it's impossible to make all balances non-negative, so return -1.
9+
- **Input Size:** Up to 10^5 elements in the array.
10+
- **Time Complexity:** O(n) where n is the length - we find the negative index once, then expand outward at most n/2 steps.
11+
- **Space Complexity:** O(1) - we only use a few variables.
12+
- **Edge Case:** If all balances are already non-negative, return 0. If the total sum is negative, return -1.
1313

1414
**1.2 High-level approach:**
1515

16-
The goal is to transfer balance from positive positions to the negative position, using the nearest positive balances first to minimize the total transfer distance (and thus moves).
17-
18-
![Circular array balance transfer visualization](https://assets.leetcode.com/static_assets/others/circular-array.png)
16+
The goal is to find the index with negative balance, then greedily transfer from neighbors at increasing distances until the negative balance is covered. We expand outward from the negative index, using the closest positive balances first.
1917

2018
**1.3 Brute force vs. optimized strategy:**
2119

2220
- **Brute Force:** Try all possible sequences of transfers, which would be exponential and too slow.
23-
- **Optimized Strategy:** Use a greedy approach: find the negative balance, collect all positive balances with their distances from the negative position, sort by distance, and greedily transfer from nearest to farthest. This is O(n log n) time.
24-
- **Optimization:** By always using the nearest available positive balance first, we minimize the total distance traveled, which directly minimizes the number of moves needed.
21+
- **Optimized Strategy:** Find the negative index, then expand outward distance by distance, transferring from neighbors at each distance. This is O(n) time.
22+
- **Optimization:** By expanding outward from the negative index, we minimize the transfer distance. The cost is transfer_amount × distance, so using closer neighbors first minimizes the total cost.
2523

2624
**1.4 Decomposition:**
2725

28-
1. Check if total sum is negative - if so, return -1.
29-
2. Find the index with negative balance.
30-
3. If no negative balance exists, return 0.
31-
4. Collect all positive balances with their circular distances from the negative position.
32-
5. Sort positive balances by distance.
33-
6. Greedily transfer from nearest positives until the negative balance is covered.
34-
7. Return the total moves (sum of transfer_amount * distance).
26+
1. Find the index with negative balance (there's at most one).
27+
2. If all balances are non-negative, return 0.
28+
3. If total sum is negative, return -1 (impossible).
29+
4. Expand outward from the negative index:
30+
- At distance d, get storage from neighbors at positions (j+d) and (j-d) modulo n.
31+
- Transfer the minimum of the debt and available storage.
32+
- Add transfer × distance to the result.
33+
- Update the balance at the negative index.
34+
5. Continue until the negative balance is covered.
3535

3636
### Steps (The "How")
3737

3838
**2.1 Initialization & Example Setup:**
3939

40-
Let's use the example: `balance = [5, 1, -4]`, `n = 3`.
40+
Let's use the example: `balance = [5, 1, -4]`
4141

42-
- Total sum: 5 + 1 + (-4) = 2 (non-negative, so possible)
43-
- Negative balance at index 2, amount: 4
44-
- Positive balances: index 0 (amount 5, distance 1), index 1 (amount 1, distance 1)
42+
- Negative index: `j = 2` (balance[2] = -4)
43+
- Total sum: 5 + 1 + (-4) = 2 (positive, so possible)
44+
- Distance `d = 0` initially
4545

4646
**2.2 Start Processing:**
4747

48-
We calculate distances and sort positive balances.
48+
We begin expanding outward from the negative index.
4949

5050
**2.3 Trace Walkthrough:**
5151

52-
| Positive Index | Amount | Distance from Index 2 | Sorted Order |
53-
|----------------|--------|----------------------|--------------|
54-
| 0 | 5 | min(\|0-2\|, 3-\|0-2\|) = min(2, 1) = 1 | 1st (tie) |
55-
| 1 | 1 | min(\|1-2\|, 3-\|1-2\|) = min(1, 2) = 1 | 1st (tie) |
52+
| Step | d | Neighbors | Storage | Debt | Transfer | Cost | Balance at j |
53+
| ---- | - | --------- | ------- | ---- | -------- | ---- | ------------- |
54+
| 1 | 1 | (2+1)%3=0, (2-1)%3=1 | 5 + 1 = 6 | 4 | min(4, 6) = 4 | 4 × 1 = 4 | -4 + 4 = 0 |
5655

57-
We need 4 units total. We can take from index 0 (distance 1): transfer 4 units, cost = 4 * 1 = 4 moves.
56+
At distance 1:
57+
- Neighbor at (2+1) % 3 = 0: balance[0] = 5
58+
- Neighbor at (2-1) % 3 = 1: balance[1] = 1
59+
- Total storage: 5 + 1 = 6
60+
- Debt: 4
61+
- Transfer: min(4, 6) = 4
62+
- Cost: 4 × 1 = 4
63+
- New balance at j: -4 + 4 = 0
5864

5965
**2.4 Increment and Loop:**
6066

61-
After transferring from all necessary positive positions, we calculate the total moves.
67+
We increment the distance and continue until the negative balance is covered.
6268

6369
**2.5 Return Result:**
6470

65-
The result is 4, which is the minimum number of moves needed. We transfer 4 units from index 0 (distance 1) to index 2, requiring 4 moves.
71+
The result is 4, which is the minimum number of moves required. We transfer 4 units from the neighbors at distance 1, with a cost of 4 moves.

explanations/3779/en.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
## Explanation
2+
3+
### Strategy (The "Why")
4+
5+
**Restate the problem:** We are given an integer array. In one operation, we remove the first three elements (or all remaining if fewer than three). We repeat until the array is empty or contains no duplicate values. We need to find the minimum number of operations required.
6+
7+
**1.1 Constraints & Complexity:**
8+
9+
- **Input Size:** Up to 10^5 elements in the array.
10+
- **Time Complexity:** O(n) where n is the length of the array - we process from right to left once.
11+
- **Space Complexity:** O(n) to store the set of seen elements.
12+
- **Edge Case:** If all elements are already distinct, we return 0 without any operations.
13+
14+
**1.2 High-level approach:**
15+
16+
The goal is to process the array from right to left, tracking which elements we've seen. If we encounter a duplicate while going right to left, we know we need to remove elements from the left. The number of operations needed is calculated based on how many elements remain.
17+
18+
**1.3 Brute force vs. optimized strategy:**
19+
20+
- **Brute Force:** Simulate the operations step by step, removing first 3 elements each time and checking for duplicates. This could be O(n^2) in worst case.
21+
- **Optimized Strategy:** Process from right to left, use a set to track seen elements. When we find a duplicate, calculate operations needed: (remaining elements + 2) // 3. This is O(n) time.
22+
- **Optimization:** By processing from right to left, we can determine the answer without actually performing the removals, making the solution much more efficient.
23+
24+
**1.4 Decomposition:**
25+
26+
1. Process the array from right to left.
27+
2. Use a set to track elements we've seen.
28+
3. For each element from right to left:
29+
- If it's already in the set, we found a duplicate.
30+
- Calculate operations needed: (remaining elements + 2) // 3.
31+
- Return the calculated operations.
32+
4. If no duplicates found, return 0.
33+
34+
### Steps (The "How")
35+
36+
**2.1 Initialization & Example Setup:**
37+
38+
Let's use the example: `nums = [3, 8, 3, 6, 5, 8]`
39+
40+
- Start from right: `8` (last element)
41+
- Seen set: `{8}`
42+
- Process right to left
43+
44+
**2.2 Start Processing:**
45+
46+
We begin processing from the rightmost element, adding each to the seen set.
47+
48+
**2.3 Trace Walkthrough:**
49+
50+
| Step | Element | In Seen? | Action | Seen Set | Remaining Elements |
51+
| ---- | ------- | -------- | ------ | -------- | ------------------ |
52+
| 1 | 8 (rightmost) | No | Add to seen | `{8}` | 5 |
53+
| 2 | 5 | No | Add to seen | `{8, 5}` | 4 |
54+
| 3 | 6 | No | Add to seen | `{8, 5, 6}` | 3 |
55+
| 4 | 3 | No | Add to seen | `{8, 5, 6, 3}` | 2 |
56+
| 5 | 8 | Yes | Found duplicate! | `{8, 5, 6, 3}` | 2 |
57+
| 6 | Calculate | - | `(2 + 2) // 3 = 1` | - | - |
58+
59+
When we find duplicate 8 at position 1 (0-indexed), we have 2 elements remaining (indices 0 and 1). Operations needed: (2 + 2) // 3 = 1.
60+
61+
**2.4 Increment and Loop:**
62+
63+
We continue processing from right to left until we find a duplicate or finish processing all elements.
64+
65+
**2.5 Return Result:**
66+
67+
The result is 1, meaning we need 1 operation to remove the first 3 elements, leaving `[6, 5, 8]` which are all distinct.
68+

0 commit comments

Comments
 (0)