Skip to content
← All posts

Longest Subarray of 1's After Deleting One Element: Sliding Window

6 min read
leetcodeproblemmediumarraysdynamic-programmingsliding-window

Given a binary array nums, you must delete exactly one element from it and return the size of the longest non-empty subarray containing only 1s in the resulting array. If there is no such subarray, return 0.

This is LeetCode 1493: Longest Subarray of 1's After Deleting One Element. It is a classic sliding window problem that builds directly on the "Max Consecutive Ones III" pattern, with one twist: you must delete an element, even if the entire array is already all ones.

nums (window indices 0..5)1i=01i=10i=21i=31i=41i=50i=61i=7after deleting index 2: longest subarray of 1s = 511111
nums = [1,1,0,1,1,1,0,1]. The window from index 0 to 5 contains one zero. Delete it to get 5 consecutive ones. Red = deleted zero, green = ones in window.

Why this problem matters

Sliding window problems are everywhere in interviews, and this one teaches a particularly useful variant: maintaining a window with a tolerance budget. Instead of requiring the window to satisfy a strict condition at every position, you allow a limited number of violations and shrink from the left when the budget runs out. This same idea powers problems about substrings with at most k replacements, subarrays with at most k distinct values, and any scenario where you want the longest contiguous range that "almost" satisfies a constraint.

Once you internalize the pattern here, you can apply it to a whole family of problems. The tolerance budget might count zeros, distinct characters, or elements outside a range. The window mechanics stay the same: expand right, check the budget, shrink left if you have overspent, and track the best window seen so far.

The key insight

Think of the deletion as tolerating one zero. Instead of literally deleting an element and scanning the array each time, you maintain a sliding window that is allowed to contain at most one zero. As you expand the right side of the window, you count zeros. When the count exceeds one, you shrink the left side until the count drops back to one.

The window size at any point represents a subarray that, after removing the single tolerated zero (or any one element if there are no zeros), would be all ones. Because you must delete exactly one element, the answer is not the window size itself but window_size - 1. The clever part: using right - left instead of right - left + 1 bakes this subtraction in automatically.

The solution

def longestSubarray(nums):
    left = 0
    zeros = 0
    best = 0
    for right in range(len(nums)):
        if nums[right] == 0:
            zeros += 1
        while zeros > 1:
            if nums[left] == 0:
                zeros -= 1
            left += 1
        best = max(best, right - left)
    return best

Let's break down what each piece does.

The variable zeros tracks how many zeros are inside the current window [left, right]. Every time we expand right and land on a zero, we increment the count. If the count exceeds one, we enter the while loop and move left forward until we have ejected a zero and the count is back to one.

The key line is best = max(best, right - left). Notice that the standard window-size formula would be right - left + 1, but we use right - left instead. This accounts for the mandatory deletion: no matter what, we must remove one element from the window, so the resulting subarray is always one shorter than the window.

After the loop finishes, best holds the length of the longest subarray of ones achievable by deleting exactly one element.

The -1 for the mandatory deletion is built into the formula right - left instead of right - left + 1. This is easy to miss if you are used to standard sliding window size calculations. If you ever wonder "why no +1?", remember: you must delete one element, so the answer is always one less than the window length.

Visual walkthrough

Let's trace the algorithm on nums = [1, 1, 0, 1, 1, 1, 0, 1]. Watch how the window expands freely while it contains at most one zero, then contracts when a second zero enters.

Step 1: Initialize. left=0, right=0, zeros=0. Expand right.

nums11011101stateL=0R=0zeros=0best=0

nums[0]=1, not a zero. Window is [1]. best = max(0, 0-0) = 0.

Step 2: Expand right to index 2. First zero encountered.

nums11011101stateL=0R=2zeros=1best=2

nums[2]=0, so zeros becomes 1. Window [1,1,0]. best = max(2, 2-0) = 2.

Step 3: Expand right through indices 3, 4, 5. All ones.

nums11011101stateL=0R=5zeros=1best=5

No new zeros. Window [1,1,0,1,1,1] has one zero. best = max(2, 5-0) = 5.

Step 4: right=6. Second zero found. zeros=2, must shrink left.

nums11011101stateL=0R=6zeros=2best=5

nums[6]=0, zeros becomes 2. That exceeds our budget of 1 zero, so we need to shrink from the left.

Step 5: Shrink left past the first zero. left moves to 3.

nums11011101stateL=3R=6zeros=1best=5

Move left past indices 0, 1 (ones), then 2 (zero, zeros drops to 1). left=3. Window [1,1,1,0]. best stays 5.

Step 6: Expand right to index 7. nums[7]=1.

nums11011101stateL=3R=7zeros=1best=5

Window [1,1,1,0,1]. best = max(5, 7-3) = max(5, 4) = 5. No improvement.

Step 7: Done. Return best = 5.

best window (indices 0..5)110111after deletion11111

The best window had 6 elements with 1 zero. Deleting that zero leaves 5 consecutive ones. Answer: 5.

The largest window we ever achieve spans indices 0 through 5, giving a size of 6. With the mandatory deletion (right - left = 5 - 0 = 5), the answer is 5.

Complexity analysis

ApproachTimeSpace
Sliding windowO(n)O(1)

Time is O(n). Each element is visited at most twice: once when right expands to include it, and at most once when left advances past it. The inner while loop does not make this quadratic because left only moves forward, never backward.

Space is O(1). We use a fixed number of variables (left, zeros, best) regardless of input size. No auxiliary data structures are needed.

The building blocks

1. Sliding window with constraint counting

zeros = 0
for right in range(len(nums)):
    if nums[right] == 0:
        zeros += 1
    while zeros > 1:
        if nums[left] == 0:
            zeros -= 1
        left += 1

This is the same template used in Max Consecutive Ones III (LeetCode 1004), where you are allowed to flip at most k zeros. Here, k is 1. The pattern generalizes: replace zeros with any counter (distinct characters, elements outside a range), replace 1 with your budget, and the structure stays identical. You expand, you count, you shrink when over budget.

2. Window size minus one for mandatory deletion

best = max(best, right - left)   # not right - left + 1

This small adjustment handles the "must delete one element" constraint. In problems where deletion is optional, you would use right - left + 1. Here, because deletion is mandatory, the resulting subarray is always one element shorter than the window. Using right - left encodes that directly. If the array is all ones and you still must delete one, the answer is len(nums) - 1, which this formula produces correctly.

Edge cases

Before submitting, think through these scenarios:

  • All ones ([1, 1, 1, 1]): The window spans the entire array with zero zeros, but you still must delete one element. The formula right - left gives 3, which is len(nums) - 1. Correct.
  • All zeros ([0, 0, 0]): The window can never contain more than one zero without shrinking. The best window has size 1 (a single zero), and right - left = 0. The longest subarray of ones after deletion is 0.
  • Single element ([1] or [0]): You must delete the only element, leaving an empty array. The answer is 0. The formula gives 0 - 0 = 0.
  • One zero in the middle ([1, 1, 0, 1, 1]): The window covers the entire array with one zero. right - left = 4. Deleting the zero gives 4 consecutive ones.
  • Zeros at both ends ([0, 1, 1, 0]): The window expands to cover all 4 elements with zeros at each boundary. But when the second zero enters, left shrinks past the first zero. Best window is [1, 1, 0] or [0, 1, 1], giving right - left = 2.
  • Alternating ([1, 0, 1, 0, 1]): The window can hold at most two ones separated by one zero. Best is right - left = 2.

From understanding to recall

You have seen how the sliding window with a zero-tolerance budget solves this problem. The logic fits in ten lines of code and runs in O(n) time. But reproducing those ten lines under pressure, remembering whether to use right - left or right - left + 1, knowing when to increment versus decrement zeros, these details slip away without practice.

Spaced repetition is how you lock them in. You write the window expansion loop from memory, then the contraction condition, then the size formula. Each time, the gap between practice sessions grows. After a few rounds, you see "longest subarray with at most one deletion" and the code writes itself. No hesitation, no off-by-one errors.

Related posts

CodeBricks breaks this problem into its sliding window expansion, contraction, and size-formula building blocks, then drills them independently with spaced repetition. You type each piece from scratch until the pattern is automatic. When a sliding window problem shows up in your interview, you do not hesitate. You just write it.