Minimum Flips to Make the Binary String Alternate
Doubled string sliding window — for each length-n window, count mismatches against "0101..." and "1010..." patterns.
5 min read
string sliding-window
Problem#
You may rotate the string and flip any bit. Return the minimum flips to make the string alternate (0101... or 1010...).
Examples#
"111000"→2."010"→0;"1110"→1.
Constraints#
1 <= s.length <= 10^5.
Approach#
Concatenate s with itself to simulate all rotations. Sliding window of length n: count mismatches against the two alternating patterns. Track the minimum mismatch count.
Solution#
class Solution {public: int minFlips(string s) { int n = s.size(); string t = s + s; int diff0 = 0, diff1 = 0, ans = INT_MAX; for (int i = 0; i < (int)t.size(); ++i) { char want0 = (i & 1) ? '1' : '0'; char want1 = (i & 1) ? '0' : '1'; if (t[i] != want0) ++diff0; if (t[i] != want1) ++diff1; if (i >= n) { char p0 = ((i - n) & 1) ? '1' : '0'; char p1 = ((i - n) & 1) ? '0' : '1'; if (t[i - n] != p0) --diff0; if (t[i - n] != p1) --diff1; } if (i >= n - 1) ans = min(ans, min(diff0, diff1)); } return ans; }};func minFlips(s string) int { n := len(s) t := s + s diff0, diff1, ans := 0, 0, math.MaxInt32 for i := 0; i < len(t); i++ { var want0, want1 byte if i&1 == 1 { want0, want1 = '1', '0' } else { want0, want1 = '0', '1' } if t[i] != want0 { diff0++ } if t[i] != want1 { diff1++ } if i >= n { var p0, p1 byte if (i-n)&1 == 1 { p0, p1 = '1', '0' } else { p0, p1 = '0', '1' } if t[i-n] != p0 { diff0-- } if t[i-n] != p1 { diff1-- } } if i >= n-1 { m := diff0 if diff1 < m { m = diff1 } if m < ans { ans = m } } } return ans}class Solution: def minFlips(self, s: str) -> int: n = len(s) t = s + s diff0 = diff1 = 0 ans = float('inf') for i in range(len(t)): want0 = '1' if i & 1 else '0' want1 = '0' if i & 1 else '1' if t[i] != want0: diff0 += 1 if t[i] != want1: diff1 += 1 if i >= n: p0 = '1' if (i - n) & 1 else '0' p1 = '0' if (i - n) & 1 else '1' if t[i - n] != p0: diff0 -= 1 if t[i - n] != p1: diff1 -= 1 if i >= n - 1: ans = min(ans, diff0, diff1) return ansfunction minFlips(s) { const n = s.length; const t = s + s; let diff0 = 0, diff1 = 0, ans = Infinity; for (let i = 0; i < t.length; i++) { const want0 = (i & 1) ? '1' : '0'; const want1 = (i & 1) ? '0' : '1'; if (t[i] !== want0) diff0++; if (t[i] !== want1) diff1++; if (i >= n) { const p0 = ((i - n) & 1) ? '1' : '0'; const p1 = ((i - n) & 1) ? '0' : '1'; if (t[i - n] !== p0) diff0--; if (t[i - n] !== p1) diff1--; } if (i >= n - 1) ans = Math.min(ans, diff0, diff1); } return ans;}class Solution { public int minFlips(String s) { int n = s.length(); String t = s + s; int diff0 = 0, diff1 = 0, ans = Integer.MAX_VALUE; for (int i = 0; i < t.length(); i++) { char want0 = ((i & 1) == 1) ? '1' : '0'; char want1 = ((i & 1) == 1) ? '0' : '1'; if (t.charAt(i) != want0) diff0++; if (t.charAt(i) != want1) diff1++; if (i >= n) { char p0 = (((i - n) & 1) == 1) ? '1' : '0'; char p1 = (((i - n) & 1) == 1) ? '0' : '1'; if (t.charAt(i - n) != p0) diff0--; if (t.charAt(i - n) != p1) diff1--; } if (i >= n - 1) ans = Math.min(ans, Math.min(diff0, diff1)); } return ans; }}function minFlips(s: string): number { const n = s.length; const t = s + s; let diff0 = 0, diff1 = 0, ans = Infinity; for (let i = 0; i < t.length; i++) { const want0 = (i & 1) ? '1' : '0'; const want1 = (i & 1) ? '0' : '1'; if (t[i] !== want0) diff0++; if (t[i] !== want1) diff1++; if (i >= n) { const p0 = ((i - n) & 1) ? '1' : '0'; const p1 = ((i - n) & 1) ? '0' : '1'; if (t[i - n] !== p0) diff0--; if (t[i - n] !== p1) diff1--; } if (i >= n - 1) ans = Math.min(ans, diff0, diff1); } return ans;}Editorial#
Rotation is naturally a sliding window over s + s. Computing mismatches against both patterns simultaneously in one sweep is O(n) total; the trick is being careful about the index parity comparisons when both adding and removing window elements.
Complexity#
- Time:
O(n). - Space:
O(n)fort,O(1)extra logic.
Concept revision#
Related#