Given a binary string s
(a string consisting only of '0's and '1's), your task is to determine the minimum number of character flips required to make s
alternating. An alternating binary string is one where no two adjacent characters are the same; for example, "0101" or "1010". Each flip changes a '0' to '1' or a '1' to '0'.
Constraints:
s
is either '0' or '1'.
At first glance, you might think about checking all possible combinations of flips, but this would be inefficient for long strings. Instead, notice that for an alternating string of length n
, there are only two possible patterns:
s
do not match the pattern and thus need to be flipped. The answer is the minimum of the two counts.
This realization shifts our approach from brute-force (trying all flip combinations) to a simple linear scan, comparing s
against both possible alternating patterns.
We solve the problem by:
s
:
alt1
)alt2
)s
and counting the number of positions where s
differs from alt1
(flips1
), and where it differs from alt2
(flips2
).flips1
and flips2
as the answer.We use simple iteration and comparison, making the solution efficient and easy to implement. Since we only need to compare each character once, the approach is optimal for this problem.
Example: Suppose s = "10010100"
alt1
): "01010101"alt2
): "10101010"Index | s | alt1 | alt2 | Mismatch alt1? | Mismatch alt2? |
---|---|---|---|---|---|
0 | 1 | 0 | 1 | Yes | No |
1 | 0 | 1 | 0 | Yes | No |
2 | 0 | 0 | 1 | No | Yes |
3 | 1 | 1 | 0 | No | Yes |
4 | 0 | 0 | 1 | No | Yes |
5 | 1 | 1 | 0 | No | Yes |
6 | 0 | 0 | 1 | No | Yes |
7 | 0 | 1 | 0 | Yes | No |
Counting mismatches:
Brute-force approach: Trying all possible flip combinations would take O(2n) time, which is infeasible for large n
.
Optimized approach (the one described above):
s
, since we scan the string once.
The key insight is that an alternating binary string of length n
can only have two forms: starting with '0' or with '1'. By counting mismatches against both, we find the minimal number of flips required. This approach is simple, efficient, and avoids unnecessary computation, making it a classic example of reducing a problem to a small set of possibilities and checking each directly.
def minFlips(s: str) -> int:
flips1 = flips2 = 0
for i, c in enumerate(s):
expected1 = '0' if i % 2 == 0 else '1'
expected2 = '1' if i % 2 == 0 else '0'
if c != expected1:
flips1 += 1
if c != expected2:
flips2 += 1
return min(flips1, flips2)
class Solution {
public:
int minFlips(string s) {
int flips1 = 0, flips2 = 0;
for (int i = 0; i < s.size(); ++i) {
char expected1 = (i % 2 == 0) ? '0' : '1';
char expected2 = (i % 2 == 0) ? '1' : '0';
if (s[i] != expected1) flips1++;
if (s[i] != expected2) flips2++;
}
return min(flips1, flips2);
}
};
class Solution {
public int minFlips(String s) {
int flips1 = 0, flips2 = 0;
for (int i = 0; i < s.length(); i++) {
char expected1 = (i % 2 == 0) ? '0' : '1';
char expected2 = (i % 2 == 0) ? '1' : '0';
if (s.charAt(i) != expected1) flips1++;
if (s.charAt(i) != expected2) flips2++;
}
return Math.min(flips1, flips2);
}
}
function minFlips(s) {
let flips1 = 0, flips2 = 0;
for (let i = 0; i < s.length; i++) {
let expected1 = i % 2 === 0 ? '0' : '1';
let expected2 = i % 2 === 0 ? '1' : '0';
if (s[i] !== expected1) flips1++;
if (s[i] !== expected2) flips2++;
}
return Math.min(flips1, flips2);
}