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;
};
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.
s
can be flipped at most once.
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:
'1'
s seen so far (ones
).flips
).'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.
ones
: counts the number of '1'
s seen so far.flips
: tracks the minimum flips needed up to the current character.'1'
, increment ones
. No flip is needed because '1'
is valid in the increasing sequence after any '0'
s.'0'
:
'0'
to '1'
(so it matches a monotone sequence after '1'
s), which costs flips + 1
.'1'
s to '0'
s (so the sequence up to here is all '0'
s), which costs ones
.flips
.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.
Let's use the input s = "00110"
.
ones = 0
, flips = 0
flips = min(flips+1, ones) = min(1, 0) = 0
flips = min(flips+1, ones) = min(1, 0) = 0
ones
to 1. flips
unchanged.ones
to 2. flips
unchanged.flips + 1 = 0 + 1 = 1
ones = 2
flips = min(1, 2) = 1
flips = 1
. Only one flip needed (either the last '0' to '1', or one of the '1's to '0').The optimized approach is much faster and suitable for large input sizes.
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.