You are given a special binary string
as input, which is a binary string consisting only of '0's and '1's. A string is considered special if it is non-empty, has the same number of '1's and '0's, and for every prefix of the string, the number of '1's is greater than or equal to the number of '0's.
Your task is to rearrange the special substrings of the input string to create the lexicographically largest possible special binary string. You can decompose the string into special substrings, rearrange them in any order, and then concatenate them back together.
Constraints:
At first glance, the problem may seem to ask for all possible permutations of substrings, but the constraints of "special binary string" mean we can't just swap any characters. Instead, we must work with special substrings—substrings that are themselves special binary strings.
A brute-force approach would involve generating all possible decompositions into special substrings, permuting them, and checking which concatenation is lexicographically largest. However, this quickly becomes infeasible as the string grows.
The key insight is that the structure of special binary strings is recursive: any special string can be broken down into a list of special substrings. If we sort these substrings in descending lexicographical order and then recursively apply this process within each substring, we can always build the largest possible string.
This recursive, greedy approach leverages the problem's constraints and properties, avoiding the need for brute-force permutation.
This approach ensures that at every level of the recursive decomposition, the largest substrings are placed first, yielding the lexicographically greatest result.
Let's take the input s = "11011000"
.
1100
(from 0 to 3) is special.11011000
(from 0 to 7) is special.11011000
, after the first 1100
, we have 1000
(from 4 to 7), which is also special.1100
: its inner part is 10
, which is special but cannot be decomposed further.1000
: its inner part is 00
, which is not special (unequal count), so we stop.1100
and 1001
(if present), in descending order.11100100
.
Thus, 11011000
becomes 11100100
after rearrangement.
class Solution:
def makeLargestSpecial(self, s: str) -> str:
subs = []
count = i = 0
for j, ch in enumerate(s):
count += 1 if ch == '1' else -1
if count == 0:
# Recursively process the inner part
subs.append('1' + self.makeLargestSpecial(s[i+1:j]) + '0')
i = j + 1
subs.sort(reverse=True)
return ''.join(subs)
class Solution {
public:
string makeLargestSpecial(string s) {
vector<string> subs;
int count = 0, i = 0;
for (int j = 0; j < s.size(); ++j) {
count += (s[j] == '1') ? 1 : -1;
if (count == 0) {
subs.push_back("1" + makeLargestSpecial(s.substr(i + 1, j - i - 1)) + "0");
i = j + 1;
}
}
sort(subs.rbegin(), subs.rend());
string result;
for (auto &sub : subs) result += sub;
return result;
}
};
class Solution {
public String makeLargestSpecial(String s) {
List<String> subs = new ArrayList<>();
int count = 0, i = 0;
for (int j = 0; j < s.length(); ++j) {
count += s.charAt(j) == '1' ? 1 : -1;
if (count == 0) {
subs.add("1" + makeLargestSpecial(s.substring(i + 1, j)) + "0");
i = j + 1;
}
}
Collections.sort(subs, Collections.reverseOrder());
StringBuilder sb = new StringBuilder();
for (String sub : subs) sb.append(sub);
return sb.toString();
}
}
var makeLargestSpecial = function(s) {
let subs = [];
let count = 0, i = 0;
for (let j = 0; j < s.length; ++j) {
count += s[j] === '1' ? 1 : -1;
if (count === 0) {
subs.push('1' + makeLargestSpecial(s.slice(i + 1, j)) + '0');
i = j + 1;
}
}
subs.sort((a, b) => b.localeCompare(a));
return subs.join('');
};
Brute-force approach: Generating all possible decompositions and permutations would have factorial complexity, specifically O(n!), which is infeasible for strings longer than a few characters.
Optimized recursive approach: Each level of recursion processes each character once, and at each step, substrings are sorted. The worst-case time complexity is O(n2 log n), where n is the length of the string: O(n) for scanning and splitting, and O(k log k) for sorting k substrings at each recursion level. Since the depth of recursion is at most O(n), the overall complexity is acceptable for the input constraints.
Space complexity: O(n2) in the worst case, due to recursive stack and the storage of substrings.
The problem leverages the recursive structure of special binary strings. By decomposing the string into special substrings, recursively maximizing each, and sorting them in descending lexicographical order, we can efficiently build the largest possible special binary string. This approach is both elegant and efficient, sidestepping the need for brute-force permutations by exploiting the unique properties of the input.