Given a number n, find all binary sequences of length 2n such that sum of first n bits is same as sum of last n bits.
Examples:
Input: N = 2
Output:
0101 1111 1001 0110 0000 1010
Input: N = 3
Output:
011011 001001 011101 010001 101011 111111
110011 101101 100001 110101 001010 011110
010010 001100 000000 010100 101110 100010
110110 100100
The idea is to fix first and last bits and then recur for remaining 2*(n-1) bits. There are four possibilities when we fix first and last bits –
- First and last bits are 1, remaining n – 1 bits on both sides should also have the same sum.
- First and last bits are 0, remaining n – 1 bits on both sides should also have the same sum.
- First bit is 1 and last bit is 0, sum of remaining n – 1 bits on left side should be 1 less than the sum n-1 bits on right side.
- First bit is 0 and last bit is 1, sum of remaining n – 1 bits on left side should be 1 more than the sum n-1 bits on right side.
Below is implementation of above idea –
C++
#include <bits/stdc++.h>
using namespace std;
void findAllSequences( int diff, char * out, int start, int end)
{
if ( abs (diff) > (end - start + 1) / 2)
return ;
if (start > end)
{
if (diff == 0)
cout << out << " " ;
return ;
}
out[start] = '0' , out[end] = '1' ;
findAllSequences(diff + 1, out, start + 1, end - 1);
out[start] = out[end] = '1' ;
findAllSequences(diff, out, start + 1, end - 1);
out[start] = out[end] = '0' ;
findAllSequences(diff, out, start + 1, end - 1);
out[start] = '1' , out[end] = '0' ;
findAllSequences(diff - 1, out, start + 1, end - 1);
}
int main()
{
int n = 2;
char out[2 * n + 1];
out[2 * n] = '\0' ;
findAllSequences(0, out, 0, 2*n - 1);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG
{
static void findAllSequences( int diff, char out[],
int start, int end)
{
if (Math.abs(diff) > (end - start + 1 ) / 2 )
return ;
if (start > end)
{
if (diff == 0 )
{
System.out.print(out);
System.out.print( " " );
}
return ;
}
out[start] = '0' ;
out[end] = '1' ;
findAllSequences(diff + 1 , out, start + 1 , end - 1 );
out[start] = out[end] = '1' ;
findAllSequences(diff, out, start + 1 , end - 1 );
out[start] = out[end] = '0' ;
findAllSequences(diff, out, start + 1 , end - 1 );
out[start] = '1' ;
out[end] = '0' ;
findAllSequences(diff - 1 , out, start + 1 , end - 1 );
}
public static void main (String[] args)
{
int n = 2 ;
char [] out = new char [ 2 * n + 1 ];
out[ 2 * n] = '\0' ;
findAllSequences( 0 , out, 0 , 2 *n - 1 );
}
}
|
Python3
def findAllSequences(diff, out, start, end):
if ( abs (diff) > (end - start + 1 ) / / 2 ):
return ;
if (start > end):
if (diff = = 0 ):
print (''.join( list (out)),end = " " );
return ;
out[start] = '0' ;
out[end] = '1' ;
findAllSequences(diff + 1 , out, start + 1 , end - 1 );
out[start] = out[end] = '1' ;
findAllSequences(diff, out, start + 1 , end - 1 );
out[start] = out[end] = '0' ;
findAllSequences(diff, out, start + 1 , end - 1 );
out[start] = '1' ;
out[end] = '0' ;
findAllSequences(diff - 1 , out, start + 1 , end - 1 );
n = 2 ;
out = [""] * ( 2 * n);
findAllSequences( 0 , out, 0 , 2 * n - 1 );
|
C#
using System;
class GFG {
static void findAllSequences( int diff,
char []outt, int start, int end)
{
if (Math.Abs(diff) > (end - start
+ 1) / 2)
return ;
if (start > end)
{
if (diff == 0)
{
Console.Write(outt);
Console.Write( " " );
}
return ;
}
outt[start] = '0' ;
outt[end] = '1' ;
findAllSequences(diff + 1, outt,
start + 1, end - 1);
outt[start] = outt[end] = '1' ;
findAllSequences(diff, outt,
start + 1, end - 1);
outt[start] = outt[end] = '0' ;
findAllSequences(diff, outt,
start + 1, end - 1);
outt[start] = '1' ;
outt[end] = '0' ;
findAllSequences(diff - 1, outt,
start + 1, end - 1);
}
public static void Main ()
{
int n = 2;
char []outt = new char [2 * n + 1];
outt[2 * n] = '\0' ;
findAllSequences(0, outt, 0, 2*n - 1);
}
}
|
PHP
<?php
function findAllSequences( $diff , $out , $start , $end )
{
if ( abs ( $diff ) > (int)(( $end - $start + 1) / 2))
return ;
if ( $start > $end )
{
if ( $diff == 0)
print (implode( "" , $out ). " " );
return ;
}
$out [ $start ] = '0' ;
$out [ $end ] = '1' ;
findAllSequences( $diff + 1, $out , $start + 1, $end - 1);
$out [ $start ] = $out [ $end ] = '1' ;
findAllSequences( $diff , $out , $start + 1, $end - 1);
$out [ $start ] = $out [ $end ] = '0' ;
findAllSequences( $diff , $out , $start + 1, $end - 1);
$out [ $start ] = '1' ;
$out [ $end ] = '0' ;
findAllSequences( $diff - 1, $out , $start + 1, $end - 1);
}
$n = 2;
$out = array_fill (0,2* $n , "" );
findAllSequences(0, $out , 0, 2* $n - 1);
?>
|
Javascript
<script>
function findAllSequences(diff, outt, start, end)
{
if (Math.abs(diff) > parseInt((end - start + 1) / 2, 10))
return ;
if (start > end)
{
if (diff == 0)
{
document.write(outt.join( "" ));
document.write( " " );
}
return ;
}
outt[start] = '0 ';
outt[end] = ' 1 ';
findAllSequences(diff + 1, outt, start + 1, end - 1);
// fill first and last bits as 1
outt[start] = outt[end] = ' 1 ';
findAllSequences(diff, outt, start + 1, end - 1);
// fill first and last bits as 0
outt[start] = outt[end] = ' 0 ';
findAllSequences(diff, outt, start + 1, end - 1);
// fill first bit as 1 and last
// bit as 0
outt[start] = ' 1 ';
outt[end] = ' 0 ';
findAllSequences(diff - 1, outt, start + 1, end - 1);
}
// input number
let n = 2;
// allocate string containing 2*n
// characters
let outt = new Array(2 * n + 1);
// null terminate output array
outt[2 * n] = ' \0';
findAllSequences(0, outt, 0, 2*n - 1);
</script>
|
Output0101 1111 1001 0110 0000 1010
Time Complexity: O(()* N)
4^N because of 4 recursive calls, and N (simplified from 2N) for time spent printing strings of size 2N
Auxiliary Space: O(N)
There is another approach by which we generate all possible strings of length n and store them in a list at an index representing their sum. Then, we iterate through each list and generate the strings of size 2n by printing each string with all other strings in the list adding up to the same value.
C++
#include <bits/stdc++.h>
using namespace std;
void generateSequencesWithSum(
int n, vector<vector<string> >& sumToString,
vector<string> sequence, int sumSoFar)
{
if (n == 0) {
string seq = "" ;
for ( int i = 0; i < sequence.size(); i++) {
seq = seq + sequence[i];
}
vector<string> x = sumToString[sumSoFar];
x.push_back(seq);
sumToString[sumSoFar] = x;
return ;
}
sequence.push_back( "0" );
generateSequencesWithSum(n - 1, sumToString, sequence,
sumSoFar);
sequence.erase(sequence.begin());
sequence.push_back( "1" );
generateSequencesWithSum(n - 1, sumToString, sequence,
sumSoFar + 1);
sequence.erase(sequence.begin());
}
void permuteSequences(vector<vector<string> > sumToString)
{
for ( int sumIndexArr = 0;
sumIndexArr < sumToString.size(); sumIndexArr++) {
for ( int sequence1 = 0;
sequence1 < sumToString[sumIndexArr].size();
sequence1++) {
for ( int sequence2 = 0;
sequence2
< sumToString[sumIndexArr].size();
sequence2++) {
if (sumIndexArr == sumToString.size() - 1
&& sequence1
== sumToString[sumIndexArr]
.size()
- 1
&& sequence2
== sumToString[sumIndexArr]
.size()
- 1) {
cout << "1111 " ;
}
else {
cout << sumToString[sumIndexArr]
[sequence1]
+ sumToString[sumIndexArr]
[sequence2]
<< " " ;
}
}
}
}
}
void findAllSequences( int n)
{
vector<vector<string> > sumToString;
for ( int i = 0; i < n + 1; i++) {
sumToString.push_back(
vector<string>());
}
generateSequencesWithSum(n, sumToString,
vector<string>(), 0);
permuteSequences(sumToString);
}
int main()
{
findAllSequences(2);
return 0;
}
|
Java
import java.util.*;
class GFG {
static void findAllSequences( int n)
{
ArrayList<ArrayList<String> > sumToString
= new ArrayList<ArrayList<String> >();
for ( int i = 0 ; i < n + 1 ; i++) {
sumToString.add(
new ArrayList<String>());
}
generateSequencesWithSum(
n, sumToString, new ArrayList<String>(), 0 );
permuteSequences(sumToString);
}
static void generateSequencesWithSum(
int n, ArrayList<ArrayList<String> > sumToString,
ArrayList<String> sequence, int sumSoFar)
{
if (n == 0 ) {
String seq = "" ;
for ( int i = 0 ; i < sequence.size(); i++) {
seq = seq + sequence.get(i);
}
ArrayList<String> x = sumToString.get(sumSoFar);
x.add(seq);
sumToString.set(sumSoFar, x);
return ;
}
sequence.add( "0" );
generateSequencesWithSum(n - 1 , sumToString,
sequence, sumSoFar);
sequence.remove( 0 );
sequence.add( "1" );
generateSequencesWithSum(n - 1 , sumToString,
sequence, sumSoFar + 1 );
sequence.remove( 0 );
}
static void permuteSequences(
ArrayList<ArrayList<String> > sumToString)
{
for ( int sumIndexArr = 0 ;
sumIndexArr < sumToString.size();
sumIndexArr++) {
for ( int sequence1 = 0 ;
sequence1
< sumToString.get(sumIndexArr).size();
sequence1++) {
for ( int sequence2 = 0 ;
sequence2
< sumToString.get(sumIndexArr).size();
sequence2++) {
if (sumIndexArr
== sumToString.size() - 1
&& sequence1
== sumToString
.get(sumIndexArr)
.size()
- 1
&& sequence2
== sumToString
.get(sumIndexArr)
.size()
- 1 ) {
System.out.print( "1111" );
}
else {
System.out.println(
sumToString.get(sumIndexArr)
.get(sequence1)
+ sumToString.get(sumIndexArr)
.get(sequence2));
}
}
}
}
}
public static void main(String[] args)
{
findAllSequences( 2 );
}
}
|
Python3
def findAllSequences(n):
sumToString = [[] for x in range (n + 1 )]
generateSequencesWithSum(n, sumToString, [], 0 )
permuteSequences(sumToString)
def generateSequencesWithSum(n, sumToString, sequence, sumSoFar):
if n = = 0 :
sumToString[sumSoFar].append("".join(sequence))
return
sequence.append( "0" )
generateSequencesWithSum(n - 1 , sumToString, sequence, sumSoFar)
sequence.pop()
sequence.append( "1" )
generateSequencesWithSum(n - 1 , sumToString, sequence, sumSoFar + 1 )
sequence.pop()
def permuteSequences(sumToString):
for sumIndexArr in sumToString:
for sequence1 in sumIndexArr:
for sequence2 in sumIndexArr:
print (sequence1 + sequence2)
findAllSequences( 2 )
|
C#
using System;
using System.Collections.Generic;
class GFG {
static void findAllSequences( int n)
{
List<List< string >> sumToString = new List<List< string >>();
for ( int i = 0; i < n + 1; i++)
{
sumToString.Add( new List< string >());
}
generateSequencesWithSum(n, sumToString, new List< string >(), 0);
permuteSequences(sumToString);
}
static void generateSequencesWithSum( int n, List<List< string >> sumToString, List< string > sequence, int sumSoFar)
{
if (n == 0)
{
string seq = "" ;
for ( int i = 0; i < sequence.Count; i++)
{
seq = seq + sequence[i];
}
sumToString[sumSoFar].Add(seq);
return ;
}
sequence.Add( "0" );
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar);
sequence.RemoveAt(0);
sequence.Add( "1" );
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar+1);
sequence.RemoveAt(0);
}
static void permuteSequences(List<List< string >> sumToString)
{
for ( int sumIndexArr = 0; sumIndexArr < sumToString.Count; sumIndexArr++)
{
for ( int sequence1 = 0; sequence1 < sumToString[sumIndexArr].Count; sequence1++)
{
for ( int sequence2 = 0; sequence2 < sumToString[sumIndexArr].Count; sequence2++)
{
if (sumIndexArr == sumToString.Count-1 && sequence1 == sumToString[sumIndexArr].Count-1 && sequence2 == sumToString[sumIndexArr].Count-1)
{
Console.Write( "1111" );
}
else
{
Console.WriteLine(sumToString[sumIndexArr][sequence1] + sumToString[sumIndexArr][sequence2]);
}
}
}
}
}
static void Main() {
findAllSequences(2);
}
}
|
Javascript
<script>
function findAllSequences(n)
{
let sumToString = [];
for (let i = 0; i < n + 1; i++)
{
sumToString.push([]);
}
generateSequencesWithSum(n, sumToString, [], 0);
permuteSequences(sumToString);
}
function generateSequencesWithSum(n, sumToString, sequence, sumSoFar)
{
if (n == 0)
{
sumToString[sumSoFar].push(sequence.join( "" ));
return ;
}
sequence.push( "0" );
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar);
sequence.shift();
sequence.push( "1" );
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar+1);
sequence.shift();
}
function permuteSequences(sumToString)
{
for (let sumIndexArr = 0; sumIndexArr < sumToString.length; sumIndexArr++)
{
for (let sequence1 = 0; sequence1 < sumToString[sumIndexArr].length; sequence1++)
{
for (let sequence2 = 0; sequence2 < sumToString[sumIndexArr].length; sequence2++)
{
if (sumIndexArr == sumToString.length-1 && sequence1 == sumToString[sumIndexArr].length-1 && sequence2 == sumToString[sumIndexArr].length-1)
{
document.write( "1111" );
}
else
{
document.write(sumToString[sumIndexArr][sequence1] + sumToString[sumIndexArr][sequence2] + "</br>" );
}
}
}
}
}
findAllSequences(2);
</script>
|
Output0000 0101 0110 1001 1010 1111
Time complexity analysis:
generateSequencesWithSum = O((2N)*N)
- 2N: we generate all permutation of binary strings of size N
- N: convert the list of characters to a string and store into array. This is done in the base case.
permuteSequences = O((2N) * N!/(N/2)!2 * N)
- 2N: we iterate through all the string generated of size n
- N!/(N/2)!2: This one is a bit challenging to explain
let’s take N = 2 as an example. Our array of possible sequence of size n would be:
array index | 0 | 1 | 2 |
list of strings | 00 | 01,10 | 11 |
In the list of strings which the index represents the sum, we get the count of strings of size 2n by using “n choose k” formula. I our case it would be nCk *nCk where k represents the number of 1s in each half of the string of size 2n:
k = 0, we have (2C0)^2 = 1 string (0000)
k = 1, we have (2C1)^2 string = 4 strings(0101 0110 1001 1010)
k = 2, we have (2c2)^2 = 1 string (1111)
We get our longest list of string when k = N/2, hence NCN/2 = N!/[(N/2)! * (N – N/2)!] which simplifies to NCN/2 = N!/(N/2)!2
Hence, for each element, we must iterate through, at most, NCN/2 for forming strings of length 2N
Without formal proof, if we graph 2^N and N!/(N/2)!2, we see that 2N has a faster growth rate than the latter. Therefore O(2N* N!/(N/2)2 ) < O(2N*2N) = O(22n) = O(4N)
Graph of 2^x and nC(n/2)
- N: we must print each string of size 2N
Finally we can ignore the time complexity of generateSequencesWithSum because permuteSequence is the leading term
Time complexity: O(2N * N!/(N/2)!2 * N) (better than the first solution of O((4^N) * N, see explanation above for further details)
Auxiliary space: O(2N) because we store all binary string permutations of size N
C++
#include<bits/stdc++.h>
using namespace std;
class FirstHalf {
public :
string data;
int sum;
FirstHalf(string data, int sum) {
this ->data = data;
this ->sum = sum;
}
};
map< int , vector<string>> mp;
vector<FirstHalf> firstHalf;
int sumOfString(string s) {
int sum = 0;
for ( auto c: s) {
sum += (c - '0' );
}
return sum;
}
void perm(string p, char * bin, int level, int n)
{
if (level == 0)
{
int sum = sumOfString(p);
firstHalf.push_back(FirstHalf(p, sum));
mp[sum].push_back(p);
return ;
}
for ( int i = 0; i < n; i++) {
char c = bin[i];
perm(p+c, bin, level-1, n);
}
}
void result() {
int i = 0;
for ( auto first: firstHalf)
{
int sum = first.sum;
vector<string> secondHalf = mp[sum];
for ( auto second: secondHalf)
{
cout << first.data + second << " " ;
i++;
if (i % 6 == 0)
cout << endl;
}
}
}
int main(){
char up[2] = { '0' , '1' };
int n = 2;
string x = "" ;
perm(x, up, n, n);
result();
return 0;
}
|
Java
import java.util.*;
class GFG {
static class FirstHalf {
String data;
int sum;
FirstHalf(String data, int sum) {
this .data = data;
this .sum = sum;
}
}
static Map<Integer, ArrayList<String>> map = new HashMap<>();
static List<FirstHalf> firstHalf = new ArrayList<>();
public static int sumOfString(String s) {
int sum = 0 ;
for ( char c: s.toCharArray()) {
sum += c - '0' ;
}
return sum;
}
public static void perm(String p, char [] bin, int level, int n) {
if (level == 0 ) {
int sum = sumOfString(p);
firstHalf.add( new FirstHalf(p, sum));
map.putIfAbsent(sum, new ArrayList<String>());
map.get(sum).add(p);
return ;
}
for ( char c: bin) {
perm(p+c, bin, level- 1 , n);
}
}
public static void result() {
int i = 0 ;
for (FirstHalf first: firstHalf) {
int sum = first.sum;
ArrayList<String> secondHalf = map.get(sum);
for (String second: secondHalf) {
System.out.print(first.data+second+ " " );
i++;
if (i % 6 == 0 )
System.out.println();
}
}
}
public static void main(String[] args) {
char [] up = { '0' , '1' };
int n = 2 ;
perm( "" , up, n, n);
result();
}
}
|
Python3
class FirstHalf:
def __init__( self , data, sum ):
self .data = data
self . sum = sum
map = {}
firstHalf = []
def sumOfString(s):
sum = 0
for i in range ( len (s)):
sum + = ord (s[i]) - ord ( '0' )
return sum
def perm(p, bin , level, n):
if level = = 0 :
sum = sumOfString(p)
firstHalf.append(FirstHalf(p, sum ))
if sum not in map :
map [ sum ] = []
map [ sum ].append(p)
return
for i in range ( len ( bin )):
perm(p + bin [i], bin , level - 1 , n)
def result():
i = 0
for j in range ( len (firstHalf)):
sum = firstHalf[j]. sum
secondHalf = map [ sum ]
for k in range ( len (secondHalf)):
print (firstHalf[j].data + secondHalf[k] + " " , end = "")
i = i + 1
if (i % 6 = = 0 ):
print ( '\n' )
up = [ '0' , '1' ]
n = 2
perm("", up, n, n)
result()
|
C#
using System;
using System.Collections.Generic;
class FirstHalf {
public string data;
public int sum;
public FirstHalf( string data, int sum) {
this .data = data;
this .sum = sum;
}
}
class Gfg
{
static Dictionary< int , List< string >> mp = new Dictionary< int , List< string >>();
static List<FirstHalf> firstHalf = new List<FirstHalf>();
static int sumOfString( string s) {
int sum = 0;
foreach ( char c in s) {
sum += (c - '0' );
}
return sum;
}
static void perm( string p, char [] bin, int level, int n) {
if (level == 0) {
int sum = sumOfString(p);
firstHalf.Add( new FirstHalf(p, sum));
if (mp.ContainsKey(sum)) {
mp[sum].Add(p);
} else {
mp.Add(sum, new List< string > { p });
}
return ;
}
for ( int i = 0; i < n; i++) {
char c = bin[i];
perm(p + c, bin, level - 1, n);
}
}
static void result() {
int i = 0;
foreach (FirstHalf first in firstHalf) {
int sum = first.sum;
List< string > secondHalf = mp[sum];
foreach ( string second in secondHalf) {
Console.Write(first.data + second + " " );
i++;
if (i % 6 == 0)
Console.WriteLine();
}
}
}
static void Main( string [] args) {
char [] up = { '0' , '1' };
int n = 2;
string x = "" ;
perm(x, up, n, n);
result();
}
}
|
Javascript
class FirstHalf {
constructor(data, sum) {
this .data = data;
this .sum = sum;
}
}
const map = new Map();
const firstHalf = [];
function sumOfString(s) {
let sum = 0;
for (let i = 0; i < s.length; i++) {
sum += s.charCodeAt(i) - '0' .charCodeAt(0);
}
return sum;
}
function perm(p, bin, level, n)
{
if (level == 0)
{
let sum = sumOfString(p);
firstHalf.push( new FirstHalf(p, sum));
if (!map.has(sum)) map.set(sum, []);
map.get(sum).push(p);
return ;
}
for (let i = 0; i < bin.length; i++) {
perm(p+bin[i], bin, level-1, n);
}
}
function result() {
let i = 0;
for (let j = 0; j < firstHalf.length; j++)
{
let sum = firstHalf[j].sum;
let secondHalf = map.get(sum);
for (let k = 0; k < secondHalf.length; k++)
{
process.stdout.write(firstHalf[j].data + secondHalf[k] + " " );
i++;
if (i % 6 == 0)
process.stdout.write( '\n' );
}
}
}
const up = [ '0' , '1' ];
const n = 2;
perm( "" , up, n, n);
result();
|
Output0000 0101 0110 1001 1010 1111
Algorithm:
1. Generate all binary permutations of size n
2. Calculate sum of the bits of each permutation and remember it for second half
[for ex: for n=2, remember there are two strings with sum = 1 i.e. “01”, “10” ]
3. Iterate all the generated permutations and for each of them append the second half according to the sum of the bits
Time complexity analysis:
sumOfString() = O(N) : traverse each bit and add it to sum
perm() = O(2N * N)
2N * N : we generate all permutations of binary bits of size N and find sum of the bits for each permutation
result() = O((2N) * (N!/(N/2)!)2)
2N: we iterate through all possible permutations of size N (first-Half)
NCN/2 = N!/(N/2)!2 : (second-Half maximum size) : explanation below:
let’s take N = 4 as an example.:
//Hash-Map looks like
0 -> [0000] …………………………..(list-size: 4C0 = 1)
1 -> [0001, 0010, 0100, 1000] …………………………..(list-size: 4C1 = 4)
2 -> [0011, 0101, 0110, 1001, 1010, 1100] …………………………..(list-size: 4C2 = 6)
3 -> [0111, 1011, 1101, 1110] …………………………..(list-size: 4C3 = 4)
4 -> [1111] …………………………..(list-size: 4C4 = 1)
We observe here that each list has a size of N choose Key which will be maximum at N choose N/2
Since we are iterating all the 2N permutations and appending second half from the map. The map has the maximum sized list at N/2 position.
Worst case occurs in N/2 position where we’ve to traverse NCN/2 = N!/(N/2)!2 permutations.
Time complexity: O(2N * N!/(N/2)!2 )
Auxiliary space: O(2N) because we store all binary string permutations of size N
Last Updated :
20 Mar, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...