Facebook Pixel

1888. Minimum Number of Flips to Make the Binary String Alternating

Problem Description

You have a binary string s consisting only of '0's and '1's. Your goal is to make this string alternating using the minimum number of flip operations.

An alternating string is one where no two adjacent characters are the same. For example:

  • "010" and "1010" are alternating strings
  • "0100" is not alternating (has "00" adjacent)

You can perform two types of operations on the string:

  1. Type-1 Operation (Rotation): Remove the first character from the string and append it to the end. This operation can be done any number of times for free.

    • Example: "1100""1001" (moved first '1' to the end)
  2. Type-2 Operation (Flip): Choose any character in the string and flip it ('0' becomes '1', '1' becomes '0'). This operation has a cost.

    • Example: "1100""1000" (flipped the second '1' to '0')

The key insight is that you can use Type-1 operations (rotations) freely to position the string optimally before applying Type-2 operations (flips). Since rotations are free, you want to find the rotation of the string that requires the minimum number of flips to become alternating.

There are only two possible alternating patterns for any string:

  • Pattern starting with '0': "010101..."
  • Pattern starting with '1': "101010..."

The solution checks all possible rotations of the string and for each rotation, calculates how many flips are needed to match either alternating pattern. It then returns the minimum number of flips required across all rotations and both patterns.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

Since we can rotate the string for free (Type-1 operations), we need to find the best starting position that minimizes the number of flips required. The key observation is that for any given string, there are only two possible alternating patterns to target: one starting with '0' ("010101...") and one starting with '1' ("101010...").

For a string of length n, we have n possible rotations. For each rotation, we need to check how many flips are required to transform it into either of the two alternating patterns. The answer is the minimum across all these possibilities.

Initially, we might think we need to physically rotate the string and check each rotation, but that would be inefficient. Instead, we can simulate the rotation effect mathematically. When we rotate a character from position i to the front, it effectively moves to position i+n in a conceptually "doubled" string.

The clever part of the solution is maintaining a running count of mismatches. We start by counting how many positions don't match the "01" pattern in the original string. Then, as we simulate each rotation:

  • We subtract the contribution of the character that's being moved from the front (it's no longer at its original position)
  • We add the contribution of that same character at its new position at the end

For each rotation state, we check both patterns. If we have cnt mismatches with the "01" pattern, then we have n - cnt mismatches with the "10" pattern (since these patterns are complementary - where one matches, the other doesn't).

This sliding window approach allows us to check all rotations in O(n) time while keeping track of the minimum flips needed across all configurations.

Learn more about Dynamic Programming and Sliding Window patterns.

Solution Approach

The implementation uses a sliding window technique to efficiently check all possible rotations:

  1. Initial Setup: We define our target pattern as "01" (alternating starting with '0'). For any position i, the expected character is target[i & 1], which gives us '0' for even positions and '1' for odd positions.

  2. Count Initial Mismatches: We calculate how many positions in the original string don't match the "01" pattern:

    cnt = sum(c != target[i & 1] for i, c in enumerate(s))

    This gives us the number of flips needed if we don't rotate and aim for the "01" pattern.

  3. Consider Both Patterns: Since there are two possible alternating patterns, if cnt flips are needed for "01", then n - cnt flips are needed for "10". We take the minimum:

    ans = min(cnt, n - cnt)
  4. Simulate Rotations: We iterate through each possible rotation by moving one character at a time from front to back:

    for i in range(n):
        cnt -= s[i] != target[i & 1]           # Remove contribution of s[i] at position i
        cnt += s[i] != target[(i + n) & 1]     # Add contribution of s[i] at position (i+n)
        ans = min(ans, cnt, n - cnt)
    • When character s[i] moves from position i to the conceptual position i+n (end of string):
      • We subtract 1 from cnt if s[i] was a mismatch at position i
      • We add 1 to cnt if s[i] becomes a mismatch at its new position (i+n) % 2
    • The expression (i + n) & 1 efficiently computes (i + n) % 2, determining whether the new position is even or odd.
  5. Track Minimum: After each rotation adjustment, we update our answer with the minimum of:

    • cnt: flips needed for "01" pattern
    • n - cnt: flips needed for "10" pattern
    • Current best answer

The algorithm runs in O(n) time with O(1) extra space, efficiently finding the minimum number of Type-2 operations needed across all possible rotations and both alternating patterns.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with s = "1100".

Step 1: Initial Setup

  • String: "1100", length n = 4
  • Target pattern "01": for alternating string starting with '0'
  • Expected pattern for positions [0,1,2,3]: "0101"

Step 2: Count Initial Mismatches

  • Position 0: s[0] = '1', expected '0' → mismatch ✗
  • Position 1: s[1] = '1', expected '1' → match ✓
  • Position 2: s[2] = '0', expected '0' → match ✓
  • Position 3: s[3] = '0', expected '1' → mismatch ✗
  • Initial cnt = 2 (two mismatches with "0101" pattern)

Step 3: Check Both Patterns for Original String

  • For pattern "0101": need 2 flips
  • For pattern "1010": need 4 - 2 = 2 flips
  • Current best: ans = min(2, 2) = 2

Step 4: Simulate Rotations

Rotation 1: Move s[0]='1' to end → "1001"

  • Remove s[0]='1' from position 0: was a mismatch, so cnt -= 1cnt = 1
  • Add s[0]='1' at position 4 (conceptually):
    • Position 4 expects target[4 & 1] = target[0] = '0'
    • '1' ≠ '0', so mismatch, cnt += 1cnt = 2
  • Check both patterns: min(2, 4-2) = 2
  • Update: ans = min(2, 2) = 2

Rotation 2: Move s[1]='1' to end → "0011"

  • Remove s[1]='1' from position 1: was a match, so cnt -= 0cnt = 2
  • Add s[1]='1' at position 5 (conceptually):
    • Position 5 expects target[5 & 1] = target[1] = '1'
    • '1' = '1', so match, cnt += 0cnt = 2
  • Check both patterns: min(2, 4-2) = 2
  • Update: ans = min(2, 2) = 2

Rotation 3: Move s[2]='0' to end → "0110"

  • Remove s[2]='0' from position 2: was a match, so cnt -= 0cnt = 2
  • Add s[2]='0' at position 6 (conceptually):
    • Position 6 expects target[6 & 1] = target[0] = '0'
    • '0' = '0', so match, cnt += 0cnt = 2
  • Check both patterns: min(2, 4-2) = 2
  • Update: ans = min(2, 2) = 2

Rotation 4: Move s[3]='0' to end → "1100" (back to original)

  • Remove s[3]='0' from position 3: was a mismatch, so cnt -= 1cnt = 1
  • Add s[3]='0' at position 7 (conceptually):
    • Position 7 expects target[7 & 1] = target[1] = '1'
    • '0' ≠ '1', so mismatch, cnt += 1cnt = 2
  • Check both patterns: min(2, 4-2) = 2
  • Update: ans = min(2, 2) = 2

Result: Minimum flips needed = 2

We can verify: "1100" can become "1010" with 2 flips (flip positions 1 and 2), or become "0101" with 2 flips (flip positions 0 and 3).

Solution Implementation

1class Solution:
2    def minFlips(self, s: str) -> int:
3        n = len(s)
4      
5        # Target pattern for alternating string starting with '0'
6        target_pattern = "01"
7      
8        # Count mismatches when comparing s with pattern "010101..."
9        # For each position i, check if s[i] matches the expected character
10        mismatch_count = sum(char != target_pattern[i & 1] for i, char in enumerate(s))
11      
12        # The answer is minimum between:
13        # 1. Flips needed for pattern "010101..." (mismatch_count)
14        # 2. Flips needed for pattern "101010..." (n - mismatch_count)
15        min_flips = min(mismatch_count, n - mismatch_count)
16      
17        # Simulate rotating the string by removing from front and adding to back
18        # This handles the Type-1 operation (moving first char to end)
19        for i in range(n):
20            # Remove contribution of character at position i (as if it's moved to end)
21            mismatch_count -= s[i] != target_pattern[i & 1]
22          
23            # Add contribution of the same character at its new position (i + n)
24            mismatch_count += s[i] != target_pattern[(i + n) & 1]
25          
26            # Update minimum flips considering both alternating patterns
27            min_flips = min(min_flips, mismatch_count, n - mismatch_count)
28      
29        return min_flips
30
1class Solution {
2    public int minFlips(String s) {
3        int stringLength = s.length();
4      
5        // Target pattern starting with "01" (alternating 0 and 1)
6        String alternatingPattern = "01";
7      
8        // Count mismatches when comparing string with "0101..." pattern
9        int mismatchCount = 0;
10        for (int i = 0; i < stringLength; ++i) {
11            // Use bitwise AND to alternate between index 0 and 1 of pattern
12            // When i is even: i & 1 = 0 (compare with '0')
13            // When i is odd: i & 1 = 1 (compare with '1')
14            if (s.charAt(i) != alternatingPattern.charAt(i & 1)) {
15                ++mismatchCount;
16            }
17        }
18      
19        // Calculate minimum flips needed for both patterns:
20        // - mismatchCount: flips needed for "0101..." pattern
21        // - (stringLength - mismatchCount): flips needed for "1010..." pattern
22        int minFlipsNeeded = Math.min(mismatchCount, stringLength - mismatchCount);
23      
24        // Simulate moving characters from beginning to end one by one
25        // This handles the Type-1 operation where we can move front character to back
26        for (int i = 0; i < stringLength; ++i) {
27            // Remove contribution of character at position i from original position
28            if (s.charAt(i) != alternatingPattern.charAt(i & 1)) {
29                --mismatchCount;
30            }
31          
32            // Add contribution of character at position i when moved to end
33            // New position would be (i + stringLength), so we check pattern at that position
34            if (s.charAt(i) != alternatingPattern.charAt((i + stringLength) & 1)) {
35                ++mismatchCount;
36            }
37          
38            // Update minimum flips considering both alternating patterns
39            minFlipsNeeded = Math.min(minFlipsNeeded, Math.min(mismatchCount, stringLength - mismatchCount));
40        }
41      
42        return minFlipsNeeded;
43    }
44}
45
1class Solution {
2public:
3    int minFlips(string s) {
4        int n = s.size();
5      
6        // Target pattern starting with "01" (alternating pattern)
7        string targetPattern = "01";
8      
9        // Count mismatches when comparing string s with pattern "010101..."
10        int mismatchCount = 0;
11        for (int i = 0; i < n; ++i) {
12            // Use bitwise AND to alternate between indices 0 and 1 of targetPattern
13            if (s[i] != targetPattern[i & 1]) {
14                ++mismatchCount;
15            }
16        }
17      
18        // Initialize answer with minimum flips needed for both patterns:
19        // Pattern 1: "010101..." requires mismatchCount flips
20        // Pattern 2: "101010..." requires (n - mismatchCount) flips
21        int minFlipsNeeded = min(mismatchCount, n - mismatchCount);
22      
23        // Simulate rotating the string by treating it as circular
24        // For each rotation, update mismatch count and find minimum
25        for (int i = 0; i < n; ++i) {
26            // Remove contribution of character at position i from old window
27            if (s[i] != targetPattern[i & 1]) {
28                --mismatchCount;
29            }
30          
31            // Add contribution of character at position i in new window
32            // After rotation, character at index i moves to position (i + n)
33            if (s[i] != targetPattern[(i + n) & 1]) {
34                ++mismatchCount;
35            }
36          
37            // Update minimum flips considering both alternating patterns
38            minFlipsNeeded = min({minFlipsNeeded, mismatchCount, n - mismatchCount});
39        }
40      
41        return minFlipsNeeded;
42    }
43};
44
1/**
2 * Finds the minimum number of flips required to make a binary string alternating.
3 * The string can be rotated (type-1 operation) and characters can be flipped (type-2 operation).
4 * 
5 * @param s - The input binary string containing only '0' and '1'
6 * @returns The minimum number of character flips needed
7 */
8function minFlips(s: string): number {
9    const stringLength: number = s.length;
10  
11    // Target pattern for alternating string starting with '0'
12    const alternatingPattern: string = '01';
13  
14    // Count mismatches with pattern "010101..." for original string
15    let mismatchCount: number = 0;
16    for (let i = 0; i < stringLength; ++i) {
17        // Check if current character matches the expected pattern character
18        // Using bitwise AND with 1 to alternate between index 0 and 1
19        if (s[i] !== alternatingPattern[i & 1]) {
20            ++mismatchCount;
21        }
22    }
23  
24    // Initialize answer with minimum flips needed for both patterns:
25    // Pattern "010101..." requires mismatchCount flips
26    // Pattern "101010..." requires (stringLength - mismatchCount) flips
27    let minFlipsNeeded: number = Math.min(mismatchCount, stringLength - mismatchCount);
28  
29    // Simulate rotating the string by moving characters from front to back
30    // This is done virtually by adjusting the mismatch count
31    for (let i = 0; i < stringLength; ++i) {
32        // Remove contribution of character at position i from the front
33        if (s[i] !== alternatingPattern[i & 1]) {
34            --mismatchCount;
35        }
36      
37        // Add contribution of the same character when it moves to the back
38        // After rotation, it would be at position (i + stringLength)
39        if (s[i] !== alternatingPattern[(i + stringLength) & 1]) {
40            ++mismatchCount;
41        }
42      
43        // Update minimum flips considering both alternating patterns
44        minFlipsNeeded = Math.min(minFlipsNeeded, mismatchCount, stringLength - mismatchCount);
45    }
46  
47    return minFlipsNeeded;
48}
49

Time and Space Complexity

Time Complexity: O(n)

The algorithm iterates through the string twice:

  • Initial calculation: O(n) to compute the sum for counting mismatches with pattern "01"
  • Main loop: Runs n iterations, with each iteration performing O(1) operations (arithmetic operations, comparisons, and array access using bitwise AND)

Total time complexity: O(n) + O(n) = O(n)

Space Complexity: O(1)

The algorithm uses only a constant amount of extra space:

  • Variable n stores the length of the string
  • Variable target stores a constant string "01"
  • Variable cnt stores the count of mismatches
  • Variable ans stores the minimum flips required
  • Loop variable i

All these variables use constant space regardless of input size, resulting in O(1) space complexity.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrectly Handling the Rotation Logic

Pitfall: A common mistake is misunderstanding how the sliding window simulates rotation. Developers often try to physically rotate the string or create new strings for each rotation, which is inefficient and unnecessary.

Incorrect approach:

# Wrong: Creating actual rotations
for i in range(n):
    rotated = s[i:] + s[:i]  # This creates O(n^2) space complexity
    # Calculate mismatches for rotated string

Correct approach:

# Right: Simulating rotation with sliding window
for i in range(n):
    cnt -= s[i] != target[i & 1]       # Remove old position contribution
    cnt += s[i] != target[(i + n) & 1] # Add new position contribution

2. Forgetting to Consider Both Alternating Patterns

Pitfall: Only checking against one pattern (either "0101..." or "1010...") and missing the optimization that if k flips are needed for one pattern, then n-k flips are needed for the other.

Incorrect approach:

# Wrong: Only checking one pattern
cnt = sum(c != '0' if i % 2 == 0 else c != '1' for i, c in enumerate(s))
return cnt  # Missing the n - cnt case

Correct approach:

# Right: Consider both patterns
ans = min(cnt, n - cnt)  # Check both "01..." and "10..." patterns

3. Off-by-One Errors in Position Calculation

Pitfall: Incorrectly calculating the new position after rotation, especially when using modulo operations.

Incorrect approach:

# Wrong: Incorrect new position calculation
cnt += s[i] != target[(n + i - 1) & 1]  # Wrong formula

Correct approach:

# Right: Correct position after moving to end
cnt += s[i] != target[(i + n) & 1]  # Character at position i moves to position i+n conceptually

4. Not Understanding the Bit Operation & 1

Pitfall: Using % 2 is correct but less efficient than & 1. Some developers might not understand that & 1 is equivalent to % 2 for non-negative integers.

Less efficient but correct:

target[i % 2]  # Works but slightly slower

More efficient:

target[i & 1]  # Bitwise AND with 1 gives the same result as modulo 2

5. Misunderstanding the Problem Statement

Pitfall: Thinking that Type-1 operations (rotations) have a cost or limit, leading to overly complex solutions trying to minimize rotations.

Key insight to remember:

  • Type-1 operations (rotations) are FREE and unlimited
  • Only Type-2 operations (flips) have a cost
  • The goal is to find the best rotation that minimizes the number of flips needed

Solution to avoid this pitfall: Always read the problem carefully and identify which operations are free versus costly. In this case, since rotations are free, we should try all possible rotations to find the one requiring minimum flips.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of these properties could exist for a graph but not a tree?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More