Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1529. Minimum Suffix Flips - Leetcode Solution

Problem Description

You are given two binary strings: target and original, both of the same length. Your goal is to transform original into target using the minimum number of "suffix flip" operations.

In one "suffix flip" operation, you choose an index i (0-based) and flip every bit from position i to the end of the string. Flipping a bit changes '0' to '1' or '1' to '0'.

Return the minimum number of suffix flips needed to make original equal to target.

  • Each flip can be done at any index, any number of times.
  • You must not reuse a flip at the same index in the same operation.
  • There is always at least one valid solution.

Thought Process

Let's start by considering the brute-force approach: for every bit that doesn't match, we could flip the suffix starting at that position. However, this would be inefficient, especially for long strings, because flipping at every mismatch could lead to redundant operations.

Instead, let's think about what actually happens when we flip a suffix. Flipping at position i inverts all bits from i onward. So, if we flip multiple times at overlapping positions, earlier flips can be "canceled out" by later ones.

The key insight is to track when the desired bit changes compared to the previous position. We only need to flip when the current bit in original (considering all previous flips) doesn't match target at that position, and the difference isn't already accounted for by a previous flip.

This leads us to an optimized approach: traverse the string from left to right, and flip whenever the effective bit (after considering previous flips) doesn't match the target, and the difference is not already handled by a previous flip.

Solution Approach

  • Initialize a variable to keep track of the current "flip state" (whether the number of flips so far is odd or even).
  • Iterate through each index i of the strings.
  • For each position, determine the effective bit in original after all previous flips:
    • If the number of flips so far is even, the bit is as in original.
    • If odd, the bit is flipped (i.e., '0' becomes '1' and vice versa).
  • If the effective bit does not match target[i], a flip is needed at this position. Increment the flip counter and update the flip state.
  • Continue to the end of the string. The total number of flips performed is the answer.

This approach ensures that each flip is only done when necessary and that we never do redundant flips. We only flip when the current effective bit and the target bit differ, and every flip affects all subsequent bits.

Example Walkthrough

Let's consider original = "001011" and target = "101101".

  1. At index 0: original[0]='0', target[0]='1'. Mismatch. Flip at index 0. Now bits 0-5 are flipped: 110100. Flips so far: 1.
  2. At index 1: effective bit is '1', target is '0'. Mismatch. Flip at index 1. Bits 1-5 are flipped: 1001011. Flips: 2.
  3. At index 2: effective bit is '0', target is '1'. Mismatch. Flip at index 2. Bits 2-5 are flipped: 101100. Flips: 3.
  4. At index 3: effective bit is '1', target is '1'. Match. No flip.
  5. At index 4: effective bit is '0', target is '0'. Match. No flip.
  6. At index 5: effective bit is '0', target is '1'. Mismatch. Flip at index 5. Bit 5 is flipped: 101101. Flips: 4.

Final string matches target after 4 flips.

Time and Space Complexity

  • Brute-force approach: For every mismatch, flip the suffix, potentially O(N^2) time for a string of length N, since each flip may take O(N) time.
  • Optimized approach: We traverse the string once, and each operation (checking and flipping the flip state) is O(1). So the total time complexity is O(N).
  • Space complexity is O(1) since we only use a few variables, regardless of input size.

Summary

The problem asks for the minimum number of suffix flips to turn one binary string into another. The elegant solution is to only flip when the current effective bit (after considering previous flips) doesn't match the target bit, and to keep track of the flip state as we traverse the string. This reduces the problem from a potentially quadratic brute-force to a linear, highly efficient solution.

Code Implementation

def minimumSuffixFlips(original: str, target: str) -> int:
    flips = 0
    flip_state = 0  # 0: even flips, 1: odd flips
    n = len(original)
    for i in range(n):
        curr_bit = original[i]
        # If number of flips so far is odd, flip the bit
        if flip_state % 2 == 1:
            curr_bit = '1' if curr_bit == '0' else '0'
        if curr_bit != target[i]:
            flips += 1
            flip_state ^= 1  # Toggle flip state
    return flips
      
int minimumSuffixFlips(string original, string target) {
    int flips = 0;
    int flipState = 0;
    int n = original.size();
    for (int i = 0; i < n; ++i) {
        char currBit = original[i];
        if (flipState % 2 == 1) {
            currBit = (currBit == '0') ? '1' : '0';
        }
        if (currBit != target[i]) {
            flips++;
            flipState ^= 1;
        }
    }
    return flips;
}
      
public int minimumSuffixFlips(String original, String target) {
    int flips = 0;
    int flipState = 0;
    int n = original.length();
    for (int i = 0; i < n; i++) {
        char currBit = original.charAt(i);
        if (flipState % 2 == 1) {
            currBit = (currBit == '0') ? '1' : '0';
        }
        if (currBit != target.charAt(i)) {
            flips++;
            flipState ^= 1;
        }
    }
    return flips;
}
      
function minimumSuffixFlips(original, target) {
    let flips = 0;
    let flipState = 0;
    for (let i = 0; i < original.length; i++) {
        let currBit = original[i];
        if (flipState % 2 === 1) {
            currBit = currBit === '0' ? '1' : '0';
        }
        if (currBit !== target[i]) {
            flips++;
            flipState ^= 1;
        }
    }
    return flips;
}