Open In App

Count number of binary strings without consecutive 1's

Last Updated : 16 Dec, 2024
Comments
Improve
Suggest changes
64 Likes
Like
Report

Given a positive integer n, the task is to count all possible distinct binary strings of length n such that there are no consecutive 1's.

Examples: 

Input: n = 3
Output: 5
Explanation: 5 strings are ("000", "001", "010", "100", "101").

Input: n = 2
Output: 3
Explanation: 3 strings are ("00", "01", "10").

Using Recursion - O(2^n) Time and O(n) Space

The idea is to explore two possible choices at each step of building the binary string. When constructing a string of length n, at each index, we have two choices: either place a 0 or place a 1. If we choose to place a 0, we can proceed to the next index. However, if we choose to place a 1, we must ensure that the next index does not contain a 1, so we skip the next index.

Mathematically the recurrence relation will look like the following:

countStrings(i) = countStrings(i+1) + countStrings(i+2)

Base Case:

  • countStrings(i) = 1, if i >= n.
C++
Java Python C# JavaScript

Output
5

Using Top-Down DP (Memoization) - O(n) Time and O(n) Space

If we notice carefully, we can observe that the above recursive solution holds the following two properties of Dynamic Programming:

1. Optimal Substructure: Number of ways to make binary string at i'th index depends on the optimal solutions of countStrings(i+1) and countStrings(i+2). By combining these substructures, we can efficiently calculate number of ways to make binary strings with consecutive 1's at index i.

2. Overlapping Subproblems: While applying a recursive approach in this problem, we notice that certain subproblems are computed multiple times. For example, while calculating countStrings(3), countStrings(4) and countStrings(5) are called. countStrings(4) will again call countStrings(5) which will lead to Overlapping Subproblems.

  • There is only one parameter: i that changes in the recursive solution. So we create a 1D array of size n for memoization.
  • We initialize this array as -1 to indicate nothing is computed initially.
  • Now we modify our recursive solution to first check if the value is -1, then only make recursive calls. This way, we avoid re-computations of the same subproblems.
C++
Java Python C# JavaScript

Output
5

Using Bottom-Up DP (Tabulation) - O(n) Time and O(n) Space

The idea is to fill the DP table based on next values. For each index, we can either place 1 or 0. The array is filled in an iterative manner from i = n-1 to i = 0.

The dynamic programming relation is as follows: 

  • dp[i] = dp[i+1] + dp[i+2]
C++
Java Python C# JavaScript

Output
5

Using Space Optimized DP - O(n) Time and O(1) Space

In previous approach of dynamic programming we have derive the relation between states as given below:

  • dp[i] = dp[i+1] + dp[i+2]

We observe that for calculating dp[i] state we only need dp[i+1] and dp[i+2]. There is no need to store all the next states.

C++
Java Python C# JavaScript

Output
5

Using Matrix Exponentiation - O(logn) Time and O(logn) Space

The recurrence relation to count binary strings of length i is:

  • F(i) = F(i-1) + F(i-2)

with bases cases F(1) = 2 and F(2) = 3.

Matrix exponentiation can be used to solve this problem in O(logn) time. Refer to Matrix Exponentiation for detailed approach.

C++
Java Python C# JavaScript

Output
5

Related article: 


Next Article

Similar Reads