LeetCode 1493 - Longest Subarray of 1's After Deleting One Element
This problem asks us to find the longest contiguous subarray of 1s in a binary array nums after deleting exactly one ele
Difficulty: 🟡 Medium
Topics: Array, Dynamic Programming, Sliding Window
Solution
Problem Understanding
This problem asks us to find the longest contiguous subarray of 1s in a binary array nums after deleting exactly one element. In other words, we can remove a single element (which could be 0 or 1) and then consider the longest block of consecutive 1s that remains. The array is binary, so elements are either 0 or 1. The function must return the length of this longest subarray.
The constraints indicate that the array can be large, up to 100,000 elements, so any solution that examines every possible subarray naively will be too slow. The array is guaranteed to have at least one element, but it may consist entirely of 1s or entirely of 0s. Since we must delete one element, even if the array is all 1s, the maximum subarray length is len(nums) - 1. Similarly, if the array is all 0s, the output must be 0.
Important edge cases include arrays that are all 1s, arrays that are all 0s, and arrays where 0s are at the start or end, which could affect how the "delete one element" operation impacts the longest sequence of 1s.
Approaches
A brute-force approach would consider deleting each element in the array and computing the length of the longest consecutive 1s for the resulting array. This involves iterating through the array for every deletion and then scanning for consecutive 1s, leading to a quadratic time complexity. This is correct but inefficient for arrays of length up to 100,000.
The key observation that enables a more efficient solution is that we only need to keep track of segments of 1s separated by at most one 0. By considering a sliding window where we allow at most one 0 to be skipped (as if it is deleted), we can find the maximum combined length of two consecutive 1 segments separated by a single 0. This turns the problem into a sliding window problem where the window can contain at most one 0.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n^2) | O(1) | Delete each element and compute the longest subarray of 1s |
| Optimal | O(n) | O(1) | Sliding window approach keeping track of at most one zero |
Algorithm Walkthrough
- Initialize two pointers
leftandrightat the start of the array. These will define the sliding window of elements being considered. - Initialize a variable
zero_countto keep track of the number of zeros in the current window. - Initialize a variable
max_lento store the maximum length of a valid window found so far. - Expand the
rightpointer through the array. Each time a zero is encountered, incrementzero_count. - If
zero_countexceeds1, shrink the window from the left until there is at most one zero in the window, decrementingzero_countwhenever a zero leaves the window. - Update
max_lenas the size of the current window minus one, because we must delete exactly one element. - Continue until
rightreaches the end of the array. Returnmax_len.
Why it works: By keeping a sliding window with at most one zero, we effectively consider deleting that zero to maximize consecutive 1s. The invariant is that zero_count <= 1 ensures we can always remove one zero to form a valid subarray.
Python Solution
from typing import List
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
left = 0
zero_count = 0
max_len = 0
for right in range(len(nums)):
if nums[right] == 0:
zero_count += 1
while zero_count > 1:
if nums[left] == 0:
zero_count -= 1
left += 1
max_len = max(max_len, right - left)
return max_len
The Python code iterates over the array with a right pointer while maintaining a count of zeros. If more than one zero is in the window, it moves the left pointer forward to reduce the zero count to at most one. The length of the current valid window minus one is used to update the maximum length.
Go Solution
func longestSubarray(nums []int) int {
left, zeroCount, maxLen := 0, 0, 0
for right := 0; right < len(nums); right++ {
if nums[right] == 0 {
zeroCount++
}
for zeroCount > 1 {
if nums[left] == 0 {
zeroCount--
}
left++
}
if right - left > maxLen {
maxLen = right - left
}
}
return maxLen
}
In Go, the logic mirrors Python. The for loop uses integer indices, and variables are initialized using :=. The slice nums is used directly, and window length is computed using right - left.
Worked Examples
Example: nums = [0,1,1,1,0,1,1,0,1]
| right | nums[right] | zero_count | left | max_len |
|---|---|---|---|---|
| 0 | 0 | 1 | 0 | 0 |
| 1 | 1 | 1 | 0 | 1 |
| 2 | 1 | 1 | 0 | 2 |
| 3 | 1 | 1 | 0 | 3 |
| 4 | 0 | 2 | 0->1 | 3 |
| 5 | 1 | 1 | 2 | 4 |
| 6 | 1 | 1 | 2 | 5 |
| 7 | 0 | 2 | 3->5 | 5 |
| 8 | 1 | 1 | 6 | 5 |
Result: 5
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Single pass over the array using sliding window |
| Space | O(1) | Only constant extra variables used |
The optimal solution scans the array once while maintaining a running count of zeros and updating the maximum length, so both the time and space complexity are minimal.
Test Cases
# Provided examples
assert Solution().longestSubarray([1,1,0,1]) == 3 # Deleting 0 gives [1,1,1]
assert Solution().longestSubarray([0,1,1,1,0,1,1,0,1]) == 5 # Deleting middle 0
assert Solution().longestSubarray([1,1,1]) == 2 # Must delete one element
# Edge cases
assert Solution().longestSubarray([0,0,0]) == 0 # Only zeros
assert Solution().longestSubarray([1,0,1,0,1]) == 3 # Deleting any zero in middle
assert Solution().longestSubarray([1]) == 0 # Single element, must delete it
assert Solution().longestSubarray([1,0,1,1,1,0,1,1]) == 5 # Mixed zeros
assert Solution().longestSubarray([1]*100000) == 99999 # Large array, all ones
| Test | Why |
|---|---|
[1,1,0,1] |
Basic case with one zero |
[0,1,1,1,0,1,1,0,1] |
Longer array with multiple zeros |
[1,1,1] |
All ones, must delete one |
[0,0,0] |
All zeros |
[1,0,1,0,1] |
Multiple small segments separated by zeros |
[1] |
Single-element array |
[1]*100000 |
Stress test for large input |
Edge Cases
One important edge case is an array containing all 1s. Since we must delete one element, the longest subarray is len(nums) - 1. Another edge case is an array of all 0s, which should return 0 because removing one 0 still leaves no 1s. A third edge case is a single-element array, which after deletion becomes empty, so the function should return 0. The sliding window implementation correctly handles these cases because it tracks zeros and ensures the maximum length accounts for deleting exactly one element.