Skip to content
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions explanations/2119/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
## 2119. Minimum Number of Operations to Make Array Continuous [Hard]

https://leetcode.com/problems/minimum-number-of-operations-to-make-array-continuous

## Description
You are given an integer array `nums`. In one operation, you can replace **any** element in `nums` with **any** integer.

`nums` is considered **continuous** if both of the following conditions are fulfilled:

- All elements in `nums` are **unique**.
- The difference between the **maximum** element and the **minimum** element in `nums` equals `nums.length - 1`.

For example, `nums = [4, 2, 5, 3]` is **continuous**, but `nums = [1, 2, 3, 5, 6]` is **not continuous**.

Return *the **minimum** number of operations to make* `nums` **continuous**.

**Examples**

```tex
Example 1:
Input: nums = [4,2,5,3]
Output: 0
Explanation: nums is already continuous.

Example 2:
Input: nums = [1,2,3,5,6]
Output: 1
Explanation: One possible solution is to change the last element to 4.
The resulting array is [1,2,3,5,4], which is continuous.

Example 3:
Input: nums = [1,10,100,1000]
Output: 3
Explanation: One possible solution is to:
- Change the second element to 2.
- Change the third element to 3.
- Change the fourth element to 4.
The resulting array is [1,2,3,4], which is continuous.
```

**Constraints**
```tex
- 1 <= nums.length <= 10^5
- 1 <= nums[i] <= 10^9
```

## Explanation

### Strategy
Let's restate the problem: You're given an array, and you need to find the minimum number of operations to make it continuous. A continuous array has unique elements where the difference between max and min equals the length minus 1.

This is a **sliding window problem** that requires understanding what makes an array continuous and finding the optimal window of elements to keep.

**What is given?** An array of integers that can be very large (up to 100,000 elements).

**What is being asked?** Find the minimum operations to make the array continuous.

**Constraints:** The array can be up to 100,000 elements long, with values up to 10⁹.

**Edge cases:**
- Single element array
- Already continuous array
- Array with all identical values
- Very large gaps between elements

**High-level approach:**
The solution involves sorting the array and using a sliding window approach to find the optimal subset of elements that can form a continuous array with minimal operations.

**Decomposition:**
1. **Sort the array**: This helps us identify potential continuous subsequences
2. **Use sliding window**: Find the longest window that can be made continuous
3. **Calculate operations**: Determine how many elements need to be changed
4. **Find minimum**: Try different window sizes to find the optimal solution

**Brute force vs. optimized strategy:**
- **Brute force**: Try all possible subsets. This is extremely inefficient.
- **Optimized**: Use sliding window with binary search. This takes O(n log n) time.

Comment on lines +66 to +78
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Doc states sliding-window O(n log n), but code is quadratic — align code or doc

Current implementation is O(u^2). Either adopt the two-pointer change (preferred) or revise this section to note the actual complexity of the provided code.

🧰 Tools
🪛 LanguageTool

[grammar] ~66-~66: There might be a mistake here.
Context: ...tween elements High-level approach: The solution involves sorting the array ...

(QB_NEW_EN)


[grammar] ~69-~69: There might be a mistake here.
Context: ...th minimal operations. Decomposition: 1. Sort the array: This helps us identify...

(QB_NEW_EN)

🤖 Prompt for AI Agents
explanations/2119/en.md around lines 66 to 78: the doc claims an O(n log n)
sliding-window approach but the implemented algorithm is O(u^2); fix by
replacing the quadratic nested-loop section with a true two-pointer
sliding-window: after sorting (O(n log n)) maintain left and right pointers,
advance right while the window can be made continuous, move left when it cannot,
and update the best window length to compute minimal operations; alternatively,
if you prefer to keep the current implementation, change the text to explicitly
state the actual O(u^2) complexity and remove the misleading O(n log n) claim.

### Steps
Let's walk through the solution step by step using the second example: `nums = [1,2,3,5,6]`

**Step 1: Sort the array**
- Original: [1,2,3,5,6]
- Sorted: [1,2,3,5,6] (already sorted)

**Step 2: Understand what makes an array continuous**
- For length 5, we need: max - min = 5 - 1 = 4
- So we need elements that span exactly 4 values
- Example: [1,2,3,4,5] has max=5, min=1, difference=4 ✓

**Step 3: Use sliding window approach**
- Start with window size = array length
- Try to find a window that can be made continuous
- For each window, calculate how many operations are needed

**Step 4: Calculate operations for different windows**
Comment on lines +91 to +96
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Clarify the algorithm and fix MD036

Describe the two-pointer window on unique values; convert bold to headings.

-**Step 3: Use sliding window approach**
-- Start with window size = array length
-- Try to find a window that can be made continuous
-- For each window, calculate how many operations are needed
+#### Step 3: Two-pointer sliding window on unique values
+- Let n = nums.length. After sorting and deduping to `unique`, keep pointers i and j.
+- While j < len(unique) and unique[j] <= unique[i] + n - 1, advance j.
+- Keep = j - i (values we can keep); ops = n - Keep. Then increment i; j never moves backward.
@@
-**Step 4: Calculate operations for different windows**
+#### Step 4: Calculate operations for different windows
📝 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
**Step 3: Use sliding window approach**
- Start with window size = array length
- Try to find a window that can be made continuous
- For each window, calculate how many operations are needed
**Step 4: Calculate operations for different windows**
#### Step 3: Two-pointer sliding window on unique values
- Let n = nums.length. After sorting and deduping to `unique`, keep pointers i and j.
- While j < len(unique) and unique[j] <= unique[i] + n - 1, advance j.
- Keep = j - i (values we can keep); ops = n - Keep. Then increment i; j never moves backward.
#### Step 4: Calculate operations for different windows
🧰 Tools
🪛 LanguageTool

[grammar] ~91-~91: There might be a mistake here.
Context: ...max=5, min=1, difference=4 ✓ Step 3: Use sliding window approach - Start with ...

(QB_NEW_EN)


[grammar] ~92-~92: There might be a mistake here.
Context: ...: Use sliding window approach** - Start with window size = array length - Try to fin...

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.17.2)

91-91: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


96-96: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🤖 Prompt for AI Agents
In explanations/2119/en.md around lines 91 to 96, replace the bold step markers
with proper Markdown headings (e.g., "## Step 3: Use sliding window approach"
and "## Step 4: Calculate operations for different windows") to satisfy MD036
and improve structure, and add a concise explanation of the algorithm: build a
frequency map and sorted list of unique values, use a two‑pointer window on the
unique values (advance r while nums[r] - nums[l] <= windowRange), maintain the
sum of counts inside the window, and for each window compute operations as
total_elements - sum_counts_in_window, tracking the minimum; preserve existing
numbered steps and examples.

- **Window [1,2,3,5,6]**:
- Current span: 6 - 1 = 5
- Need span: 5 - 1 = 4
- Gap: 5 - 4 = 1
- Operations needed: 1 (change 6 to 4)

- **Window [1,2,3,5]**:
- Current span: 5 - 1 = 4
- Need span: 4 - 1 = 3
- Gap: 4 - 3 = 1
- Operations needed: 1 (change 5 to 3)

- **Window [2,3,5,6]**:
- Current span: 6 - 2 = 4
- Need span: 4 - 1 = 3
- Gap: 4 - 3 = 1
- Operations needed: 1 (change 6 to 4)

**Step 5: Find optimal solution**
- Minimum operations: 1
- Optimal window: [1,2,3,5] → change 5 to 4 → [1,2,3,4]

**Why this works:**
The sliding window approach works because:
1. **Optimal substructure**: The best solution for a larger array must include the best solution for a smaller subarray
2. **Monotonicity**: If a window of size k can be made continuous, then a window of size k-1 can also be made continuous
3. **Efficiency**: We only need to check O(n) different window sizes instead of all possible subsets

> **Note:** The key insight is that we can use a sliding window to find the longest subsequence that can be made continuous, and then calculate the minimum operations needed. This avoids the need to try all possible combinations.

**Time Complexity:** O(n log n) - sorting takes O(n log n), sliding window takes O(n)
**Space Complexity:** O(1) - we only need a few variables for the sliding window
50 changes: 50 additions & 0 deletions solutions/2119/01.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
def minOperations(nums):
"""
Find the minimum number of operations to make the array continuous.

Args:
nums: List[int] - Array of integers

Returns:
int - Minimum number of operations needed
"""
# Handle edge case
if len(nums) <= 1:
return 0

# Sort the array to work with ordered elements
nums.sort()

# Remove duplicates to work with unique elements
unique_nums = []
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (code-quality): Convert for loop into list comprehension (list-comprehension)

for i, num in enumerate(nums):
if i == 0 or num != nums[i-1]:
unique_nums.append(num)

n = len(unique_nums)
min_operations = float('inf')

# Try different window sizes
for i in range(n):
# For each starting position, find the longest window that can be made continuous
left = unique_nums[i]

# Binary search for the rightmost element that can be part of a continuous sequence
Comment on lines +29 to +32
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (performance): Binary search could replace the inner loop for efficiency.

Consider using bisect_right to efficiently find the rightmost element in the window, which will improve performance for large datasets.

# starting from left
right = left + len(nums) - 1

# Find how many elements in unique_nums fall within [left, right]
# This gives us the size of the window that can be made continuous
count = 0
for j in range(i, n):
if unique_nums[j] <= right:
count += 1
else:
break

# Calculate operations needed
# We need to change (len(nums) - count) elements
operations = len(nums) - count
min_operations = min(min_operations, operations)

return min_operations
Comment on lines +27 to +50
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Replace O(u^2) scan with true sliding window (two pointers) to meet 1e5 constraint

The inner loop makes this O(u^2) in unique values and will TLE. Use two pointers so j never moves backward; overall O(u) after sort. Also removes the inaccurate “Binary search” comment.

-    n = len(unique_nums)
-    min_operations = float('inf')
-    
-    # Try different window sizes
-    for i in range(n):
-        # For each starting position, find the longest window that can be made continuous
-        left = unique_nums[i]
-        
-        # Binary search for the rightmost element that can be part of a continuous sequence
-        # starting from left
-        right = left + len(nums) - 1
-        
-        # Find how many elements in unique_nums fall within [left, right]
-        # This gives us the size of the window that can be made continuous
-        count = 0
-        for j in range(i, n):
-            if unique_nums[j] <= right:
-                count += 1
-            else:
-                break
-        
-        # Calculate operations needed
-        # We need to change (len(nums) - count) elements
-        operations = len(nums) - count
-        min_operations = min(min_operations, operations)
+    m = len(unique_nums)
+    min_operations = len(nums)
+    j = 0
+    for i in range(m):
+        while j < m and unique_nums[j] <= unique_nums[i] + len(nums) - 1:
+            j += 1
+        keep = j - i
+        operations = len(nums) - keep
+        if operations < min_operations:
+            min_operations = operations
📝 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
# Try different window sizes
for i in range(n):
# For each starting position, find the longest window that can be made continuous
left = unique_nums[i]
# Binary search for the rightmost element that can be part of a continuous sequence
# starting from left
right = left + len(nums) - 1
# Find how many elements in unique_nums fall within [left, right]
# This gives us the size of the window that can be made continuous
count = 0
for j in range(i, n):
if unique_nums[j] <= right:
count += 1
else:
break
# Calculate operations needed
# We need to change (len(nums) - count) elements
operations = len(nums) - count
min_operations = min(min_operations, operations)
return min_operations
m = len(unique_nums)
min_operations = len(nums)
j = 0
for i in range(m):
# expand right pointer as far as the window remains within size len(nums)
while j < m and unique_nums[j] <= unique_nums[i] + len(nums) - 1:
j += 1
# number of unique values we can keep in this window
keep = j - i
operations = len(nums) - keep
if operations < min_operations:
min_operations = operations
return min_operations
🤖 Prompt for AI Agents
In solutions/2119/01.py around lines 27 to 50, the inner loop scanning j from i
to n makes the algorithm O(u^2) and will TLE; replace it with a two-pointer
sliding window: keep j initialized outside the for-i loop and only advance j
forward while unique_nums[j] <= left + len(nums) - 1, compute count as (j - i)
(or j - i + 1 depending on inclusive indexing), compute operations = len(nums) -
count and update min_operations, and remove the incorrect "Binary search"
comment so j never moves backward and overall complexity becomes O(u).