1888. Minimum Number of Flips to Make The Binary String Alternating - Explanation
Description
You may perform these operations on the binary string s in any order:
- Move its first character to the end. This rotation is free.
- Flip any one character, changing
0to1or1to0.
Return the fewest flips needed to make the string alternating, meaning every pair of adjacent characters differs. Only flips are counted; you may perform any number of rotations. The first and last characters do not need to differ.
Example 1:
Input: s = "001"
Output: 0Explanation: Move the first 0 to the end to obtain 010. This is already alternating, so the rotation needs no flips.
Example 2:
Input: s = "0001"
Output: 1Explanation: Flip the second character to obtain 0101. No rotation of 0001 is alternating, so one flip is necessary.
Example 3:
Input: s = "0000"
Output: 2Explanation: Flip the second and fourth characters to obtain 0101. Any alternating string of length four needs two ones, so two flips are necessary.
Constraints:
1 <= s.length <= 100000- Every character is
0or1.
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Sliding Window Technique - Efficiently processing subarrays/substrings by maintaining a window of fixed or variable size
- String Manipulation - Working with rotations and pattern matching in strings
- Modular Arithmetic - Using mod operator to simulate circular array traversal
- Dynamic Programming - Tracking state transitions as elements shift positions
1. Brute Force
Intuition
An alternating string is either "010101..." or "101010...". The type-1 operation (moving first character to end) lets us try all possible rotations of the string. For each rotation, we count how many flips are needed to match either target pattern.
We generate both alternating patterns of length n, then for each of the n possible rotations, compute the difference count against both patterns and track the minimum.
Algorithm
- Build two target patterns:
alt1starting with'0'andalt2starting with'1'. - For each rotation index
ifrom0ton-1:- Create the rotated string by moving the first
icharacters to the end. - Count mismatches with both
alt1andalt2. - Update the minimum flip count.
- Create the rotated string by moving the first
- Return the minimum found.
class Solution:
def minFlips(self, s: str) -> int:
res = n = len(s)
alt1, alt2 = [], []
for i in range(n):
alt1.append("0" if i % 2 == 0 else "1")
alt2.append("1" if i % 2 == 0 else "0")
def diff(A, B):
cnt = 0
for i in range(n):
cnt += 1 if (A[i] != B[i]) else 0
return cnt
for i in range(n):
newS = s[i:] + s[:i]
res = min(res, min(diff(alt1, newS), diff(alt2, newS)))
return resTime & Space Complexity
- Time complexity:
- Space complexity:
2. Brute Force (Space Optimized)
Intuition
Instead of creating explicit rotated strings, we can iterate circularly through the original string using modular arithmetic. For each starting position, we walk through all n characters and count mismatches against both alternating patterns on the fly.
This saves the O(n) space needed to store rotated strings while maintaining the same logic: try every rotation and count flips needed for both target patterns.
Algorithm
- For each starting position
i:- Initialize counters for mismatches against
"010..."and"101...". - Walk through
ncharacters using modular indexing(i + k) % n. - Toggle the expected character as we go.
- Track the minimum between both pattern mismatches.
- Initialize counters for mismatches against
- Return the overall minimum.
class Solution:
def minFlips(self, s: str) -> int:
n = res = len(s)
for i in range(n):
start_0 = 1 if s[i] != '0' else 0
start_1 = 1 if s[i] != '1' else 0
c = '0'
j = (i + 1) % n
while j != i:
start_1 += 1 if s[j] != c else 0
start_0 += 1 if s[j] == c else 0
c = '0' if c == '1' else '1'
j = (j + 1) % n
res = min(res, min(start_1, start_0))
return resTime & Space Complexity
- Time complexity:
- Space complexity: extra space.
3. Sliding Window
Intuition
Concatenating the string with itself (s + s) simulates all rotations. A window of size n sliding over this doubled string represents each rotation. We can maintain mismatch counts incrementally: add the new character's contribution when expanding the window, and remove the old character's contribution when shrinking.
This transforms the O(n^2) brute force into O(n) by avoiding recalculation of the full difference for each rotation.
Algorithm
- Double the string:
s = s + s. - Build alternating patterns of length
2n. - Use two pointers
landrto maintain a window of sizen:- As
rexpands, updatediff1anddiff2based on mismatches at positionr. - When window exceeds size
n, remove contribution from positionland advancel. - When window is exactly size
n, record the minimum ofdiff1anddiff2.
- As
- Return the minimum.
class Solution:
def minFlips(self, s: str) -> int:
n = len(s)
s = s + s
alt1, alt2 = [], []
for i in range(len(s)):
alt1.append("0" if i % 2 == 0 else "1")
alt2.append("1" if i % 2 == 0 else "0")
res = len(s)
diff1, diff2 = 0, 0
l = 0
for r in range(len(s)):
if s[r] != alt1[r]:
diff1 += 1
if s[r] != alt2[r]:
diff2 += 1
if r - l + 1 > n:
if s[l] != alt1[l]:
diff1 -= 1
if s[l] != alt2[l]:
diff2 -= 1
l += 1
if r - l + 1 == n:
res = min(res, diff1, diff2)
return resTime & Space Complexity
- Time complexity:
- Space complexity:
4. Sliding Window (Space Optimized)
Intuition
We can avoid storing the doubled string and alternating patterns by computing expected characters on the fly. By tracking what character position r should have (toggling between '0' and '1'), we update mismatch counts directly.
Using modular indexing s[r % n] simulates the doubled string. We track the expected starting character for both window boundaries and toggle as we slide.
Algorithm
- Initialize difference counters and window boundaries.
- For
rfrom 0 to2n - 1:- Compute expected character at position
rfor pattern starting with '0'. - Update both mismatch counts based on whether
s[r % n]matches. - If window exceeds size
n, remove contribution froms[l]and advancel. - When window equals size
n, update minimum.
- Compute expected character at position
- Toggle expected characters as window slides.
class Solution:
def minFlips(self, s: str) -> int:
res = n = len(s)
diff1 = diff2 = l = 0
rstart_0 = lstart_0 = '0'
for r in range(2 * n):
if s[r % n] != rstart_0:
diff1 += 1
if s[r % n] == rstart_0:
diff2 += 1
if r - l + 1 > n:
if s[l] != lstart_0:
diff1 -= 1
if s[l] == lstart_0:
diff2 -= 1
l += 1
lstart_0 = '1' if lstart_0 == '0' else '0'
if r - l + 1 == n:
res = min(res, diff1, diff2)
rstart_0 = '1' if rstart_0 == '0' else '0'
return resTime & Space Complexity
- Time complexity:
- Space complexity: extra space.
5. Dynamic Programming
Intuition
First, count mismatches for the original string against pattern "1010...". The mismatch count for "0101..." is simply n - start_1 since every position either matches one pattern or the other.
For odd-length strings, rotating changes parity. After one rotation, positions that needed a '0' now need a '1' and vice versa. We can compute the new mismatch counts by swapping and adjusting based on the character that moved from front to back.
Algorithm
- Count initial mismatches (
start_1) against pattern"101...". - Compute
start_0 = n - start_1for pattern"010...". - If
nis even, rotations do not change the answer, so returnmin(start_0, start_1). - For odd
n, simulate each rotation:- Swap
dp0anddp1(parity flip). - Adjust counts based on the character that rotated.
- Track minimum across all rotations.
- Swap
class Solution:
def minFlips(self, s: str) -> int:
start_1 = 0
for i in range(len(s)):
if i & 1:
start_1 += s[i] == "1"
else:
start_1 += s[i] == "0"
start_0 = len(s) - start_1
ans = min(start_0, start_1)
if len(s) % 2 == 0:
return ans
dp0, dp1 = start_0, start_1
for c in s:
dp0, dp1 = dp1, dp0
if c == "1":
dp0 += 1
dp1 -= 1
else:
dp0 -= 1
dp1 += 1
ans = min(dp0, dp1, ans)
return ansTime & Space Complexity
- Time complexity:
- Space complexity: extra space.
Common Pitfalls
Forgetting That Rotations Only Matter for Odd-Length Strings
For even-length strings, rotating the string does not change the number of flips needed because the parity of each position remains the same after a full rotation cycle. The optimization to skip rotations when n % 2 == 0 is critical for both correctness and performance. Without this check, you might perform unnecessary work or miss that the initial comparison already gives the optimal answer.
Incorrectly Handling the Doubled String in Sliding Window
When using the sliding window approach with s + s, you must build alternating patterns of length 2n, not n. If you only build patterns of length n and try to index beyond, you will get index-out-of-bounds errors or incorrect mismatch counts. Additionally, when the window slides, you must properly remove the contribution of the leftmost character before adding the new rightmost character.
Confusing Which Pattern Tracks Which Mismatches
The two patterns "010101..." and "101010..." are complementary. If a position matches one pattern, it mismatches the other. When computing both diff counts simultaneously, ensure you are consistent: if s[r] != alt1[r], increment diff1; if s[r] != alt2[r], increment diff2. Mixing up which count corresponds to which pattern will produce incorrect minimum flip counts.
Sign in to join the discussion