Given two integers N and K, the task is to find the number of binary strings of length N having an even number of 1’s out of which less than K are consecutive.
Examples:
Input: N = 4, K = 2
Output: 4
Explanation:
The possible binary strings are 0000, 0101, 1001, 1010. They all have even number of 1’s with less than 2 of them occurring consecutively.
Input: N = 3, K = 2
Output: 2
Explanation:
The possible binary strings are 000, 101. All other strings that is 001, 010, 011, 100, 110, 111 does not meet the criteria.
Approach:
This problem can be solved by Dynamic Programming.
Let us consider a 3D table dp[][][] to store the solution of each subproblem, such that, dp[n][i][s] denotes the number of binary strings of length n having i consecutive 1’s and sum of 1’s = s. As it is only required to check whether the total number of 1’s is even or not we store s % 2. So, dp[n][i][s] can be calculated as follows:
- If we place 0 at the nth position, the number of 1’s remain unchanged. Hence, dp[n][i][s] = dp[n – 1][0][s].
- If we place 1 at the nth position, dp[n][i][s] = dp[n – 1][i + 1][(s + 1) % 2] .
- From the above two points the recurrence relation formed is given by:
![Rendered by QuickLaTeX.com dp[n][i][s] = dp[n-1][0][s] + dp[n - 1][i + 1][(s + 1)mod 2]](https://www.geeksforgeeks.org/wp-content/ql-cache/quicklatex.com-8d64d404a7dc1d74596c6bf12bd0bd59_l3.png)
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[100001][20][2];
int possibleBinaries( int pos,
int ones,
int sum,
int k)
{
if (ones == k)
return 0;
if (pos == 0)
return (sum == 0) ? 1 : 0;
if (dp[pos][ones][sum] != -1)
return dp[pos][ones][sum];
int ret = possibleBinaries(pos - 1,
ones + 1,
(sum + 1) % 2,
k)
+ possibleBinaries(pos - 1, 0,
sum, k);
dp[pos][ones][sum] = ret;
return dp[pos][ones][sum];
}
int main()
{
int N = 3;
int K = 2;
memset (dp, -1, sizeof dp);
cout << possibleBinaries(N, 0, 0, K);
}
|
Java
import java.io.*;
class GFG{
static int [][][]dp = new int [ 100001 ][ 20 ][ 2 ];
static int possibleBinaries( int pos, int ones,
int sum, int k)
{
if (ones == k)
return 0 ;
if (pos == 0 )
return (sum == 0 ) ? 1 : 0 ;
if (dp[pos][ones][sum] != - 1 )
return dp[pos][ones][sum];
int ret = possibleBinaries(pos - 1 ,
ones + 1 ,
(sum + 1 ) % 2 , k) +
possibleBinaries(pos - 1 , 0 ,
sum, k);
dp[pos][ones][sum] = ret;
return dp[pos][ones][sum];
}
public static void main(String[] args)
{
int N = 3 ;
int K = 2 ;
for ( int i = 0 ; i < 100001 ; i++)
{
for ( int j = 0 ; j < 20 ; j++)
{
for ( int l = 0 ; l < 2 ; l++)
dp[i][j][l] = - 1 ;
}
}
System.out.print(possibleBinaries(N, 0 , 0 , K));
}
}
|
Python3
import numpy as np
dp = np.ones((( 100002 , 21 , 3 )))
dp = - 1 * dp
def possibleBinaries(pos, ones, sum , k):
if (ones = = k):
return 0
if (pos = = 0 ):
return 1 if ( sum = = 0 ) else 0
if (dp[pos][ones][ sum ] ! = - 1 ):
return dp[pos][ones][ sum ]
ret = (possibleBinaries(pos - 1 ,
ones + 1 ,
( sum + 1 ) % 2 , k) +
possibleBinaries(pos - 1 , 0 , sum , k))
dp[pos][ones][ sum ] = ret
return dp[pos][ones][ sum ]
N = 3
K = 2
print ( int (possibleBinaries(N, 0 , 0 , K)))
|
C#
using System;
class GFG{
static int [,,]dp = new int [100001, 20, 2];
static int possibleBinaries( int pos, int ones,
int sum, int k)
{
if (ones == k)
return 0;
if (pos == 0)
return (sum == 0) ? 1 : 0;
if (dp[pos, ones, sum] != -1)
return dp[pos, ones, sum];
int ret = possibleBinaries(pos - 1,
ones + 1,
(sum + 1) % 2, k) +
possibleBinaries(pos - 1, 0,
sum, k);
dp[pos, ones, sum] = ret;
return dp[pos, ones, sum];
}
public static void Main(String[] args)
{
int N = 3;
int K = 2;
for ( int i = 0; i < 100001; i++)
{
for ( int j = 0; j < 20; j++)
{
for ( int l = 0; l < 2; l++)
dp[i, j, l] = -1;
}
}
Console.Write(possibleBinaries(N, 0, 0, K));
}
}
|
Javascript
<script>
let dp = new Array(100001).fill(-1).map((t) => new Array(20).fill(-1).map((r) => new Array(2).fill(-1)));
function possibleBinaries(pos, ones, sum, k)
{
if (ones == k)
return 0;
if (pos == 0)
return (sum == 0) ? 1 : 0;
if (dp[pos][ones][sum] != -1)
return dp[pos][ones][sum];
let ret = possibleBinaries(pos - 1,
ones + 1,
(sum + 1) % 2,
k)
+ possibleBinaries(pos - 1, 0,
sum, k);
dp[pos][ones][sum] = ret;
return dp[pos][ones][sum];
}
let N = 3;
let K = 2;
document.write(possibleBinaries(N, 0, 0, K));
</script>
|
Time Complexity: O(2*N*K), where N and K represents the given two integers.
Auxiliary Space: O(100001*20*2), no any other extra space is required, so it is a constant.
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a 3D DP table to store the solution of the subproblems.
- Initialize the DP with base cases
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
- Return the final solution stored in dp[N][0][0].
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int possibleBinaries( int N, int K) {
int dp[N+1][K+1][2];
memset (dp, 0, sizeof (dp));
for ( int i=0; i<=K; i++) {
dp[1][i][0] = 1;
dp[1][i][1] = 1;
}
for ( int i=2; i<=N; i++) {
for ( int j=0; j<=K; j++) {
for ( int k=0; k<=1; k++) {
if (j == K) {
dp[i][j][k] = 0;
} else if (k == 0) {
dp[i][j][k] = dp[i-1][j+1][1];
} else {
dp[i][j][k] = dp[i-1][j+1][0] + dp[i-1][j][1];
}
}
}
}
return dp[N][0][0];
}
int main() {
int N = 3;
int K = 2;
cout << possibleBinaries(N, K);
}
|
Java
import java.util.Arrays;
public class PossibleBinaries {
static int possibleBinaries( int N, int K) {
int [][][] dp = new int [N+ 1 ][K+ 1 ][ 2 ];
for ( int i= 0 ; i<=N; i++) {
for ( int j= 0 ; j<=K; j++) {
Arrays.fill(dp[i][j], 0 );
}
}
for ( int i= 0 ; i<=K; i++) {
dp[ 1 ][i][ 0 ] = 1 ;
dp[ 1 ][i][ 1 ] = 1 ;
}
for ( int i= 2 ; i<=N; i++) {
for ( int j= 0 ; j<=K; j++) {
for ( int k= 0 ; k<= 1 ; k++) {
if (j == K) {
dp[i][j][k] = 0 ;
} else if (k == 0 ) {
dp[i][j][k] = dp[i- 1 ][j+ 1 ][ 1 ];
} else {
dp[i][j][k] = dp[i- 1 ][j+ 1 ][ 0 ] + dp[i- 1 ][j][ 1 ];
}
}
}
}
return dp[N][ 0 ][ 0 ];
}
public static void main(String[] args) {
int N = 3 ;
int K = 2 ;
System.out.println(possibleBinaries(N, K));
}
}
|
Python3
def possibleBinaries(N, K):
dp = [[[ 0 for _ in range ( 2 )] for _ in range (K + 1 )] for _ in range (N + 1 )]
for i in range (K + 1 ):
dp[ 1 ][i][ 0 ] = 1
dp[ 1 ][i][ 1 ] = 1
for i in range ( 2 , N + 1 ):
for j in range (K + 1 ):
for k in range ( 2 ):
if j = = K:
dp[i][j][k] = 0
elif k = = 0 :
dp[i][j][k] = dp[i - 1 ][j + 1 ][ 1 ]
else :
dp[i][j][k] = dp[i - 1 ][j + 1 ][ 0 ] + dp[i - 1 ][j][ 1 ]
return dp[N][ 0 ][ 0 ]
N = 3
K = 2
print (possibleBinaries(N, K))
|
C#
using System;
public class Program {
public static int PossibleBinaries( int N, int K) {
int [,,] dp = new int [N+1, K+1, 2];
for ( int i=0; i<=K; i++) {
dp[1, i, 0] = 1;
dp[1, i, 1] = 1;
}
for ( int i=2; i<=N; i++) {
for ( int j=0; j<=K; j++) {
for ( int k=0; k<=1; k++) {
if (j == K) {
dp[i, j, k] = 0;
} else if (k == 0) {
dp[i, j, k] = dp[i-1, j+1, 1];
} else {
dp[i, j, k] = dp[i-1, j+1, 0] + dp[i-1, j, 1];
}
}
}
}
return dp[N, 0, 0];
}
public static void Main() {
int N = 3;
int K = 2;
Console.WriteLine(PossibleBinaries(N, K));
}
}
|
Javascript
function possibleBinaries(N, K) {
var dp = new Array(N+1);
for ( var i = 0; i < dp.length; i++) {
dp[i] = new Array(K+1);
for ( var j = 0; j < dp[i].length; j++) {
dp[i][j] = new Array(2);
for ( var k = 0; k < dp[i][j].length; k++) {
dp[i][j][k] = 0;
}
}
}
for ( var i = 0; i < K+1; i++) {
dp[1][i][0] = 1;
dp[1][i][1] = 1;
}
for ( var i = 2; i < N+1; i++) {
for ( var j = 0; j < K+1; j++) {
for ( var k = 0; k < 2; k++) {
if (j == K) {
dp[i][j][k] = 0;
} else if (k == 0) {
dp[i][j][k] = dp[i-1][j+1][1];
} else {
dp[i][j][k] = dp[i-1][j+1][0] + dp[i-1][j][1];
}
}
}
}
return dp[N][0][0];
}
var N = 3;
var K = 2;
console.log(possibleBinaries(N, K));
|
Time Complexity : O(N*K*2)
Auxiliary Space : O(N*K*2)