Given a string s containing characters '0', '1', and '?'. Generate all distinct binary strings that can be formed by replacing each '?' with either '0' or '1'. Return the strings in lexicographically increasing order.
Examples:
Input: s = "1??0?101"
Output: ["10000101", "10001101", "10100101", "10101101", "11000101", "11001101", "11100101", "11101101"]
Explanation: There are 3 wildcard characters, so 23 = 8 binary strings can be formed.Input: s = "10?"
Output: ["100", "101"]
Explanation: There is 1 wildcard character, so 2 binary strings can be formed.
Table of Content
[Naive Approach ] Generate All Binary Strings - O(2^n × n) Time and O(n) Space
The idea is to generate all possible binary strings of length equal to the given string. For each generated string, check whether it matches the given pattern. A generated string is considered valid if every fixed character ('0' or '1') matches the corresponding character in the given string, while a '?' can match either '0' or '1'.
- Let n be the length of the given string and initialize an empty list to store the valid binary strings.
- Generate all possible binary strings of length n using recursion.
- For each generated string, compare it with the given pattern.
- If a character in the pattern is '0' or '1', it must match the corresponding character in the generated string; '?' can match either '0' or '1'.
- If the generated string satisfies all positions, add it to the answer.
- Return all valid strings, which are generated in lexicographical order.
#include <bits/stdc++.h>
using namespace std;
// Recursively generates all binary strings of length n.
void generate(int idx, int n, string &curr, string &pattern, vector<string> &ans)
{
// A binary string of length n has been generated.
if (idx == n)
{
// Check whether the generated string matches the pattern.
bool valid = true;
for (int i = 0; i < n; i++)
{
if (pattern[i] != '?' && pattern[i] != curr[i])
{
valid = false;
break;
}
}
if (valid)
ans.push_back(curr);
return;
}
// Place '0' at the current position.
curr.push_back('0');
generate(idx + 1, n, curr, pattern, ans);
curr.pop_back();
// Place '1' at the current position.
curr.push_back('1');
generate(idx + 1, n, curr, pattern, ans);
curr.pop_back();
}
vector<string> generateStrings(string &s)
{
int n = s.size();
vector<string> ans;
string curr = "";
// Generate all possible binary strings.
generate(0, n, curr, s, ans);
return ans;
}
int main()
{
string s = "10?";
vector<string> res = generateStrings(s);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << "\"" << res[i] << "\"";
if (i + 1 < res.size())
cout << ", ";
}
cout << "]\n";
return 0;
}
import java.util.*;
class GFG {
// Recursively generates all binary strings of length n.
static void generate(int idx, int n, StringBuilder curr,
String pattern,
ArrayList<String> ans)
{
// A binary string of length n has been generated.
if (idx == n) {
// Check whether the generated string matches
// the pattern.
boolean valid = true;
for (int i = 0; i < n; i++) {
if (pattern.charAt(i) != '?'
&& pattern.charAt(i)
!= curr.charAt(i)) {
valid = false;
break;
}
}
if (valid)
ans.add(curr.toString());
return;
}
// Place '0' at the current position.
curr.append('0');
generate(idx + 1, n, curr, pattern, ans);
curr.deleteCharAt(curr.length() - 1);
// Place '1' at the current position.
curr.append('1');
generate(idx + 1, n, curr, pattern, ans);
curr.deleteCharAt(curr.length() - 1);
}
static ArrayList<String> generateStrings(String s)
{
int n = s.length();
ArrayList<String> ans = new ArrayList<>();
StringBuilder curr = new StringBuilder();
// Generate all possible binary strings.
generate(0, n, curr, s, ans);
return ans;
}
public static void main(String[] args)
{
String s = "10?";
List<String> res = generateStrings(s);
System.out.println(res);
}
}
# Recursively generates all binary strings of length n.
def generate(idx, n, curr, pattern, ans):
# A binary string of length n has been generated.
if idx == n:
# Check whether the generated string matches the pattern.
valid = True
for i in range(n):
if pattern[i] != '?' and pattern[i] != curr[i]:
valid = False
break
if valid:
ans.append("".join(curr))
return
# Place '0' at the current position.
curr.append('0')
generate(idx + 1, n, curr, pattern, ans)
curr.pop()
# Place '1' at the current position.
curr.append('1')
generate(idx + 1, n, curr, pattern, ans)
curr.pop()
def generateStrings(s):
n = len(s)
ans = []
curr = []
# Generate all possible binary strings.
generate(0, n, curr, s, ans)
return ans
# Driver Code
if __name__ == "__main__":
s = "10?"
print(generateStrings(s))
using System;
using System.Collections.Generic;
using System.Text;
class GFG {
// Recursively generates all binary strings of length n.
static void Generate(int idx, int n, StringBuilder curr,
string pattern, List<string> ans)
{
// A binary string of length n has been generated.
if (idx == n) {
// Check whether the generated string matches
// the pattern.
bool valid = true;
for (int i = 0; i < n; i++) {
if (pattern[i] != '?'
&& pattern[i] != curr[i]) {
valid = false;
break;
}
}
if (valid)
ans.Add(curr.ToString());
return;
}
// Place '0' at the current position.
curr.Append('0');
Generate(idx + 1, n, curr, pattern, ans);
curr.Remove(curr.Length - 1, 1);
// Place '1' at the current position.
curr.Append('1');
Generate(idx + 1, n, curr, pattern, ans);
curr.Remove(curr.Length - 1, 1);
}
static List<string> generateStrings(string s)
{
int n = s.Length;
List<string> ans = new List<string>();
StringBuilder curr = new StringBuilder();
// Generate all possible binary strings.
Generate(0, n, curr, s, ans);
return ans;
}
static void Main()
{
string s = "10?";
List<string> res = generateStrings(s);
Console.WriteLine(
"["
+ string.Join(
", ", res.ConvertAll(x => "\"" + x + "\""))
+ "]");
}
}
// Recursively generates all binary strings of length n.
function generate(idx, n, curr, pattern, ans)
{
// A binary string of length n has been generated.
if (idx === n) {
// Check whether the generated string matches the
// pattern.
let valid = true;
for (let i = 0; i < n; i++) {
if (pattern[i] !== "?"
&& pattern[i] !== curr[i]) {
valid = false;
break;
}
}
if (valid)
ans.push(curr.join(""));
return;
}
// Place '0' at the current position.
curr.push("0");
generate(idx + 1, n, curr, pattern, ans);
curr.pop();
// Place '1' at the current position.
curr.push("1");
generate(idx + 1, n, curr, pattern, ans);
curr.pop();
}
function generateStrings(s)
{
const n = s.length;
const ans = [];
const curr = [];
// Generate all possible binary strings.
generate(0, n, curr, s, ans);
return ans;
}
// Driver Code
const s = "10?";
console.log(generateStrings(s));
Output
["100", "101"]
[Expected Approach] Using Recursion and Backtracking - O(2^k × n) Time and O(n) Space
The idea is to process the string recursively from left to right. Whenever a '?' is encountered, replace it with '0' and '1' one by one and recursively process the remaining string. If the current character is '0' or '1', simply move to the next position. When the end of the string is reached, add the generated string to the answer. Placing '0' before '1' ensures lexicographical order.
- Start from the first character of the string.
- If the current character is '0' or '1', move to the next position.
- If the current character is '?', replace it with '0' and recursively process the remaining string.
- Backtrack, replace the same '?' with '1', and recursively process the remaining string.
- When all characters have been processed, add the current string to the answer.
- Return the list of all generated binary strings, which are naturally produced in lexicographical order.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Recursively generates all valid binary strings.
void solve(int idx, string &s, vector<string> &res)
{
// All characters have been processed.
// The current string is one valid binary string.
if (idx == s.length())
{
res.push_back(s);
return;
}
// If the current character is '?',
// replace it with both '0' and '1'.
if (s[idx] == '?')
{
// Replace '?' with '0' first to maintain
// lexicographical order.
s[idx] = '0';
solve(idx + 1, s, res);
// Replace '?' with '1' and generate
// the remaining strings.
s[idx] = '1';
solve(idx + 1, s, res);
// Restore the original character
// before returning (backtracking).
s[idx] = '?';
}
else
{
// If the current character is already
// fixed ('0' or '1'), move to the next position.
solve(idx + 1, s, res);
}
}
// Returns all possible binary strings that can be
// formed by replacing every '?' with '0' or '1'.
vector<string> generateStrings(string &s)
{
vector<string> res;
// Generate all valid binary strings.
solve(0, s, res);
return res;
}
int main()
{
string s = "10?";
vector<string> res = generateStrings(s);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << "\"" << res[i] << "\"";
if (i + 1 < res.size())
cout << ", ";
}
cout << "]\n";
return 0;
}
import java.util.*;
public class GFG {
// Recursively generates all valid binary strings.
static void solve(int idx, char[] arr,
ArrayList<String> res)
{
// All characters have been processed.
// The current string is one valid binary string.
if (idx == arr.length) {
res.add(new String(arr));
return;
}
// If the current character is '?',
// replace it with both '0' and '1'.
if (arr[idx] == '?') {
// Replace '?' with '0' first to maintain
// lexicographical order.
arr[idx] = '0';
solve(idx + 1, arr, res);
// Replace '?' with '1' and generate
// the remaining strings.
arr[idx] = '1';
solve(idx + 1, arr, res);
// Restore the original character
// before returning (backtracking).
arr[idx] = '?';
}
else {
// If the current character is already
// fixed ('0' or '1'), move to the next
// position.
solve(idx + 1, arr, res);
}
}
// Returns all possible binary strings that can be
// formed by replacing every '?' with '0' or '1'.
static ArrayList<String> generateStrings(String s)
{
ArrayList<String> res = new ArrayList<>();
char[] arr = s.toCharArray();
// Generate all valid binary strings.
solve(0, arr, res);
return res;
}
public static void main(String[] args)
{
String s = "10?";
List<String> res = generateStrings(s);
System.out.println(res);
}
}
# Recursively generates all valid binary strings.
def solve(idx, arr, res):
# All characters have been processed.
# The current string is one valid binary string.
if idx == len(arr):
res.append("".join(arr))
return
# If the current character is '?',
# replace it with both '0' and '1'.
if arr[idx] == "?":
# Replace '?' with '0' first to maintain
# lexicographical order.
arr[idx] = "0"
solve(idx + 1, arr, res)
# Replace '?' with '1' and generate
# the remaining strings.
arr[idx] = "1"
solve(idx + 1, arr, res)
# Restore the original character
# before returning (backtracking).
arr[idx] = "?"
else:
# If the current character is already
# fixed ('0' or '1'), move to the next position.
solve(idx + 1, arr, res)
# Returns all possible binary strings that can be
# formed by replacing every '?' with '0' or '1'.
def generateStrings(s):
res = []
arr = list(s)
# Generate all valid binary strings.
solve(0, arr, res)
return res
# Driver code
if __name__ == "__main__":
s = "10?"
res = generateStrings(s)
print(res)
using System;
using System.Collections.Generic;
public class GFG {
// Recursively generates all valid binary strings.
static void Solve(int idx, char[] arr, List<string> res)
{
// All characters have been processed.
// The current string is one valid binary string.
if (idx == arr.Length) {
res.Add(new string(arr));
return;
}
// If the current character is '?',
// replace it with both '0' and '1'.
if (arr[idx] == '?') {
// Replace '?' with '0' first to maintain
// lexicographical order.
arr[idx] = '0';
Solve(idx + 1, arr, res);
// Replace '?' with '1' and generate
// the remaining strings.
arr[idx] = '1';
Solve(idx + 1, arr, res);
// Restore the original character
// before returning (backtracking).
arr[idx] = '?';
}
else {
// If the current character is already
// fixed ('0' or '1'), move to the next
// position.
Solve(idx + 1, arr, res);
}
}
// Returns all possible binary strings that can be
// formed by replacing every '?' with '0' or '1'.
static List<string> generateStrings(string s)
{
List<string> res = new List<string>();
char[] arr = s.ToCharArray();
// Generate all valid binary strings.
Solve(0, arr, res);
return res;
}
public static void Main()
{
string s = "10?";
List<string> res = generateStrings(s);
Console.WriteLine(
"["
+ string.Join(
", ", res.ConvertAll(x => "\"" + x + "\""))
+ "]");
}
}
// Recursively generates all valid binary strings.
function solve(idx, arr, res)
{
// All characters have been processed.
// The current string is one valid binary string.
if (idx === arr.length) {
res.push(arr.join(""));
return;
}
// If the current character is '?',
// replace it with both '0' and '1'.
if (arr[idx] === "?") {
// Replace '?' with '0' first to maintain
// lexicographical order.
arr[idx] = "0";
solve(idx + 1, arr, res);
// Replace '?' with '1' and generate
// the remaining strings.
arr[idx] = "1";
solve(idx + 1, arr, res);
// Restore the original character
// before returning (backtracking).
arr[idx] = "?";
}
else {
// If the current character is already
// fixed ('0' or '1'), move to the next position.
solve(idx + 1, arr, res);
}
}
// Returns all possible binary strings that can be
// formed by replacing every '?' with '0' or '1'.
function generateStrings(s)
{
const res = [];
const arr = s.split("");
// Generate all valid binary strings.
solve(0, arr, res);
return res;
}
// Driver Code
let s = "10?";
let res = generateStrings(s);
console.log(res);
Output
["100", "101"]