Maximum Binary String After Change
MedPrompt
You are given a binary string binary consisting of only 0's or 1's. You can apply each of the following operations any number of times:
- Operation 1: If the number contains the substring
"00", you can replace it with"10".- For example,
"00010" -> "10010"
- For example,
- Operation 2: If the number contains the substring
"10", you can replace it with"01".- For example,
"00010" -> "00001"
- For example,
Return the maximum binary string you can obtain after any number of operations. Binary string x is greater than binary string y if x's decimal representation is greater than y's decimal representation.
Example 1:
Input: binary = "000110"
Output: "111011"
Explanation: A valid transformation sequence can be:
"000110" -> "000101"
"000101" -> "100101"
"100101" -> "110101"
"110101" -> "110011"
"110011" -> "111011"Example 2:
Input: binary = "01"
Output: "01"
Explanation: "01" cannot be transformed any further.
Constraints:
1 <= binary.length <= 105binaryconsist of'0'and'1'.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach treats the problem as a state-space search. Each unique binary string that can be formed is a state, and the allowed operations ("00" -> "10", "10" -> "01") are transitions between states. We can use a search algorithm like Breadth-First Search (BFS) or Depth-First Search (DFS) to explore all reachable states from the initial string. By keeping track of the lexicographically largest string found during the exploration, we can find the solution. A set is used to store visited states to prevent re-processing and getting stuck in cycles.
Algorithm
- Initialize a queue for Breadth-First Search (BFS) with the initial
binarystring. - Use a
HashSetto keep track of all visited strings to avoid cycles and redundant computations. - Initialize a variable
maxStringwith the initialbinarystring. - While the queue is not empty, dequeue a string
s. - Iterate through the string
sto find all occurrences of"00"and"10". - For each occurrence, apply the corresponding transformation (
"00" -> "10"or"10" -> "01") to generate anewString. - If
newStringhas not been visited: a. AddnewStringto the queue and the visited set. b. ComparenewStringwithmaxStringlexicographically and updatemaxStringifnewStringis larger. - After the BFS completes,
maxStringwill hold the maximum possible binary string.
Walkthrough
The brute-force method systematically explores every possible string that can be generated from the input. Starting with the given binary string, we apply the two operations at every possible position to generate a new set of strings. This process is repeated for each newly generated string until no new strings can be created. We use a queue for a BFS traversal to ensure we explore strings level by level, and a hash set to avoid redundant work on strings we've already seen. Throughout this process, we maintain a variable that stores the lexicographically greatest string encountered so far. While this method is guaranteed to find the correct answer, the number of possible strings can be astronomically large, making it impractical for anything but very small input strings.
Complexity
Time
O(S * N), where S is the number of reachable unique strings. The number of states S can be exponential in N, making the approach too slow for the given constraints.
Space
O(S * N), where S is the number of reachable unique strings and N is the length of the string. This is likely to be exponential and thus infeasible.
Trade-offs
Pros
Guaranteed to find the optimal solution.
Conceptually straightforward application of graph traversal algorithms.
Cons
Extremely high time complexity, making it infeasible for the given constraints.
Requires a large amount of memory to store all visited states, which can lead to memory overflow.
A highly efficient greedy approach can be formulated by analyzing the net effect of the operations. The operation "10" -> "01" allows a '0' to move left past '1's. The operation "00" -> "10" converts two '0's into a '1' and a '0'. This means we can transform all but one '0' into '1's. The leading '1's (before the first '0') cannot be moved. The rest of the string, which contains all the '0's, can be optimally rearranged. By consolidating all '0's, we can convert them into a sequence of '1's followed by a single '0'. This leads to a simple formula to directly construct the final, maximal string.
Algorithm
- Count the total number of zeros (
zeros) in the input stringbinary. - If
zerosis 0 or 1, no"00" -> "10"transformation is possible. The"10" -> "01"transformation would only yield a lexicographically smaller string. Thus, the string is already maximal. Return the originalbinarystring. - Find the index of the first '0' in the string. Let this be
first_zero_idx. This represents the number of leading '1's which are fixed in their positions. - The final string will consist of
n-1ones and a single zero. The key is to determine the position of this zero. - The final zero's position is calculated as
final_zero_pos = first_zero_idx + zeros - 1. - Construct the result: create a character array of length
nfilled with '1's, then set the character atfinal_zero_posto '0'. - Convert the character array to a string and return it.
Walkthrough
This optimal approach is based on a key insight: the final maximized string will contain at most one '0'. If the original string has k > 1 zeros, we can use the "00" -> "10" operation k-1 times to convert k-1 zeros into k-1 ones, leaving a single '0'. The "10" -> "01" operation allows us to effectively move this '0' around.
Any '1's at the beginning of the string (before the first '0') are stuck; no operation can move them or place a '0' before them. Let's say there are leading_ones such '1's. The rest of the string contains all the zeros and the remaining ones. This segment can be transformed into a string with zeros - 1 new '1's, all the original '1's from this segment, and one '0'. To maximize the overall string, we should place all possible '1's first. The transformed segment will become a block of '1's followed by a single '0'.
Therefore, the final '0' will be located at an index equal to the count of leading '1's plus the count of newly formed '1's (zeros - 1). This allows us to calculate the final position of the '0' and construct the string in a single pass.
import java.util.Arrays; class Solution { public String maximumBinaryString(String binary) { int n = binary.length(); int zeros = 0; int firstZeroIdx = -1; for (int i = 0; i < n; i++) { if (binary.charAt(i) == '0') { zeros++; if (firstZeroIdx == -1) { firstZeroIdx = i; } } } // If there are 0 or 1 zeros, the string cannot be improved. // "00"->"10" is not possible. "10"->"01" makes the string smaller. if (zeros <= 1) { return binary; } // The final string will have n-1 ones and one zero. // We need to find the position of this single zero. char[] resultChars = new char[n]; Arrays.fill(resultChars, '1'); // The zero will be placed after the leading ones and after the newly created ones. // Number of leading ones = firstZeroIdx. // Number of newly created ones = zeros - 1. int finalZeroPos = firstZeroIdx + zeros - 1; resultChars[finalZeroPos] = '0'; return new String(resultChars); }}Complexity
Time
O(N), where N is the length of the binary string. We perform a single pass to count zeros and find the first zero, and another pass to construct the result string.
Space
O(N) to store the character array for the result string. In Java, strings are immutable, so this space is necessary for the output.
Trade-offs
Pros
Extremely efficient with linear time complexity.
Low space complexity.
Simple to implement once the pattern is understood.
Cons
The logic is not immediately obvious and requires careful analysis of the operations' effects.
Solutions
Solution
class Solution {public String maximumBinaryString(String binary) { int k = binary.indexOf('0'); if (k == -1) { return binary; } int n = binary.length(); for (int i = k + 1; i < n; ++i) { if (binary.charAt(i) == '0') { ++k; } } char[] ans = binary.toCharArray(); Arrays.fill(ans, '1'); ans[k] = '0'; return String.valueOf(ans); }}public class Solution { public string MaximumBinaryString(string binary) { int k = binary.IndexOf('0'); if (k == -1) { return binary; } k += binary.Substring(k + 1).Count(c => c == '0'); return new string('1', k) + '0' + new string('1', binary.Length - k - 1); }}class Solution { public: string maximumBinaryString ( string binary ) { int k = binary . find ( '0' ); if ( k == binary . npos ) return binary ; int n = binary . size (); for ( int i = k + 1 ; i < n ; ++ i ) { if ( binary [ i ] == '0' ) { ++ k ; } } return string ( k , '1' ) + '0' + string ( n - k - 1 , '1' ); } };class Solution: def maximumBinaryString(self, binary: str) -> str: k = binary . find('0') if k == - 1: return binary k += binary[k + 1:]. count('0') return '1' * k + '0' + '1' * (len(binary) - k - 1)Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.