Given a positive integer N, count all possible distinct binary strings of length N such that there are no consecutive 1’s.
Examples:
Input: N = 2
Output: 3
// The 3 strings are 00, 01, 10
Input: N = 3
Output: 5
// The 5 strings are 000, 001, 010, 100, 101
This problem can be solved using Dynamic Programming. Let a[i] be the number of binary strings of length i which do not contain any two consecutive 1’s and which end in 0. Similarly, let b[i] be the number of such strings which end in 1. We can append either 0 or 1 to a string ending in 0, but we can only append 0 to a string ending in 1. This yields the recurrence relation:
a[i] = a[i - 1] + b[i - 1]
b[i] = a[i - 1]
The base cases of above recurrence are a[1] = b[1] = 1. The total number of strings of length i is just a[i] + b[i].
Following is the implementation of above solution. In the following implementation, indexes start from 0. So a[i] represents the number of binary strings for input length i+1. Similarly, b[i] represents binary strings for input length i+1.
Implementation:
C++
#include <iostream>
using namespace std;
int countStrings( int n)
{
int a[n], b[n];
a[0] = b[0] = 1;
for ( int i = 1; i < n; i++)
{
a[i] = a[i-1] + b[i-1];
b[i] = a[i-1];
}
return (a[n-1] + b[n-1])%1000000007;
}
int main()
{
cout << countStrings(3) << endl;
return 0;
}
|
Java
import java.io.*;
class Subset_sum
{
static int countStrings( int n)
{
int a[] = new int [n];
int b[] = new int [n];
a[ 0 ] = b[ 0 ] = 1 ;
for ( int i = 1 ; i < n; i++)
{
a[i] = a[i- 1 ] + b[i- 1 ];
b[i] = a[i- 1 ];
}
return (a[n- 1 ] + b[n- 1 ])% 1000000007 ;
}
public static void main (String args[])
{
System.out.println(countStrings( 3 ));
}
}
|
Python3
def countStrings(n):
a = [ 0 for i in range (n)]
b = [ 0 for i in range (n)]
a[ 0 ] = b[ 0 ] = 1
for i in range ( 1 ,n):
a[i] = a[i - 1 ] + b[i - 1 ]
b[i] = a[i - 1 ]
return a[n - 1 ] + b[n - 1 ]
print (countStrings( 3 ))
|
C#
using System;
class Subset_sum
{
static int countStrings( int n)
{
int []a = new int [n];
int []b = new int [n];
a[0] = b[0] = 1;
for ( int i = 1; i < n; i++)
{
a[i] = a[i-1] + b[i-1];
b[i] = a[i-1];
}
return (a[n-1] + b[n-1])%1000000007;
}
public static void Main ()
{
Console.Write(countStrings(3));
}
}
|
Javascript
<script>
function countStrings(n)
{
let a = [];
let b = [];
a[0] = b[0] = 1;
for (let i = 1; i < n; i++)
{
a[i] = a[i - 1] + b[i - 1];
b[i] = a[i - 1];
}
return (a[n-1] + b[n-1])%1000000007;
}
document.write(countStrings(3));
</script>
|
PHP
<?php
function countStrings( $n )
{
$a [ $n ] = 0;
$b [ $n ] = 0;
$a [0] = $b [0] = 1;
for ( $i = 1; $i < $n ; $i ++)
{
$a [ $i ] = $a [ $i - 1] +
$b [ $i - 1];
$b [ $i ] = $a [ $i - 1];
}
return ( $a [ $n - 1] +
$b [ $n - 1])%1000000007;
}
echo countStrings(3) ;
?>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Source:
If we take a closer look at the pattern, we can observe that the count is actually (n+2)’th Fibonacci number for n >= 1. The Fibonacci Numbers are 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 141, ….
n = 1, count = 2 = fib(3)
n = 2, count = 3 = fib(4)
n = 3, count = 5 = fib(5)
n = 4, count = 8 = fib(6)
n = 5, count = 13 = fib(7)
................
Therefore we can count the strings in O(Log n) time also using the method 5 here.
Another method :-
From the above method it is clear that we only want just previous value in the for loop which we can also do by replacing the array with the variable.
Below is the implementation of the above approach:-
C++
#include <bits/stdc++.h>
using namespace std;
int countStrings( int n)
{
int a = 1, b = 1;
for ( int i = 1; i < n; i++) {
int temp = a + b;
b = a;
a = temp;
}
return (a + b)%1000000007;
}
int main()
{
cout << countStrings(3) << endl;
return 0;
}
|
Java
import java.io.*;
class Subset_sum {
static int countStrings( int n)
{
int a = 1 ;
int b = 1 ;
for ( int i = 1 ; i < n; i++) {
int temp = a + b;
b = a;
a = temp;
}
return (a + b)% 1000000007 ;
}
public static void main(String args[])
{
System.out.println(countStrings( 3 ));
}
}
|
Python3
class Subset_sum :
@staticmethod
def countStrings( n) :
a = 1
b = 1
i = 1
while (i < n) :
temp = a + b
b = a
a = temp
i + = 1
return (a + b) % 1000000007
@staticmethod
def main( args) :
print (Subset_sum.countStrings( 3 ))
if __name__ = = "__main__" :
Subset_sum.main([])
|
C#
using System;
public class Subset_sum
{
public static int countStrings( int n)
{
var a = 1;
var b = 1;
for ( int i = 1; i < n; i++)
{
var temp = a + b;
b = a;
a = temp;
}
return (a + b)%1000000007;
}
public static void Main(String[] args)
{
Console.WriteLine(Subset_sum.countStrings(3));
}
}
|
Javascript
function countStrings(n){
var a = 1;
var b = 1;
for (let i=1;i<n;i++){
var temp = a + b;
b = a;
a = temp;
}
return (a + b)%1000000007;
}
console.log(countStrings(3));
|
Time Complexity: O(N)
Auxiliary Space: O(1)
Related Post :
1 to n bit numbers with no consecutive 1s in binary representation.
Another Useful Approach:-
Fibonacci in Log (n) without using Matrix Exponentiation
As for calculating the n we can express it as the product of n/2 and n/2 ((n/2+1) for n is odd) as they are independent ,now as there are the cases when we combining these two half values to get full length there may be occurrence of consecutive 1’s at the joining. So we have to subtract those cases to get the final result.
f(n)=f(n/2)*f(n/2) - (those values which has consecutive 1's at the joining part)
To find the values of consecutive 1’s at the intersection
As moving from n to n+1 ,the difference between them is the only value which have 0’s at the end as 0 values only double the values . And 0’s values at the end will only give two results as 0 and 1 because if last element is 1 then we can’t get 1 after it as then they become two consecutive.
So,
f(n)-f(n-1) = 0's value at the last position of f(n-1) = 1's value at the last position of f(n)
Finally ,
If n is even:
f(n)=f(n/2)*f(n/2) - (f(n/2)-f(n/2-1))(f(n/2)-f(n/2-1))
If n is odd:
f(n)=f(n/2)*f(n/2+1) - (f(n/2)-f(n/2-1))(f(n/2+1)-f(n/2))
And we will store pre-calculated value using map.
C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public :
map< long long int , long long int >mp;
int countStrings( long long int N) {
if (N==0) return 1;
if (N==1) return 2;
if (N==2) return 3;
long long int mod=1e9+7;
long long int a=mp[N/2-1]=((mp[N/2-1])?mp[N/2-1]:countStrings(N/2-1))%mod,b=mp[N/2]=((mp[N/2])?mp[N/2]:countStrings(N/2))%mod,c=mp[N/2+1]=((mp[N/2+1])?mp[N/2+1]:countStrings(N/2+1))%mod;
if (N%2)
return mp[N]=((b*c%mod)-((c-b)*(b-a)%mod)+mod)%mod;
return mp[N]=((b*b%mod)-((b-a)*(b-a)%mod)+mod)%mod;
}
};
int main() {
int t;
cin >> t;
while (t--) {
long long int N;
cin >> N;
Solution obj;
cout << obj.countStrings(N) << endl;
}
}
|
Java
import java.util.*;
class Solution {
Map<Long, Long> mp = new HashMap<>();
long countStrings( long N) {
if (N == 0 ) return 1 ;
if (N == 1 ) return 2 ;
if (N == 2 ) return 3 ;
long mod = ( long )1e9 + 7 ;
if (mp.containsKey(N)) {
return mp.get(N);
}
long a = mp.getOrDefault(N/ 2 - 1 , countStrings(N/ 2 - 1 )) % mod;
long b = mp.getOrDefault(N/ 2 , countStrings(N/ 2 )) % mod;
long c = mp.getOrDefault(N/ 2 + 1 , countStrings(N/ 2 + 1 )) % mod;
long result;
if (N % 2 == 1 )
result = ((b * c % mod) - ((c - b) * (b - a) % mod) + mod) % mod;
else
result = ((b * b % mod) - ((b - a) * (b - a) % mod) + mod) % mod;
mp.put(N, result);
return result;
}
}
public class Main {
public static void main(String[] args) {
long N = 10 ;
Solution obj = new Solution();
System.out.println(obj.countStrings(N));
}
}
|
Python3
class Solution:
def __init__( self ):
self .mp = {}
def countStrings( self , N):
if N = = 0 :
return 1
if N = = 1 :
return 2
if N = = 2 :
return 3
mod = 10 * * 9 + 7
a = self .mp.get(N / / 2 - 1 , self .countStrings(N / / 2 - 1 )) % mod
b = self .mp.get(N / / 2 , self .countStrings(N / / 2 )) % mod
c = self .mp.get(N / / 2 + 1 , self .countStrings(N / / 2 + 1 )) % mod
if N % 2 :
return (b * c - (c - b) * (b - a) + mod) % mod
return (b * b - (b - a) * (b - a) + mod) % mod
t = 1
while t > 0 :
N = 10
obj = Solution()
print (obj.countStrings(N))
t - = 1
|
C#
using System;
using System.Collections.Generic;
class Solution {
static Dictionary< long , long > mp = new Dictionary< long , long >();
public static long countStrings( long N) {
if (N == 0) return 1;
if (N == 1) return 2;
if (N == 2) return 3;
long mod = ( long )1e9 + 7;
long a = mp.ContainsKey(N / 2 - 1) ? mp[N / 2 - 1] : countStrings(N / 2 - 1);
long b = mp.ContainsKey(N / 2) ? mp[N / 2] : countStrings(N / 2);
long c = mp.ContainsKey(N / 2 + 1) ? mp[N / 2 + 1] : countStrings(N / 2 + 1);
if (N % 2 == 1) {
return mp[N] = ((b * c % mod) - ((c - b) * (b - a) % mod) + mod) % mod;
} else {
return mp[N] = ((b * b % mod) - ((b - a) * (b - a) % mod) + mod) % mod;
}
}
}
class Program {
static void Main( string [] args) {
long N = 10;
Console.WriteLine(Solution.countStrings(N));
}
}
|
Javascript
class Solution {
constructor() {
this .mp = new Map();
}
countStrings(N) {
if (N === 0n) return 1n;
if (N === 1n) return 2n;
if (N === 2n) return 3n;
const mod = 1000000007n;
if ( this .mp.has(N)) {
return this .mp.get(N);
}
const a = this .mp.has(N / 2n - 1n) ? this .mp.get(N / 2n - 1n) : this .countStrings(N / 2n - 1n);
const b = this .mp.has(N / 2n) ? this .mp.get(N / 2n) : this .countStrings(N / 2n);
const c = this .mp.has(N / 2n + 1n) ? this .mp.get(N / 2n + 1n) : this .countStrings(N / 2n + 1n);
let result;
if (N % 2n === 1n)
result = ((b * c % mod) - ((c - b) * (b - a) % mod) + mod) % mod;
else
result = ((b * b % mod) - ((b - a) * (b - a) % mod) + mod) % mod;
this .mp.set(N, result);
return result;
}
}
const N = 10n;
const obj = new Solution();
console.log(obj.countStrings(N).toString());
|
Time Complexity: O(log N)
Auxiliary Space : O(log N)
For n=10 , the output is 144.
We can calculate Fibonacci in log(n) using above result .