Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
npm run format:json
npm run format:python
35 changes: 35 additions & 0 deletions data/leetcode-problems.json
Original file line number Diff line number Diff line change
Expand Up @@ -26444,5 +26444,40 @@
"title": "Minimum Distance Excluding One Maximum Weighted Edge",
"difficulty": "Medium",
"link": "https://leetcode.com/problems/minimum-distance-excluding-one-maximum-weighted-edge/"
},
"3779": {
"id": 3779,
"category": "Array & Hashing",
"title": "Minimum Number of Operations to Have Distinct Elements",
"difficulty": "Medium",
"link": "https://leetcode.com/problems/minimum-number-of-operations-to-have-distinct-elements/"
},
"3780": {
"id": 3780,
"category": "Array & Hashing",
"title": "Maximum Sum of Three Numbers Divisible by Three",
"difficulty": "Medium",
"link": "https://leetcode.com/problems/maximum-sum-of-three-numbers-divisible-by-three/"
},
"3781": {
"id": 3781,
"category": "Greedy",
"title": "Maximum Score After Binary Swaps",
"difficulty": "Medium",
"link": "https://leetcode.com/problems/maximum-score-after-binary-swaps/"
},
"3783": {
"id": 3783,
"category": "Math & Geometry",
"title": "Mirror Distance of an Integer",
"difficulty": "Easy",
"link": "https://leetcode.com/problems/mirror-distance-of-an-integer/"
},
"3784": {
"id": 3784,
"category": "Greedy",
"title": "Minimum Deletion Cost to Make All Characters Equal",
"difficulty": "Medium",
"link": "https://leetcode.com/problems/minimum-deletion-cost-to-make-all-characters-equal/"
}
}
47 changes: 24 additions & 23 deletions explanations/3774/en.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,59 @@

### Strategy (The "Why")

**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.
**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.

**1.1 Constraints & Complexity:**

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

**1.2 High-level approach:**

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.

![Array sorting and selection visualization](https://assets.leetcode.com/static_assets/others/array-sorting.png)
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.

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

- **Brute Force:** Find k largest and k smallest elements without sorting, which would require multiple passes and be O(n*k) time.
- **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.
- **Optimization:** Sorting allows us to easily identify the k smallest (first k) and k largest (last k) elements in a single operation.
- **Brute Force:** Find the k largest and k smallest elements by scanning the array multiple times, which would be O(n × k) time.
- **Optimized Strategy:** Sort the array once, then directly access the first k and last k elements. This is O(n log n) time.
- **Optimization:** Sorting allows us to efficiently access the k smallest and k largest elements in sorted order, making the solution simple and efficient.

**1.4 Decomposition:**

1. Sort the array in ascending order.
2. Calculate the sum of the first k elements (smallest k).
3. Calculate the sum of the last k elements (largest k).
2. Calculate the sum of the k smallest elements (first k elements).
3. Calculate the sum of the k largest elements (last k elements).
4. Return the absolute difference between these two sums.

### Steps (The "How")

**2.1 Initialization & Example Setup:**

Let's use the example: `nums = [5, 2, 2, 4]`, `k = 2`.
Let's use the example: `nums = [5, 2, 2, 4]`, `k = 2`

- After sorting: `sorted_nums = [2, 2, 4, 5]`
- Original array: `[5, 2, 2, 4]`
- After sorting: `[2, 2, 4, 5]`

**2.2 Start Processing:**

We calculate the sums of the smallest and largest k elements.
We sort the array to easily access the smallest and largest elements.

**2.3 Trace Walkthrough:**

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

**2.4 Increment and Loop:**

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

**2.5 Return Result:**

Expand Down
51 changes: 26 additions & 25 deletions explanations/3775/en.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,61 @@

### Strategy (The "Why")

**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.
**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'.

**1.1 Constraints & Complexity:**

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

**1.2 High-level approach:**

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.

![Word processing visualization](https://assets.leetcode.com/static_assets/others/word-processing.png)
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.

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

- **Brute Force:** Process each word multiple times, counting vowels separately for comparison and reversal, which would be less efficient.
- **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.
- **Optimization:** By processing words in a single pass and reusing the vowel counting logic, we avoid redundant operations.
- **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.
- **Optimized Strategy:** Same approach - split into words, count vowels in first word, then process remaining words. This is O(n) time.
- **Optimization:** By splitting once and processing words sequentially, we avoid multiple string scans and make the solution straightforward.

**1.4 Decomposition:**

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

### Steps (The "How")

**2.1 Initialization & Example Setup:**

Let's use the example: `s = "cat and mice"`.
Let's use the example: `s = "cat and mice"`

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

**2.2 Start Processing:**

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

**2.3 Trace Walkthrough:**

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

**2.4 Increment and Loop:**

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

**2.5 Return Result:**

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.
The result is `"cat dna mice"`, where "and" was reversed to "dna" because it has the same vowel count (1) as "cat".
64 changes: 35 additions & 29 deletions explanations/3776/en.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,70 @@

### Strategy (The "Why")

**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.
**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.

**1.1 Constraints & Complexity:**

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Space complexity is inconsistent with the implementation.

The explanation states O(1) space, but the solution creates a copy with A = balance[:], which is O(n) space. Consider updating the documentation to reflect the actual space usage.

🔎 Suggested fix
-- **Space Complexity:** O(1) - we only use a few variables.
+- **Space Complexity:** O(n) - we create a copy of the balance array.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- **Input Size:** Up to 10^5 elements in the array.
- **Time Complexity:** O(n) where n is the length - we find the negative index once, then expand outward at most n/2 steps.
- **Space Complexity:** O(1) - we only use a few variables.
- **Edge Case:** If all balances are already non-negative, return 0. If the total sum is negative, return -1.
- **Input Size:** Up to 10^5 elements in the array.
- **Time Complexity:** O(n) where n is the length - we find the negative index once, then expand outward at most n/2 steps.
- **Space Complexity:** O(n) - we create a copy of the balance array.
- **Edge Case:** If all balances are already non-negative, return 0. If the total sum is negative, return -1.
🤖 Prompt for AI Agents
In explanations/3776/en.md around lines 9 to 12, the doc claims O(1) space but
the implementation creates a copy with A = balance[:] (O(n)); update the Space
Complexity line to O(n) to match the code, or alternatively remove the array
copy in the implementation and operate in-place to legitimately claim O(1)
space—pick one approach and make the corresponding change (update the text to
O(n) if keeping the copy, or change code to avoid copying if you want O(1)).


**1.2 High-level approach:**

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).

![Circular array balance transfer visualization](https://assets.leetcode.com/static_assets/others/circular-array.png)
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.

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

- **Brute Force:** Try all possible sequences of transfers, which would be exponential and too slow.
- **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.
- **Optimization:** By always using the nearest available positive balance first, we minimize the total distance traveled, which directly minimizes the number of moves needed.
- **Optimized Strategy:** Find the negative index, then expand outward distance by distance, transferring from neighbors at each distance. This is O(n) time.
- **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.

**1.4 Decomposition:**

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

### Steps (The "How")

**2.1 Initialization & Example Setup:**

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

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

**2.2 Start Processing:**

We calculate distances and sort positive balances.
We begin expanding outward from the negative index.

**2.3 Trace Walkthrough:**

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

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

**2.4 Increment and Loop:**

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

**2.5 Return Result:**

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.
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.
68 changes: 68 additions & 0 deletions explanations/3779/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## Explanation

### Strategy (The "Why")

**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.

**1.1 Constraints & Complexity:**

- **Input Size:** Up to 10^5 elements in the array.
- **Time Complexity:** O(n) where n is the length of the array - we process from right to left once.
- **Space Complexity:** O(n) to store the set of seen elements.
- **Edge Case:** If all elements are already distinct, we return 0 without any operations.

**1.2 High-level approach:**

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.

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

- **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.
- **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.
- **Optimization:** By processing from right to left, we can determine the answer without actually performing the removals, making the solution much more efficient.

**1.4 Decomposition:**

1. Process the array from right to left.
2. Use a set to track elements we've seen.
3. For each element from right to left:
- If it's already in the set, we found a duplicate.
- Calculate operations needed: (remaining elements + 2) // 3.
- Return the calculated operations.
4. If no duplicates found, return 0.

### Steps (The "How")

**2.1 Initialization & Example Setup:**

Let's use the example: `nums = [3, 8, 3, 6, 5, 8]`

- Start from right: `8` (last element)
- Seen set: `{8}`
- Process right to left

**2.2 Start Processing:**

We begin processing from the rightmost element, adding each to the seen set.

**2.3 Trace Walkthrough:**

| Step | Element | In Seen? | Action | Seen Set | Remaining Elements |
| ---- | ------- | -------- | ------ | -------- | ------------------ |
| 1 | 8 (rightmost) | No | Add to seen | `{8}` | 5 |
| 2 | 5 | No | Add to seen | `{8, 5}` | 4 |
| 3 | 6 | No | Add to seen | `{8, 5, 6}` | 3 |
| 4 | 3 | No | Add to seen | `{8, 5, 6, 3}` | 2 |
| 5 | 8 | Yes | Found duplicate! | `{8, 5, 6, 3}` | 2 |
| 6 | Calculate | - | `(2 + 2) // 3 = 1` | - | - |

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.

**2.4 Increment and Loop:**

We continue processing from right to left until we find a duplicate or finish processing all elements.

**2.5 Return Result:**

The result is 1, meaning we need 1 operation to remove the first 3 elements, leaving `[6, 5, 8]` which are all distinct.

Loading