Taro Logo

Max Consecutive Ones III

Medium
Google logo
Google
0 views
Topics:
ArraysSliding WindowsTwo Pointers

Given a binary array nums and an integer k, return the maximum number of consecutive 1's in the array if you can flip at most k 0's.

For example:

nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2

Output: 6

Explanation: [1,1,1,0,0,1,1,1,1,1,1] where the bolded numbers were flipped from 0 to 1. The longest subarray is underlined.

nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], k = 3

Output: 10

Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] where the bolded numbers were flipped from 0 to 1. The longest subarray is underlined.

Consider these constraints:

  • 1 <= nums.length <= 10^5
  • nums[i] is either 0 or 1.
  • 0 <= k <= nums.length

Explain your approach to solve this problem efficiently. What is the time and space complexity of your solution? Also, consider the edge cases. Provide clean, well-documented code to illustrate your solution.

Solution


Brute Force Solution

A brute force solution would involve checking every possible subarray of nums to see how many 1s it contains, and how many flips would be required to turn the subarray into all 1s. We can keep track of the longest valid subarray found so far and return it. This approach is generally inefficient but helps to illustrate the problem.

  1. Iterate through all possible start indices of subarrays.
  2. For each start index, iterate through all possible end indices.
  3. For each subarray, count the number of 0s.
  4. If the number of 0s is less than or equal to k, calculate the length of the subarray.
  5. Keep track of the maximum length found so far.

Code (Python):

def longestOnes_brute_force(nums, k):
    max_len = 0
    for i in range(len(nums)):
        for j in range(i, len(nums)):
            subarray = nums[i:j+1]
            zeros = subarray.count(0)
            if zeros <= k:
                max_len = max(max_len, len(subarray))
    return max_len

Time Complexity: O(n^3) - Two nested loops to generate all subarrays, and count is O(n).

Space Complexity: O(n) - For storing subarray.

Optimal Solution: Sliding Window

A more efficient approach is to use the sliding window technique. The main idea is to maintain a window that satisfies the condition of having at most k zeros. We expand the window to the right until we have more than k zeros, and then we shrink it from the left until the condition is satisfied again. This way, we only iterate through the array once.

  1. Initialize two pointers, left and right, to 0.
  2. Initialize a variable zeros to keep track of the number of zeros in the current window.
  3. Iterate through the array using the right pointer.
  4. If nums[right] is 0, increment zeros.
  5. While zeros is greater than k, increment left and if nums[left-1] was 0 decrement zeros.
  6. Update the maximum window length.
  7. Return the maximum length.

Code (Python):

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

Time Complexity: O(n) - Single pass through the array.

Space Complexity: O(1) - Constant extra space.

Edge Cases

  • Empty array: The problem statement specifies 1 <= nums.length, so we do not need to handle empty arrays.
  • k = 0: The algorithm still works correctly, finding the longest consecutive sequence of 1s.
  • k >= len(nums): The entire array can be flipped to 1s, so the result should be len(nums).
  • Array with all 1s: The algorithm will directly return len(nums) since no flips are needed.
  • Array with all 0s: The algorithm will return k if k < len(nums) and len(nums) if k >= len(nums).