Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

926. Flip String to Monotone Increasing - Leetcode Solution

Code Implementation

class Solution:
    def minFlipsMonoIncr(self, s: str) -> int:
        flips = 0
        ones = 0
        for c in s:
            if c == '1':
                ones += 1
            else:
                flips = min(flips + 1, ones)
        return flips
      
class Solution {
public:
    int minFlipsMonoIncr(string s) {
        int flips = 0, ones = 0;
        for (char c : s) {
            if (c == '1') {
                ones++;
            } else {
                flips = min(flips + 1, ones);
            }
        }
        return flips;
    }
};
      
class Solution {
    public int minFlipsMonoIncr(String s) {
        int flips = 0, ones = 0;
        for (char c : s.toCharArray()) {
            if (c == '1') {
                ones++;
            } else {
                flips = Math.min(flips + 1, ones);
            }
        }
        return flips;
    }
}
      
var minFlipsMonoIncr = function(s) {
    let flips = 0, ones = 0;
    for (let i = 0; i < s.length; i++) {
        if (s[i] === '1') {
            ones++;
        } else {
            flips = Math.min(flips + 1, ones);
        }
    }
    return flips;
};
      

Problem Description

Given a binary string s (a string consisting only of '0' and '1'), you are asked to return the minimum number of flips required to make s monotone increasing. A string is monotone increasing if it consists of some number of '0's (possibly none), followed by some number of '1's (also possibly none). In other words, all the '0's must come before any '1's.

In one flip, you can change a '0' to a '1' or a '1' to a '0'. Your task is to compute the minimum number of such flips needed.

  • Each character in s can be flipped at most once.
  • The solution must be efficient for large input sizes (up to 105 characters).

Thought Process

The brute-force approach would be to consider every possible split point in the string: for each position, flip all '1's before it to '0's and all '0's after it to '1's. Then, count the flips for each split and take the minimum. However, this approach is inefficient for long strings, as it requires recalculating counts for each split.

To optimize, we can process the string in a single pass, keeping track of two quantities:

  • The number of '1's seen so far (ones).
  • The minimum number of flips needed up to the current position (flips).
For each character, we decide whether to flip this character or to flip previous '1's, updating the minimum flips accordingly.

The main insight is that, for monotone increasing, every '0' after a '1' must be flipped, or, alternatively, we could have flipped some earlier '1's to '0's. We always want to choose the cheaper option at each step.

Solution Approach

  • Initialize two counters:
    • ones: counts the number of '1's seen so far.
    • flips: tracks the minimum flips needed up to the current character.
  • Iterate through each character in the string:
    • If the character is '1', increment ones. No flip is needed because '1' is valid in the increasing sequence after any '0's.
    • If the character is '0':
      • We can either flip this '0' to '1' (so it matches a monotone sequence after '1's), which costs flips + 1.
      • Or, flip all previous '1's to '0's (so the sequence up to here is all '0's), which costs ones.
      • Take the minimum of these two options for flips.
  • Return flips after processing the entire string.

This approach ensures that at each step, we only keep track of the minimum flips needed, leading to an efficient O(n) solution.

Example Walkthrough

Let's use the input s = "00110".

  1. Start: ones = 0, flips = 0
  2. First character: '0'
    • It's '0', so no change. flips = min(flips+1, ones) = min(1, 0) = 0
  3. Second character: '0'
    • Again, '0'. flips = min(flips+1, ones) = min(1, 0) = 0
  4. Third character: '1'
    • It's '1', increment ones to 1. flips unchanged.
  5. Fourth character: '1'
    • It's '1', increment ones to 2. flips unchanged.
  6. Fifth character: '0'
    • It's '0'. We can either:
      • Flip this '0' to '1': flips + 1 = 0 + 1 = 1
      • Or flip all previous '1's to '0': ones = 2
      • So flips = min(1, 2) = 1
  7. End: flips = 1. Only one flip needed (either the last '0' to '1', or one of the '1's to '0').

Time and Space Complexity

  • Brute-force approach:
    • For each possible split (n+1 in total for length n), count flips before and after the split, which takes O(n) per split.
    • Total time: O(n2).
    • Space: O(1) extra space.
  • Optimized approach (as above):
    • Single pass through the string: O(n) time.
    • Only two integer counters used: O(1) space.

The optimized approach is much faster and suitable for large input sizes.

Summary

The key to efficiently solving the "Flip String to Monotone Increasing" problem is to realize that at each character, we can decide to either flip the current '0' to '1' or flip all previous '1's to '0's, whichever is cheaper. By maintaining running counts and always picking the minimal flip count at each step, we achieve an elegant O(n) solution with constant space. This approach is both intuitive and highly efficient for large binary strings.