Special Binary String solution and explanation
9 more videos on this problem
Special Binary String | Detailed Intuition | Dry Run | Leetcode 761 | codestorywithMIKcodestorywithMIK · 34:37 · 12K views
761. Special Binary String (Leetcode Hard)Programming Live with Larry · 51:12 · 5K views
Leetcode 0761. Special Binary StringFearless Learner · 11:11 · 3K views
761. Special Binary String | Leetcode Daily - PythonLeetcode Daily · 6:11 · 1K views
Special Binary String | LeetCode 761 | Recursion & Lexicographical SortingSanyam IIT Guwahati · 21:34 · 1K views
Daily Leetcode #2152: Feb 20, 2026 - 761. Special Binary StringProgramming Live with Larry · 59:36 · 687 views
LeetCode 761: Special Binary StringAlitaCode · 28:30 · 663 views
LeetCode Hard: 761. Special Binary Stringrobzingcod · 29:56 · 618 views
761. Special Binary String |Special Binary String|Leetcode 761|Daily Leetcode problem| leetcode potdCode Thoughts · 11:44 · 323 views
Special Binary String | LeetCode 761 - Pythonimpoldev · 13:06 · 318 views
The problem
Special binary strings are binary strings with the following two properties:
- The number of
0's is equal to the number of1's. - Every prefix of the binary string has at least as many
1's as0's.
You are given a special binary string s.
A move consists of choosing two consecutive, non-empty, special substrings of s, and swapping them. Two strings are consecutive if the last character of the first string is exactly one index before the first character of the second string.
Return the lexicographically largest resulting string possible after applying the mentioned operations on the string.
Example 1:
Input: s = "11011000" Output: "11100100" Explanation: The strings "10" [occuring at s[1]] and "1100" [at s[3]] are swapped. This is the lexicographically largest string possible after some number of swaps.
Example 2:
Input: s = "10" Output: "10"
Constraints:
1 <= s.length <= 50s[i]is either'0'or'1'.sis a special binary string.
Approach overview
Problem Overview: You’re given a binary string that is special: it contains the same number of 1s and 0s, and every prefix has at least as many 1s as 0s. You can swap adjacent special substrings. The goal is to rearrange the string to produce the lexicographically largest possible result.
Approach 1: Brute Force Rearrangement (Exponential Time, Exponential Space)
The naive idea is to generate all valid swaps of adjacent special substrings and track the lexicographically largest result. Each step tries every possible split where both sides remain valid special strings. This quickly explodes because the number of permutations grows exponentially with the number of segments. Time complexity is roughly O(2^n) in the worst case with large recursion trees, and space complexity is also O(2^n) due to storing generated states. This approach mainly helps understand the problem constraints but is not practical for large inputs.
Approach 2: Stack / Balanced Decomposition (O(n^2) time, O(n) space)
A special binary string behaves similarly to balanced parentheses. Iterate through the string while counting 1s and 0s. Whenever the counts match, you’ve found a minimal valid special substring. Extract these segments and store them. Each segment can then be processed recursively and combined back. While this decomposition is efficient, naive concatenation or repeated comparisons during reordering can push the time complexity toward O(n^2). This technique highlights the structural similarity between this problem and balanced structures often discussed in stack problems.
Approach 3: Recursive Decomposition and Sorting (O(n log n) time, O(n) space)
The optimal strategy recursively breaks the string into its smallest special components. Scan the string while maintaining a counter: increment for 1 and decrement for 0. When the counter returns to zero, you’ve identified a complete special substring. Recursively solve the inner portion s[i+1:j], wrap it with 1 and 0, and add the result to a list.
After extracting all components, sort them in descending lexicographic order and concatenate. Larger segments starting with more leading 1s produce bigger lexicographic values, so sorting ensures the globally optimal arrangement. The scan is linear and the sorting step dominates with O(k log k) where k is the number of segments, leading to overall O(n log n) time and O(n) recursion space.
This technique combines ideas from string manipulation and divide‑and‑conquer recursion. The recursive structure ensures every nested special substring is maximized before assembling the final answer.
Recommended for interviews: Recursive decomposition with sorting is the expected solution. It demonstrates recognition of the balanced structure, correct recursive segmentation, and greedy ordering for lexicographic maximization. Interviewers typically want to see how you detect valid segments and recursively optimize them using recursion.
Approach 1: Recursive Decomposition and Sorting
This approach leverages recursion to decompose the special binary string into smaller special substrings, sort these components, and then rebuild the string to achieve the lexicographically largest string. This works because by sorting the special substrings in descending order, larger lexicographical strings are formed.
def makeLargestSpecial(s: str) -> str:
count = i = 0
res = []
for j, c in enumerate(s):
if c == '1':
count += 1
else:
count -= 1
if count == 0:
res.append('1' + makeLargestSpecial(s[i + 1:j]) + '0')
i = j + 1
return ''.join(sorted(res, reverse=True))import java.util.ArrayList;
import java.util.Collections;
class Solution {
public String makeLargestSpecial(String s) {
int count = 0, i = 0;
ArrayList<String> res = new ArrayList<>();
for (int j = 0; j < s.length(); j++) {
if (s.charAt(j) == '1') count++;
else count--;
if (count == 0) {
res.add('1' + makeLargestSpecial(s.substring(i + 1, j)) + '0');
i = j + 1;
}
}
Collections.sort(res, Collections.reverseOrder());
return String.join("", res);
}
}#include <vector>
#include <string>
#include <algorithm>
class Solution {
public:
std::string makeLargestSpecial(std::string s) {
int count = 0, i = 0;
std::vector<std::string> res;
for (int j = 0; j < s.size(); ++j) {
s[j] == '1' ? ++count : --count;
if (count == 0) {
res.push_back("1" + makeLargestSpecial(s.substr(i + 1, j - i - 1)) + "0");
i = j + 1;
}
}
std::sort(res.begin(), res.end(), std::greater<std::string>());
return std::accumulate(res.begin(), res.end(), std::string(""));
}
};var makeLargestSpecial = function(s) {
let count = 0, i = 0;
let res = [];
for (let j = 0; j < s.length; j++) {
s.charAt(j) === '1' ? count++ : count--;
if (count === 0) {
res.push('1' + makeLargestSpecial(s.substring(i + 1, j)) + '0');
i = j + 1;
}
}
res.sort((a, b) => b.localeCompare(a));
return res.join('');
};#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
// Function prototypes
char* makeLargestSpecial(const char* s);
// Utility function
int compare(const void* a, const void* b) {
return strcmp(*(const char**)b, *(const char**)a);
}
char* makeLargestSpecial(const char* s) {
int len = strlen(s);
int count = 0, i = 0, subIndex = 0;
char** substrings = (char**)malloc(len / 2 * sizeof(char*));
char* res = (char*)malloc(len + 1);
for (int j = 0; j < len; j++) {
s[j] == '1' ? count++ : count--;
if (count == 0) {
int size = j - i + 1;
char* sub = (char*)malloc(size + 1);
snprintf(sub, size + 1, "1%s0", makeLargestSpecial(s + i + 1));
substrings[subIndex++] = sub;
i = j + 1;
}
}
qsort(substrings, subIndex, sizeof(char*), compare);
res[0] = '\0';
for (int k = 0; k < subIndex; k++) {
strcat(res, substrings[k]);
free(substrings[k]);
}
free(substrings);
return res;
}using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
public string MakeLargestSpecial(string s) {
int count = 0, i = 0;
List<string> res = new List<string>();
for (int j = 0; j < s.Length; j++) {
if (s[j] == '1') count++;
else count--;
if (count == 0) {
res.Add('1' + MakeLargestSpecial(s.Substring(i + 1, j - i - 1)) + '0');
i = j + 1;
}
}
res.Sort((a, b) => string.Compare(b, a));
return string.Concat(res);
}
}The function recursively decomposes the string whenever a balance point is reached, i.e., when the count of '1's and '0's becomes zero. Once parts are decomposed, they are sorted in reverse (descending) order to achieve the lexicographically largest string.
Time Complexity: O(n^2), where n is the length of the string, due to recursive decomposition and sorting.
Space Complexity: O(n), for storing the results and recursion stack.
Approach 2: Recursion + Sorting
We can treat the special binary sequence as "valid parentheses", where 1 represents an opening parenthesis and 0 represents a closing parenthesis. For example, "11011000" can be viewed as "(()(()))".
Swapping two consecutive non-empty special substrings is equivalent to swapping two adjacent valid parentheses. We can use recursion to solve this problem.
We treat each "valid parenthesis" in string s as a part, process it recursively, and finally sort them to get the final answer.
The time complexity is O(n^2), and the space complexity is O(n), where n is the length of string s.
function makeLargestSpecial(s: string): string {
if (s.length === 0) {
return '';
}
const ans: string[] = [];
let cnt = 0;
for (let i = 0, j = 0; i < s.length; ++i) {
cnt += s[i] === '1' ? 1 : -1;
if (cnt === 0) {
const t = '1' + makeLargestSpecial(s.substring(j + 1, i)) + '0';
ans.push(t);
j = i + 1;
}
}
ans.sort((a, b) => b.localeCompare(a));
return ans.join('');
}func makeLargestSpecial(s string) string {
if s == "" {
return ""
}
ans := sort.StringSlice{}
cnt := 0
for i, j := 0, 0; i < len(s); i++ {
if s[i] == '1' {
cnt++
} else {
cnt--
}
if cnt == 0 {
ans = append(ans, "1"+makeLargestSpecial(s[j+1:i])+"0")
j = i + 1
}
}
sort.Sort(sort.Reverse(ans))
return strings.Join(ans, "")
}Complexity comparison
| Approach | Complexity |
|---|---|
| Recursive Decomposition and Sorting | Time Complexity: O(n^2), where n is the length of the string, due to recursive decomposition and sorting. Space Complexity: O(n), for storing the results and recursion stack. |
| Recursion + Sorting | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force Rearrangement | O(2^n) | O(2^n) | Understanding the structure of valid special substrings; not practical for real constraints |
| Stack / Balanced Decomposition | O(n^2) | O(n) | When identifying minimal balanced segments before optimization |
| Recursive Decomposition and Sorting | O(n log n) | O(n) | Optimal solution for interviews and production implementations |
Frequently asked questions
Is Special Binary String easy or hard?
Special Binary String is classified as Hard on LeetCode. The difficulty comes from recognizing that the string behaves like balanced parentheses and that optimal results require recursively maximizing inner segments and sorting them for lexicographic order.
Special Binary String Python/Java solution
Most Python and Java implementations follow the same recursive pattern: scan the string while maintaining a balance counter, recursively process inner substrings, store results in a list, sort the list in descending order, and join them. This keeps the time complexity around O(n log n) with O(n) extra space.
How to solve Special Binary String in O(n)?
A strictly O(n) algorithm is difficult because the optimal solution requires sorting special substrings to maximize lexicographic order. Most accepted implementations run in O(n log n) time due to the sorting step. The linear part of the algorithm comes from scanning the string and recursively decomposing balanced segments.
What is the best approach for Special Binary String?
Recursive decomposition with lexicographic sorting is the most effective approach. The algorithm splits the string into minimal special substrings using a balance counter, recursively maximizes each inner substring, then sorts the results in descending order before concatenation. This guarantees the largest possible lexicographic string.
Is Special Binary String asked at Google/Amazon/Meta?
Special Binary String is considered a hard-level string and recursion problem and has appeared in advanced interview preparation sets. Variants involving balanced structures, recursion, and lexicographic maximization are common at companies like Google, Amazon, and Meta.
What data structure is used in Special Binary String?
The solution mainly relies on recursion and dynamic substring construction. A list or array is used to store extracted special substrings before sorting them. Conceptually, the problem is similar to balanced parentheses problems often solved with stacks.
What is the time complexity of Special Binary String?
The optimal recursive decomposition approach runs in O(n log n) time. Scanning the string to detect special substrings takes O(n), while sorting the extracted components dominates with O(k log k), where k is the number of segments. Space complexity is O(n) due to recursion and substring storage.
