Time Needed to Rearrange a Binary String
MedPrompt
You are given a binary string s. In one second, all occurrences of "01" are simultaneously replaced with "10". This process repeats until no occurrences of "01" exist.
Return the number of seconds needed to complete this process.
Example 1:
Input: s = "0110101"
Output: 4
Explanation:
After one second, s becomes "1011010".
After another second, s becomes "1101100".
After the third second, s becomes "1110100".
After the fourth second, s becomes "1111000".
No occurrence of "01" exists any longer, and the process needed 4 seconds to complete,
so we return 4.Example 2:
Input: s = "11100"
Output: 0
Explanation:
No occurrence of "01" exists in s, and the processes needed 0 seconds to complete,
so we return 0.
Constraints:
1 <= s.length <= 1000s[i]is either'0'or'1'.
Follow up:
Can you solve this problem in O(n) time complexity?
Approaches
2 approaches with complexity analysis and trade-offs.
The most intuitive way to solve this problem is to directly simulate the process described. We can model the passage of time with a loop, where each iteration represents one second. In each second, we scan the string and identify all occurrences of "01". We then replace them with "10" to produce the string's state for the next second. This process is repeated until no "01" substrings exist in the string. The total number of iterations will be the answer.
Algorithm
- Initialize a counter
secondsto 0. - Start a loop that continues as long as the string contains the substring
"01". - Inside the loop, increment
seconds. - To handle the simultaneous replacement of all
"01"occurrences, we must build a new version of the string in each iteration. AStringBuilderis suitable for this. - Iterate through the current string's characters. If we find a
"01"pattern starting at indexi, we append"10"to ourStringBuilderand advance our loop counter by 2. - Otherwise, we append the current character and advance by 1.
- After iterating through the entire string, we update our main string to this new version.
- The loop terminates when a full pass over the string finds no
"01"substrings. The value ofsecondsis the result.
Walkthrough
To implement this, we can use a while loop that continues as long as swaps are being made. Inside the loop, we count a second and then construct the next state of the string. A crucial detail is that all swaps happen simultaneously. This means we must base our swaps on the string's state at the beginning of the second. A simple way to achieve this is to build a new string (or StringBuilder) for the next state, rather than modifying the string in-place. We iterate through the current string, and whenever we see a "01", we append "10" to our new string. Otherwise, we append the character we are currently at. After the pass is complete, we update the current string to the new one we just built. If a pass completes with no swaps made, we have reached the final state and can stop.
class Solution { public int secondsToRemoveOccurrences(String s) { int seconds = 0; StringBuilder currentS = new StringBuilder(s); while (true) { boolean foundSwap = false; int i = 0; while (i < currentS.length() - 1) { if (currentS.charAt(i) == '0' && currentS.charAt(i + 1) == '1') { foundSwap = true; break; } i++; } if (!foundSwap) { break; } seconds++; StringBuilder nextS = new StringBuilder(); i = 0; while (i < currentS.length()) { if (i + 1 < currentS.length() && currentS.charAt(i) == '0' && currentS.charAt(i + 1) == '1') { nextS.append("10"); i += 2; } else { nextS.append(currentS.charAt(i)); i++; } } currentS = nextS; } return seconds; }}Complexity
Time
O(N * T), where N is the length of the string and T is the total number of seconds required. In the worst-case scenario, like the string `"011...1"`, a single '0' has to move N-1 positions, taking one second per position. Thus, T can be up to O(N), making the total time complexity O(N^2).
Space
O(N), where N is the length of the string. This is because in each iteration of the simulation, we create a new `StringBuilder` or string of length N to store the state of the string for the next second.
Trade-offs
Pros
The logic is straightforward and easy to implement as it directly follows the problem statement.
It is guaranteed to be correct.
Cons
The time complexity of O(N^2) can be too slow if the input string length
Nis large.It creates a new string or
StringBuilderin every iteration, which can be memory-intensive for very long strings, although within the given constraints it's acceptable.
Instead of a full simulation, we can find the answer in a single pass. The key idea is to analyze the constraints on the time required for the swaps. The total time is determined by the '0' that takes the longest to reach its final sorted position. This time is affected by the number of '1's it needs to pass and the number of other '0's that might be blocking its path. We can formulate a dynamic programming-like relation by iterating through the string and keeping track of the number of '0's seen and the time elapsed so far.
Algorithm
- Initialize two integer variables:
zeros = 0to count the number of '0's encountered so far, andseconds = 0to store the result. - Iterate through the input string
sfrom left to right, character by character. - If the current character is
'0', increment thezeroscounter. - If the current character is
'1':- Check if
zeros > 0. If not, this '1' is already in a sorted position relative to the characters seen so far, so we do nothing. - If
zeros > 0, it means this '1' must move left past all thezeros'0's we've seen. This process takes time. The total time (seconds) is constrained by two factors:- A '0' that was already moving for
secondsseconds needs one additional second to pass the current '1'. This implies the new time must be at leastseconds + 1. - A contiguous block of
zeros'0's needszerosseconds to fully move past a single '1' (e.g.,"001"->"010"->"100"takes 2 seconds). This implies the time must be at leastzeros.
- A '0' that was already moving for
- To satisfy both constraints, we update
seconds = Math.max(seconds + 1, zeros).
- Check if
- After iterating through the entire string, the
secondsvariable will hold the total time needed.
Walkthrough
We can iterate through the string from left to right, maintaining a count of zeros (zeros) seen so far and the calculated time (seconds). When we encounter a '0', we just increment zeros. When we encounter a '1', if there are any zeros to its left (zeros > 0), we know swaps must occur. The time required for these swaps is determined by the more restrictive of two conditions. First, any '0' that was already part of a seconds-long swap sequence will need one more second to get past this new '1', so the time must be at least seconds + 1. Second, a group of zeros '0's takes zeros seconds to move past a single '1'. Therefore, the updated time must be the maximum of these two values. This single pass correctly accumulates the maximum time required by any '0' to find its final position.
class Solution { public int secondsToRemoveOccurrences(String s) { int zeros = 0; int seconds = 0; for (char c : s.toCharArray()) { if (c == '0') { zeros++; } else if (zeros > 0) { // This '1' must be swapped with the '0's on its left. // The time is constrained by two factors: // 1. A '0' that took `seconds` to get to the position just before this '1' // needs one more second to pass it. Time >= seconds + 1. // 2. A block of `zeros` '0's needs `zeros` seconds to pass this '1'. // Time >= zeros. // The new time must satisfy both, so we take the maximum. seconds = Math.max(seconds + 1, zeros); } } return seconds; }}Complexity
Time
O(N), where N is the length of the string. This is because we perform a single pass through the string.
Space
O(1), as we only use a few variables (`zeros`, `seconds`) to keep track of the state, regardless of the input string size.
Trade-offs
Pros
Extremely efficient with a linear time complexity.
Uses constant extra space, making it very memory-efficient.
Cons
The logic is more abstract and less intuitive than the direct simulation, requiring a deeper understanding of the underlying process.
Solutions
Solution
class Solution {public int secondsToRemoveOccurrences(String s) { char[] cs = s.toCharArray(); boolean find = true; int ans = 0; while (find) { find = false; for (int i = 0; i < cs.length - 1; ++i) { if (cs[i] == '0' && cs[i + 1] == '1') { char t = cs[i]; cs[i] = cs[i + 1]; cs[i + 1] = t; ++i; find = true; } } if (find) { ++ans; } } return ans; }}class Solution {public: int secondsToRemoveOccurrences(string s) { bool find = true; int ans = 0; while (find) { find = false; for (int i = 0; i < s.size() - 1; ++i) { if (s[i] == '0' && s[i + 1] == '1') { swap(s[i], s[i + 1]); ++i; find = true; } } if (find) { ++ans; } } return ans; }};class Solution: def secondsToRemoveOccurrences(self, s: str) -> int: ans = 0 while s . count('01'): s = s . replace('01', '10') ans += 1 return ansVideo 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.