Find all even length binary sequences with same sum of first and second half bits
Last Updated :
20 Mar, 2023
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++
// C++ program to print even length binary sequences
// whose sum of first and second half bits is same
#include <bits/stdc++.h>
using namespace std;
// Function to print even length binary sequences
// whose sum of first and second half bits is same
// diff --> difference between sums of first n bits
// and last n bits
// out --> output array
// start --> starting index
// end --> ending index
void findAllSequences(int diff, char* out, int start, int end)
{
// We can't cover difference of more than n with 2n bits
if (abs(diff) > (end - start + 1) / 2)
return;
// if all bits are filled
if (start > end)
{
// if sum of first n bits and last n bits are same
if (diff == 0)
cout << out << " ";
return;
}
// fill first bit as 0 and last bit as 1
out[start] = '0', out[end] = '1';
findAllSequences(diff + 1, out, start + 1, end - 1);
// fill first and last bits as 1
out[start] = out[end] = '1';
findAllSequences(diff, out, start + 1, end - 1);
// fill first and last bits as 0
out[start] = out[end] = '0';
findAllSequences(diff, out, start + 1, end - 1);
// fill first bit as 1 and last bit as 0
out[start] = '1', out[end] = '0';
findAllSequences(diff - 1, out, start + 1, end - 1);
}
// Driver program
int main()
{
// input number
int n = 2;
// allocate string containing 2*n characters
char out[2 * n + 1];
// null terminate output array
out[2 * n] = '\0';
findAllSequences(0, out, 0, 2*n - 1);
return 0;
}
Java
// Java program to print even length binary
// sequences whose sum of first and second
// half bits is same
import java.io.*;
import java.util.*;
class GFG
{
// Function to print even length binary sequences
// whose sum of first and second half bits is same
// diff --> difference between sums of first n bits
// and last n bits
// out --> output array
// start --> starting index
// end --> ending index
static void findAllSequences(int diff, char out[],
int start, int end)
{
// We can't cover difference of more
// than n with 2n bits
if (Math.abs(diff) > (end - start + 1) / 2)
return;
// if all bits are filled
if (start > end)
{
// if sum of first n bits and
// last n bits are same
if (diff == 0)
{
System.out.print(out);
System.out.print(" ");
}
return;
}
// fill first bit as 0 and last bit as 1
out[start] = '0';
out[end] = '1';
findAllSequences(diff + 1, out, start + 1, end - 1);
// fill first and last bits as 1
out[start] = out[end] = '1';
findAllSequences(diff, out, start + 1, end - 1);
// fill first and last bits as 0
out[start] = out[end] = '0';
findAllSequences(diff, out, start + 1, end - 1);
// fill first bit as 1 and last bit as 0
out[start] = '1';
out[end] = '0';
findAllSequences(diff - 1, out, start + 1, end - 1);
}
// Driver program
public static void main (String[] args)
{
// input number
int n = 2;
// allocate string containing 2*n characters
char[] out = new char[2 * n + 1];
// null terminate output array
out[2 * n] = '\0';
findAllSequences(0, out, 0, 2*n - 1);
}
}
// This code is contributed by Pramod Kumar
Python3
# Python3 program to print even length binary sequences
# whose sum of first and second half bits is same
# Function to print even length binary sequences
# whose sum of first and second half bits is same
# diff --> difference between sums of first n bits
# and last n bits
# out --> output array
# start --> starting index
# end --> ending index
def findAllSequences(diff, out, start, end):
# We can't cover difference of more than n with 2n bits
if (abs(diff) > (end - start + 1) // 2):
return;
# if all bits are filled
if (start > end):
# if sum of first n bits and last n bits are same
if (diff == 0):
print(''.join(list(out)),end=" ");
return;
# fill first bit as 0 and last bit as 1
out[start] = '0';
out[end] = '1';
findAllSequences(diff + 1, out, start + 1, end - 1);
# fill first and last bits as 1
out[start] = out[end] = '1';
findAllSequences(diff, out, start + 1, end - 1);
# fill first and last bits as 0
out[start] = out[end] = '0';
findAllSequences(diff, out, start + 1, end - 1);
# fill first bit as 1 and last bit as 0
out[start] = '1';
out[end] = '0';
findAllSequences(diff - 1, out, start + 1, end - 1);
# Driver program
# input number
n = 2;
# allocate string containing 2*n characters
out=[""]*(2*n);
findAllSequences(0, out, 0, 2*n - 1);
# This code is contributed by mits
C#
// C# program to print even length binary
// sequences whose sum of first and second
// half bits is same
using System;
class GFG {
// Function to print even length binary
// sequences whose sum of first and
// second half bits is same
// diff --> difference between sums of
// first n bits
// and last n bits
// out --> output array
// start --> starting index
// end --> ending index
static void findAllSequences(int diff,
char []outt, int start, int end)
{
// We can't cover difference of
// more than n with 2n bits
if (Math.Abs(diff) > (end - start
+ 1) / 2)
return;
// if all bits are filled
if (start > end)
{
// if sum of first n bits and
// last n bits are same
if (diff == 0)
{
Console.Write(outt);
Console.Write(" ");
}
return;
}
// fill first bit as 0 and last bit
// as 1
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);
}
// Driver program
public static void Main ()
{
// input number
int n = 2;
// allocate string containing 2*n
// characters
char []outt = new char[2 * n + 1];
// null terminate output array
outt[2 * n] = '\0';
findAllSequences(0, outt, 0, 2*n - 1);
}
}
// This code is contributed by nitin mittal.
PHP
<?php
// PHP program to print even length binary sequences
// whose sum of first and second half bits is same
// Function to print even length binary sequences
// whose sum of first and second half bits is same
// diff --> difference between sums of first n bits
// and last n bits
// out --> output array
// start --> starting index
// end --> ending index
function findAllSequences($diff, $out, $start, $end)
{
// We can't cover difference of more than n with 2n bits
if (abs($diff) > (int)(($end - $start + 1) / 2))
return;
// if all bits are filled
if ($start > $end)
{
// if sum of first n bits and last n bits are same
if ($diff == 0)
print(implode("",$out)." ");
return;
}
// fill first bit as 0 and last bit as 1
$out[$start] = '0';
$out[$end] = '1';
findAllSequences($diff + 1, $out, $start + 1, $end - 1);
// fill first and last bits as 1
$out[$start] = $out[$end] = '1';
findAllSequences($diff, $out, $start + 1, $end - 1);
// fill first and last bits as 0
$out[$start] = $out[$end] = '0';
findAllSequences($diff, $out, $start + 1, $end - 1);
// fill first bit as 1 and last bit as 0
$out[$start] = '1';
$out[$end] = '0';
findAllSequences($diff - 1, $out, $start + 1, $end - 1);
}
// Driver program
// input number
$n = 2;
// allocate string containing 2*n characters
$out=array_fill(0,2*$n,"");
findAllSequences(0, $out, 0, 2*$n - 1);
// This code is contributed by chandan_jnu
?>
JavaScript
<script>
// JavaScript program to print even length binary
// sequences whose sum of first and second
// half bits is same
// Function to print even length binary
// sequences whose sum of first and
// second half bits is same
// diff --> difference between sums of
// first n bits
// and last n bits
// out --> output array
// start --> starting index
// end --> ending index
function findAllSequences(diff, outt, start, end)
{
// We can't cover difference of
// more than n with 2n bits
if (Math.abs(diff) > parseInt((end - start + 1) / 2, 10))
return;
// if all bits are filled
if (start > end)
{
// if sum of first n bits and
// last n bits are same
if (diff == 0)
{
document.write(outt.join(""));
document.write(" ");
}
return;
}
// fill first bit as 0 and last bit
// as 1
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((4 ^ N )* 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++
// C++ program to implement the approach
#include <bits/stdc++.h>
using namespace std;
//function that generates the sequence
void generateSequencesWithSum(
int n, vector<vector<string> >& sumToString,
vector<string> sequence, int sumSoFar)
{
// Base case, if there are no more binary digits to
// include
if (n == 0) {
// add permutation to list of sequences with sum
// corresponding to index
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;
}
// Generate sequence +0
sequence.push_back("0");
generateSequencesWithSum(n - 1, sumToString, sequence,
sumSoFar);
sequence.erase(sequence.begin());
// Generate sequence +1
sequence.push_back("1");
generateSequencesWithSum(n - 1, sumToString, sequence,
sumSoFar + 1);
sequence.erase(sequence.begin());
}
// function to form permutations of the sequences
void permuteSequences(vector<vector<string> > sumToString)
{
// There are 2^n substring in this list of lists
for (int sumIndexArr = 0;
sumIndexArr < sumToString.size(); sumIndexArr++) {
// Append
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]
<< " ";
}
}
}
}
}
// function that finds all the subsequences
void findAllSequences(int n)
{
vector<vector<string> > sumToString;
for (int i = 0; i < n + 1; i++) {
sumToString.push_back(
vector<string>()); // list of strings
// where index
// represents sum
}
generateSequencesWithSum(n, sumToString,
vector<string>(), 0);
permuteSequences(sumToString);
}
// Driver Code
int main()
{
// Function Call
findAllSequences(2);
return 0;
}
// this code is contributed by phasing17
Java
// Java program to implement the approach
import java.util.*;
class GFG {
// function that finds all the subsequences
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>()); // list of strings
// where index
// represents sum
}
generateSequencesWithSum(
n, sumToString, new ArrayList<String>(), 0);
permuteSequences(sumToString);
}
static void generateSequencesWithSum(
int n, ArrayList<ArrayList<String> > sumToString,
ArrayList<String> sequence, int sumSoFar)
{
// Base case, if there are no more binary digits to
// include
if (n == 0) {
// add permutation to list of sequences with sum
// corresponding to index
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;
}
// Generate sequence +0
sequence.add("0");
generateSequencesWithSum(n - 1, sumToString,
sequence, sumSoFar);
sequence.remove(0);
// Generate sequence +1
sequence.add("1");
generateSequencesWithSum(n - 1, sumToString,
sequence, sumSoFar + 1);
sequence.remove(0);
}
// function to form permutations of the sequences
static void permuteSequences(
ArrayList<ArrayList<String> > sumToString)
{
// There are 2^n substring in this list of lists
for (int sumIndexArr = 0;
sumIndexArr < sumToString.size();
sumIndexArr++) {
// Append
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));
}
}
}
}
}
// Driver Code
public static void main(String[] args)
{
// Function Call
findAllSequences(2);
}
// this code is contributed by phasing17
}
Python3
def findAllSequences(n):
sumToString = [[] for x in range(n+1)] # list of strings where index represents sum
generateSequencesWithSum(n, sumToString, [], 0)
permuteSequences(sumToString)
def generateSequencesWithSum(n, sumToString, sequence, sumSoFar):
#Base case, if there are no more binary digits to include
if n == 0:
sumToString[sumSoFar].append("".join(sequence)) #add permutation to list of sequences with sum corresponding to index
return
#Generate sequence +0
sequence.append("0")
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar)
sequence.pop()
#Generate sequence +1
sequence.append("1")
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar+1)
sequence.pop()
def permuteSequences(sumToString):
#There are 2^n substring in this list of lists
for sumIndexArr in sumToString:
# Append
for sequence1 in sumIndexArr:
for sequence2 in sumIndexArr:
print(sequence1 + sequence2)
findAllSequences(2)
#Contribution by Xavier Jean Baptiste
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>()); // list of strings where index represents sum
}
generateSequencesWithSum(n, sumToString, new List<string>(), 0);
permuteSequences(sumToString);
}
static void generateSequencesWithSum(int n, List<List<string>> sumToString, List<string> sequence, int sumSoFar)
{
// Base case, if there are no more binary digits to include
if(n == 0)
{
//add permutation to list of sequences with sum corresponding to index
string seq = "";
for(int i = 0; i < sequence.Count; i++)
{
seq = seq + sequence[i];
}
sumToString[sumSoFar].Add(seq);
return;
}
// Generate sequence +0
sequence.Add("0");
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar);
sequence.RemoveAt(0);
// Generate sequence +1
sequence.Add("1");
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar+1);
sequence.RemoveAt(0);
}
static void permuteSequences(List<List<string>> sumToString)
{
// There are 2^n substring in this list of lists
for(int sumIndexArr = 0; sumIndexArr < sumToString.Count; sumIndexArr++)
{
// Append
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);
}
}
// This code is contributed by divyesh072019.
JavaScript
<script>
function findAllSequences(n)
{
let sumToString = [];
for(let i = 0; i < n + 1; i++)
{
sumToString.push([]); // list of strings where index represents sum
}
generateSequencesWithSum(n, sumToString, [], 0);
permuteSequences(sumToString);
}
function generateSequencesWithSum(n, sumToString, sequence, sumSoFar)
{
// Base case, if there are no more binary digits to include
if(n == 0)
{
//add permutation to list of sequences with sum corresponding to index
sumToString[sumSoFar].push(sequence.join(""));
return;
}
// Generate sequence +0
sequence.push("0");
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar);
sequence.shift();
// Generate sequence +1
sequence.push("1");
generateSequencesWithSum(n-1, sumToString, sequence, sumSoFar+1);
sequence.shift();
}
function permuteSequences(sumToString)
{
// There are 2^n substring in this list of lists
for(let sumIndexArr = 0; sumIndexArr < sumToString.length; sumIndexArr++)
{
// Append
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);
// This code is contributed by decode2207.
</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: Key -> sum of bits; Value -> All possible permutation with respective sum
map<int, vector<string>> mp;
// first N-half bits
vector<FirstHalf> firstHalf;
// function to find sum of the bits from a String
int sumOfString(string s) {
int sum = 0;
// ex: converts "1" to 1 -> (ASCII('1') - ASCII('0') = 1)
for(auto c: s) {
sum += (c - '0');
}
return sum;
}
void perm(string p, char* bin, int level, int n)
{
// p: processed string(processed permutation at current level)
// bin: {'0', '1'}
// l: current level of recursion tree (leaf/solution level = 0)
// n: total levels
if(level == 0)
{
// at solution level find sum of the current permutation
int sum = sumOfString(p);
// store current permutation to firstHalf list
firstHalf.push_back(FirstHalf(p, sum));
// put current permutation to its respective sum value
mp[sum].push_back(p);
return;
}
// generate calls for permutation
// working: first solution with all 0s,
// then replacing last 0 with 1 and so on...
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)
{
// for each firstHalf string
// find sum of the bits of current string
int sum = first.sum;
// retrieve respective secondHalf from map based on sum key
vector<string> secondHalf = mp[sum];
for(auto second: secondHalf)
{
// append first and second half and print
cout << first.data + second << " ";
// after every 6 solution line is changed in output
// only for formatting below lines could be removed
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;
}
// This code is contributed by Nidhi goel.
Java
import java.util.*;
class GFG {
static class FirstHalf {
String data;
int sum;
FirstHalf(String data, int sum) {
this.data = data;
this.sum = sum;
}
}
//MAP: Key -> sum of bits; Value -> All possible permutation with respective sum
static Map<Integer, ArrayList<String>> map = new HashMap<>();
//first N-half bits
static List<FirstHalf> firstHalf = new ArrayList<>();
//function to find sum of the bits from a String
public static int sumOfString(String s) {
int sum = 0;
//ex: converts "1" to 1 -> (ASCII('1') - ASCII('0') = 1)
for(char c: s.toCharArray()) {
sum += c - '0';
}
return sum;
}
public static void perm(String p, char[] bin, int level, int n) {
//p: processed string(processed permutation at current level)
//bin: {'0', '1'}
//l: current level of recursion tree (leaf/solution level = 0)
//n: total levels
if(level == 0) {
//at solution level find sum of the current permutation
int sum = sumOfString(p);
//store current permutation to firstHalf list
firstHalf.add(new FirstHalf(p, sum));
//put current permutation to its respective sum value
map.putIfAbsent(sum, new ArrayList<String>());
map.get(sum).add(p);
return;
}
//generate calls for permutation
//working: first solution with all 0s, then replacing last 0 with 1 and so on...
for(char c: bin) {
perm(p+c, bin, level-1, n);
}
}
public static void result() {
int i = 0;
for(FirstHalf first: firstHalf) {
//for each firstHalf string
//find sum of the bits of current string
int sum = first.sum;
//retrieve respective secondHalf from map based on sum key
ArrayList<String> secondHalf = map.get(sum);
for(String second: secondHalf) {
//append first and second half and print
System.out.print(first.data+second+" ");
//after every 6 solution line is changed in output
//only for formatting below lines could be removed
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();
}
}
//Code contributed by Animesh Singh
Python3
# Python code implementation
class FirstHalf:
def __init__(self, data, sum):
self.data = data
self.sum = sum
# MAP: Key -> sum of bits; Value -> All possible permutation with respective sum
map = {}
# first N-half bits
firstHalf = []
# function to find sum of the bits from a String
def sumOfString(s):
sum = 0
# ex: converts "1" to 1 -> (ASCII('1') - ASCII('0') = 1)
for i in range(len(s)):
sum += ord(s[i]) - ord('0')
return sum
def perm(p, bin, level, n):
# p: processed string(processed permutation at current level)
# bin: ['0', '1']
# l: current level of recursion tree (leaf/solution level = 0)
# n: total levels
if level == 0:
# at solution level find sum of the current permutation
sum = sumOfString(p)
# store current permutation to firstHalf list
firstHalf.append(FirstHalf(p, sum))
# put current permutation to its respective sum value
if sum not in map:
map[sum] = []
map[sum].append(p)
return
# generate calls for permutation
# working: first solution with all 0s, then replacing last 0 with 1 and so on...
for i in range(len(bin)):
perm(p+bin[i], bin, level-1, n)
def result():
i = 0
for j in range(len(firstHalf)):
# for each firstHalf string
# find sum of the bits of current string
sum = firstHalf[j].sum
# retrieve respective secondHalf from map based on sum key
secondHalf = map[sum]
for k in range(len(secondHalf)):
# append first and second half and print
print(firstHalf[j].data + secondHalf[k] + " ", end="")
# after every 6 solution line is changed in output
# only for formatting below lines could be removed
i = i + 1
if(i % 6 == 0):
print('\n')
up = ['0', '1']
n = 2
perm("", up, n, n)
result()
# The code is contributed by Nidhi goel.
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
{
// MAP: Key -> sum of bits; Value -> All possible permutation with respective sum
static Dictionary<int, List<string>> mp = new Dictionary<int, List<string>>();
// first N-half bits
static List<FirstHalf> firstHalf = new List<FirstHalf>();
// function to find sum of the bits from a String
static int sumOfString(string s) {
int sum = 0;
// ex: converts "1" to 1 -> (ASCII('1') - ASCII('0') = 1)
foreach (char c in s) {
sum += (c - '0');
}
return sum;
}
static void perm(string p, char[] bin, int level, int n) {
// p: processed string(processed permutation at current level)
// bin: {'0', '1'}
// l: current level of recursion tree (leaf/solution level = 0)
// n: total levels
if (level == 0) {
// at solution level find sum of the current permutation
int sum = sumOfString(p);
// store current permutation to firstHalf list
firstHalf.Add(new FirstHalf(p, sum));
// put current permutation to its respective sum value
if (mp.ContainsKey(sum)) {
mp[sum].Add(p);
} else {
mp.Add(sum, new List<string> { p });
}
return;
}
// generate calls for permutation
// working: first solution with all 0s,
// then replacing last 0 with 1 and so on...
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) {
// for each firstHalf string
// find sum of the bits of current string
int sum = first.sum;
// retrieve respective secondHalf from map based on sum key
List<string> secondHalf = mp[sum];
foreach (string second in secondHalf) {
// append first and second half and print
Console.Write(first.data + second + " ");
// after every 6 solution line is changed in output
// only for formatting below lines could be removed
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;
}
}
// MAP: Key -> sum of bits; Value -> All possible permutation with respective sum
const map = new Map();
// first N-half bits
const firstHalf = [];
// function to find sum of the bits from a String
function sumOfString(s) {
let sum = 0;
//ex: converts "1" to 1 -> (ASCII('1') - ASCII('0') = 1)
for(let i = 0; i < s.length; i++) {
sum += s.charCodeAt(i) - '0'.charCodeAt(0);
}
return sum;
}
function perm(p, bin, level, n)
{
// p: processed string(processed permutation at current level)
// bin: ['0', '1']
// l: current level of recursion tree (leaf/solution level = 0)
// n: total levels
if(level == 0)
{
// at solution level find sum of the current permutation
let sum = sumOfString(p);
// store current permutation to firstHalf list
firstHalf.push(new FirstHalf(p, sum));
// put current permutation to its respective sum value
if(!map.has(sum)) map.set(sum, []);
map.get(sum).push(p);
return;
}
// generate calls for permutation
// working: first solution with all 0s, then replacing last 0 with 1 and so on...
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++)
{
// for each firstHalf string
// find sum of the bits of current string
let sum = firstHalf[j].sum;
// retrieve respective secondHalf from map based on sum key
let secondHalf = map.get(sum);
for(let k = 0; k < secondHalf.length; k++)
{
// append first and second half and print
process.stdout.write(firstHalf[j].data + secondHalf[k] + " ");
// after every 6 solution line is changed in output
// only for formatting below lines could be removed
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
Similar Reads
Basics & Prerequisites
Data Structures
Getting Started with Array Data StructureArray is a collection of items of the same variable type that are stored at contiguous memory locations. It is one of the most popular and simple data structures used in programming. Basic terminologies of ArrayArray Index: In an array, elements are identified by their indexes. Array index starts fr
14 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem