Longest Subarray of Ones After Deleting One Element — At-Most-One-Zero Window [LC 1493, Google]
Advertisement
Problem Statement
LeetCode 1493 — Longest Subarray of 1s After Deleting One Element · Difficulty: Medium
Given a binary array
nums, you should delete one element from it. Return the size of the longest non-empty subarray containing only1s in the resulting array. Return0if there is no such subarray.
Constraints:
1 <= nums.length <= 10^5nums[i]is either0or1
Example 1:
Input: nums = [1, 1, 0, 1]
Output: 3
Explanation: Delete the 0 at index 2 → [1, 1, 1]. Longest subarray of 1s = 3.Example 2:
Input: nums = [0, 1, 1, 1, 0, 1, 1, 0, 1]
Output: 5
Explanation: Delete a 0 to get a subarray of 5 consecutive 1s (indices 1-5).Example 3:
Input: nums = [1, 1, 1]
Output: 2
Explanation: You must delete one element. All elements are 1, so delete any one.
Longest remaining subarray of 1s = 2.Why This Problem Matters
LC 1493 is a clean medium problem that tests a specific reframing skill: converting "delete exactly one element and maximize ones" into "find the longest window with at most one zero." The result is window_length - 1 (subtracting the one mandatory deletion).
Google and Amazon use this problem to test whether candidates recognize the equivalence between the delete-one constraint and the at-most-k-zeros sliding window. It is also a gentle warm-up for LC 1004 (Max Consecutive Ones III), which generalizes to "at most k zeros."
The all-ones edge case (Example 3) catches candidates off-guard: you must delete one element even when all are 1s, so the answer is n - 1, not n. The formula right - left (window size minus 1) handles this automatically.
The Core Insight
Reframe: The longest subarray of 1s after deleting exactly one element equals the longest window containing at most one zero, minus 1 (for the deleted element). That minus-1 is baked into the formula right - left (window size right - left + 1 minus 1).
Shrinkable window with zero budget:
- Expand right: if
nums[right] == 0, incrementzeros. - Shrink left while
zeros > 1: ifnums[left] == 0, decrementzeros; advanceleft. - After shrinking, the window
[left, right]has at most one zero. The subarray of 1s obtained by deleting that zero has lengthright - left(window size minus 1). - Track the maximum
right - leftacross all positions.
Visual Dry Run
Input: nums = [0, 1, 1, 1, 0, 1, 1, 0, 1]
right | val | zeros | left | window [left,right] | right - left |
|---|---|---|---|---|---|
| 0 | 0 | 1 | 0 | [0,0]="0" | 0 |
| 1 | 1 | 1 | 0 | [0,1]="01" | 1 |
| 2 | 1 | 1 | 0 | [0,2]="011" | 2 |
| 3 | 1 | 1 | 0 | [0,3]="0111" | 3 |
| 4 | 0 | 2 | → shrink: nums[0]=0 → zeros=1, left=1 | [1,4]="1110" | 3 |
| 5 | 1 | 1 | 1 | [1,5]="11101" | 4 |
| 6 | 1 | 1 | 1 | [1,6]="111011" | 5 |
| 7 | 0 | 2 | → shrink: nums[1]=1, left=2; nums[2]=1, left=3; nums[3]=1, left=4; nums[4]=0 → zeros=1, left=5 | [5,7]="110" | 2 |
| 8 | 1 | 1 | 5 | [5,8]="1101" | 3 |
Maximum right - left = 5 ✓
Common Mistakes
-
Returning
right - left + 1instead ofright - left. The problem asks for the length of the subarray after the deletion — the window of lengthright - left + 1contains one zero; deleting it gives a subarray of lengthright - left. Always subtract 1. -
Forgetting the all-ones edge case. When all elements are 1,
zerosis always 0, andright - leftat the final position givesn - 1— correct, because you must delete one element. No special case needed. -
Shrinking with
while nums[left] == 1: left++instead of trackingzeros. This is wrong: it can advanceleftpast a zero that should be kept. Always trackzerosexplicitly. -
Not advancing
leftfar enough. Whenzeros == 2, you need to shrink untilzeros <= 1— which requires finding and removing one of the two zeros. Thewhile zeros > 1loop handles this correctly. -
Initializing
ans = -1and returning0when no ones exist. If all elements are 0, every window haszeros > 0after just one element, so after any shrink,right - leftis 0. The maximum remains 0, which is the correct answer.
Solutions
Python
def longestSubarray(nums: list[int]) -> int:
left = 0
zeros = 0 # count of zeros in current window
ans = 0 # longest subarray of 1s after one deletion
for right in range(len(nums)):
if nums[right] == 0:
zeros += 1 # include a zero in the window
# Shrink from left while window has more than one zero
while zeros > 1:
if nums[left] == 0:
zeros -= 1 # remove a zero from the window
left += 1 # advance left pointer
# Window [left, right] has at most one zero.
# Deleting that zero gives a subarray of length (right - left + 1) - 1 = right - left.
ans = max(ans, right - left)
return ansJavaScript
function longestSubarray(nums) {
let left = 0;
let zeros = 0; // count of zeros in the current window
let ans = 0;
for (let right = 0; right < nums.length; right++) {
if (nums[right] === 0) {
zeros++; // expand: include a zero
}
// Shrink while more than one zero is in the window
while (zeros > 1) {
if (nums[left] === 0) {
zeros--; // remove a zero from the left
}
left++; // advance left
}
// Window length is (right - left + 1); after mandatory deletion: right - left
ans = Math.max(ans, right - left);
}
return ans;
}Complexity Analysis
| Approach | Time | Space | Notes |
|---|---|---|---|
| Brute force (all subarrays) | O(n²) | O(1) | TLE for n = 10^5 |
| Shrinkable window (this) | O(n) | O(1) | Each pointer moves forward at most n times |
right advances from 0 to n-1 (n steps). left only moves forward, advancing at most n times total across all iterations of the while loop. Total: O(n) time, O(1) space.
Follow-up Questions
-
LC 1004 — Max Consecutive Ones III (at most k flips): Generalize the budget from 1 to k. Replace
zeros > 1withzeros > k. The rest of the algorithm is identical. This is exactly the at-most-k-zeros window. -
What if you must delete exactly one zero (not any one element)? Count all 1-separated groups, then for each group of zeros, find the two adjacent runs of ones and their combined length. O(n) with a single pass.
-
What if the array can contain values other than 0 and 1? Define "bad elements" as those you want to delete. Count them with a budget — same sliding window approach.
-
What is the maximum subarray of 1s without any deletion (LC 485)? Simply track the current run of 1s and reset on 0. The two-pointer approach here is overkill for that problem.
This Pattern Solves
- LC 1493 — Longest Subarray of 1s After Deleting One Element (this problem)
- LC 1004 — Max Consecutive Ones III (at most k zeros, same pattern)
- LC 424 — Longest Repeating Character Replacement (budget on replacements)
- LC 992 — Subarrays with K Different Integers (at-least minus at-least)
- LC 209 — Minimum Size Subarray Sum (minimize window instead of maximize)
Key Takeaways
- Reframe "delete exactly one element, maximize 1s" as "find the longest window with at most one zero" — the deletion is implicit, and the result is
window_length - 1 = right - left. - Use
zerosto track the zero count in the window; shrink from the left wheneverzeros > 1. - The formula
right - left(notright - left + 1) is the key formula — it accounts for the mandatory one-element deletion automatically. - All-ones arrays are handled correctly without special cases:
zerosstays 0, andright - leftat the end equalsn - 1, which is the correct answer when you must delete one of n ones. - This generalizes directly to LC 1004 (k flips): change
zeros > 1tozeros > k— one character change in the algorithm. - Time O(n), space O(1) — both pointers move forward monotonically, so no element is processed more than twice.
- Google and Amazon use this to check whether candidates recognize the "at-most-one-bad-element" window reframing and can apply it without introducing an explicit inner loop.
Advertisement