Open In App

Count strings with consecutive 1's

Last Updated : 09 Jul, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an integer n, find the count the number of binary strings of length n that contain at least one pair of consecutive 1's. A binary string is a sequence made up of only 0's and 1's.

Examples:

Input: n = 2
Output: 1
Explanation: The 4 strings of length 2 are: 00, 01, 10, 11. Only 11 has consecutive 1's.

Input: n = 3
Output: 3
Explanation: The 8 strings of length 3 are: 000, 001, 010, 011, 100, 101, 110, 111. Strings with consecutive 1's are: 011, 110, and 111.

[Naive Approach] Using Recursion - O(2n) Time and O(n) Space

The idea is to simulate the generation of all binary strings of length n using recursion while tracking the previous bit.
Whenever we place two consecutive 1s, we know all further completions will also contain such a pair — so we directly add 2^(remaining length) instead of continuing the recursion. This helps us avoid expanding unnecessary branches.

C++
#include <iostream>
#include <vector>
using namespace std;

// Recursive helper to count numbers with 
// at least one pair of consecutive 1s
int solve(int i, int prev, int n) {
    if (i > n) return 0;

    int res = 0;

    if (prev == 0) {
        // Try placing 1 or 0 at the current position
        res = solve(i + 1, 1, n) + 
               solve(i + 1, 0, n);
    } 
    else{
        // try placing 0 after a 1
        res = solve(i + 1, 0, n);
        // try placing 1: now remaining positions can be anything
        // atleast 1 time consecutive '1' is found
        res = res + (1 << (n-i));
    }

    return res;
}

int countConsec(int n) {
    return solve(1, 0, n );
}

int main() {
    int n = 3;
    cout << countConsec(n) << endl;
    return 0;
}
Java
class GfG {
    // Recursive helper to count numbers with 
    // at least one pair of consecutive 1s
    static int solve(int i, int prev, int n) {
        if (i > n) return 0;

        int res = 0;

        if (prev == 0) {
            // Try placing 1 or 0 at the current position
            res = solve(i + 1, 1, n) + 
                  solve(i + 1, 0, n);
        } 
        else{
            // try placing 0 after a 1
            res = solve(i + 1, 0, n);
            // try placing 1: now remaining positions can be anything
            // atleast 1 time consecutive '1' is found
            res += 1 << (n-i);
        }

        return res;
    }

    static int countConsec(int n) {
        return solve(1, 0, n);
    }

    public static void main(String[] args) {
        int n = 3;
        System.out.println(countConsec(n));
    }
}
Python
# Recursive helper to count numbers with 
# at least one pair of consecutive 1s
def solve(i, prev, n):
    if i > n:
        return 0

    if prev == 0:
        # Try placing 1 or 0 at the current position
        return  solve(i + 1, 1, n) + \
                solve(i + 1, 0, n)
    else:
        # try placing 0 after a 1
        res = solve(i + 1, 0, n)
        # try placing 1: now remaining positions can be anything
        # atleast 1 time consecutive '1' is found
        res += 1 << (n-i)
        return res

def countConsec(n):
    return solve(1, 0, n)

if __name__ == "__main__":
    n = 3
    print(countConsec(n))
C#
using System;

class GfG {
    // Recursive helper to count numbers with 
    // at least one pair of consecutive 1s
    static int solve(int i, int prev, int n) {
        if (i > n) return 0;

        int res = 0;

        if (prev == 0) {
            // Try placing 1 or 0 at the current position
            res = solve(i + 1, 1, n) + 
                  solve(i + 1, 0, n);
        } 
        else{
            // try placing 0 after a 1
            res = solve(i + 1, 0, n);
            // try placing 1: now remaining positions can be anything
            // atleast 1 time consecutive '1' is found
            res += 1 << (n-i);
        }

        return res;
    }

    static int countConsec(int n) {
        return solve(1, 0, n);
    }

    static void Main() {
        int n = 3;
        Console.WriteLine(countConsec(n));
    }
}
Javascript
// Recursive helper to count numbers with 
// at least one pair of consecutive 1s
function solve(i, prev, n) {
    if (i > n) return 0;

    let res = 0;

    if (prev === 0) {
        // Try placing 1 or 0 at the current position
        res = solve(i + 1, 1, n) + 
              solve(i + 1, 0, n);
    } 
    else{
        // try placing 0 after a 1
        res = solve(i + 1, 0, n);
        // try placing 1: now remaining positions can be anything
        // atleast 1 time consecutive '1' is found
        res += 1 << (n-i);
    }

    return res;
}

function countConsec(n) {
    return solve(1, 0, n);
}

// Driver Code
let n = 3;
console.log(countConsec(3));

Output
3

[Better Approach 1] Top-Down Dynamic Programming (Memoization)

We recursively construct all binary strings of length n, keeping track of whether the previous bit was '1'. At each position i, if we place a '1' after another '1', it means the condition is already satisfied. In this case, we can directly add 2^(n - i) to the result — representing all possible combinations for the remaining bits — and terminate this path early.

This approach avoids exploring unnecessary branches and reduces redundant computation using memoization.
The recursion is defined by the state dp[i][prev], where: i is the current index (bit position) and prev indicates whether the previous bit was '1'.

C++
#include <iostream>
#include <vector>
using namespace std;

// Recursive helper to count numbers with 
// at least one pair of consecutive 1s

int solve(int i, int prev, int n, vector<vector<int>> &dp) {
    if (i > n) return 0;

    if (dp[i][prev] != -1) return dp[i][prev];

    int res = 0;

    if (prev == 0) {
        // Try placing '1' or '0' at the current position
        res = solve(i + 1, 1, n, dp) + 
              solve(i + 1, 0, n, dp);
    } 
    else{
        // Try placing '0' after a '1'
        res = solve(i + 1, 0, n, dp);
        
        // Try placing '1' : now remaining positions can be anything
        // At least 1 time consecutive '1' is found
        res += 1 << (n-i);
    }

    return dp[i][prev] = res;
}

int countConsec(int n) {
    vector<vector<int>> dp(n + 2, vector<int>(2, -1));
    return solve(1, 0, n, dp);
}

int main() {
    int n = 3;
    cout << countConsec(n) << endl;
    return 0;
}
Java
import java.util.*;

class GfG {

    // recursive helper to count numbers with 
    // at least one pair of consecutive 1s
    static int solve(int i, int prev, int n, int[][] dp) {
        if (i > n) return 0;

        if (dp[i][prev] != -1) return dp[i][prev];

        int res = 0;

        if (prev == 0) {
            // try placing '1' or '0' at the current position
            res = solve(i + 1, 1, n, dp) + 
                  solve(i + 1, 0, n, dp);
        } 
        else{
            // try placing '0' after a '1'
            res = solve(i + 1, 0, n, dp);
            
            // try placing '1' : now remaining positions can be anything
            // at least 1 time consecutive '1' is found
            res += 1 << (n-i);
        }

        return dp[i][prev] = res;
    }

    static int countConsec(int n) {
        int[][] dp = new int[n + 2][2];
        for (int[] row : dp) Arrays.fill(row, -1);
        return solve(1, 0, n, dp);
    }

    public static void main(String[] args) {
        int n = 3;
        System.out.println(countConsec(n));
    }
}
Python
# Recursive helper to count numbers with 
# at least one pair of consecutive 1s
def solve(i, prev, n, dp):
    if i > n:
        return 0

    if dp[i][prev] != -1:
        return dp[i][prev]

    res = 0

    if prev == 0:
        # try placing '1' or '0' at the current position
        res = solve(i + 1, 1, n, dp) + \
              solve(i + 1, 0, n, dp)
    else:
        # try placing '0' after a '1'
        res = solve(i + 1, 0, n, dp)
        
        # try placing '1': now remaining positions can be anything
        # at least 1 time consecutive '1' is found
        res += 1 << (n-i)

    dp[i][prev] = res
    return res

def countConsec(n):
    dp = [[-1] * 2 for _ in range(n + 2)]
    return solve(1, 0, n, dp)

if __name__ == "__main__":
    n = 3
    print(countConsec(n))
C#
using System;

class GfG {

    // Recursive helper to count numbers with 
    // at least one pair of consecutive 1s
    static int Solve(int i, int prev, int n, int[,] dp) {
        if (i > n) return 0;

        if (dp[i, prev] != -1) return dp[i, prev];

        int res = 0;

        if (prev == 0) {
            // Try placing '1' or '0' at the current position
            res = Solve(i + 1, 1, n, dp) + 
                  Solve(i + 1, 0, n, dp);
        } 
        else {
            // try placing '0' after a '1'
            res = Solve(i + 1, 0, n, dp);
            
            // try placing '1': now remaining positions can be anything
            // At least 1 time consecutive '1' is found
            res += 1 << (n-i);
        }

        return dp[i, prev] = res;
    }

    static int CountConsec(int n) {
        
        int[,] dp = new int[n + 2, 2];
        for (int i = 0; i <= n + 1; i++) {
            for (int j = 0; j < 2; j++) {
                dp[i, j] = -1;
            }
        }

        return Solve(1, 0, n, dp);
    }

    static void Main() {
        int n = 3;
        Console.WriteLine(CountConsec(n));
    }
}
JavaScript
// Recursive helper to count numbers with 
// at least one pair of consecutive 1s
function solve(i, prev, n, dp) {
    if (i > n) return 0;

    if (dp[i][prev] !== -1) return dp[i][prev];

    let res = 0;

    if (prev === 0) {
        // try placing '1' or '0' at the current position
        res = solve(i + 1, 1, n, dp) + 
              solve(i + 1, 0, n, pow2, dp);
    } 
    else{
        
        // Try placing '0' after a '1'
        res = solve(i + 1, 0, n, dp);
        
        // Try placing '1': now remaining positions can be anything
        // At least 1 time consecutive '1' is found
        res += 1 << (n-i);
        
    }

    return dp[i][prev] = res;
}

function countConsec(n) {
    let pow2 = Array(n + 1).fill(1);
    for (let i = 1; i <= n; i++) {
        pow2[i] = pow2[i - 1] * 2;
    }

    let dp = Array.from({ length: n + 2 }, () => Array(2).fill(-1));
    return solve(1, 0, n, pow2, dp);
}

// Driver Code
let n = 3;
console.log(countConsec(n))

Output
3

Time Complexity: O(n) since there are only 2 choices for prev and n positions, the total number of unique subproblems is 2 * n.
Auxiliary Space: O(n) due to recursion stack in the worst case and the dp table of size 2 * (n+1) used for memoization.

[Better Approach 2] Bottom-Up Dynamic Programming - O(n) Time and O(n) Space

The idea is to simulate the generation of all binary strings of length n and count those that contain at least one pair of consecutive '1's, using dynamic programming.

We define a 2D DP array dp[i][prev], where:

  • i is the current position in the string (0-based index),
  • prev is the last bit placed (0 or 1),
  • dp[i][prev] stores the number of valid binary strings from index i to n - 1 starting with the previous bit prev and containing at least one occurrence of consecutive '1's.

Transitions:

  • If prev == 0, then we can place either 0 or 1 freely since no consecutive 1s are formed yet. So, dp[i][0] = dp[i+1][0] + dp[i+1][1]
  • If prev == 1:
    -> Placing 0: we continue as before → dp[i+1][0]
    -> Placing 1: we form a consecutive pair of 1s, and the rest n-i bits can be anything → contributes 2^(n - i)
    -> So, dp[i][1] = dp[i+1][0] + 2^(n - i)
C++
#include <iostream>
#include <vector>
using namespace std;

int countConsec(int n) {
    // dp[i][prev] = number of binary strings from index i to n
    // with previous bit 'prev' and at least one pair of consecutive '1's

    vector<vector<int>> dp(n + 2, vector<int>(2, 0));

    // Iterate from i = n to 1
    for (int i = n; i >= 1; i--) {
        for (int prev = 0; prev <= 1; prev++) {
            if (prev == 0) {
                // place '0' or '1'
                dp[i][prev] = dp[i + 1][0] + dp[i + 1][1];
            } else {
                // place '0' after '1'
                dp[i][prev] = dp[i + 1][0];

                // place '1' after '1' → found one pair of consecutive '1's,
                // rest (n - i) bits can be anything: 2^(n - i)
                dp[i][prev] += (1 << (n - i));  // 2^(n - i)
            }
        }
    }

    // start from index 1, with prev = 0
    return dp[1][0];  
}

int main() {
    int n = 3;
    cout << countConsec(n) << endl;
    return 0;
}
Java
import java.util.*;

class GfG {
    public static int countConsec(int n) {
        // dp[i][prev] = number of binary strings from index i to n
        // with previous bit 'prev' and at least one pair of consecutive '1's
        int[][] dp = new int[n + 2][2];

        // iterate from i = n to 1
        for (int i = n; i >= 1; i--) {
            for (int prev = 0; prev <= 1; prev++) {
                if (prev == 0) {
                    // place '0' or '1'
                    dp[i][prev] = dp[i + 1][0] + dp[i + 1][1];
                } else {
                    // place '0' after '1'
                    dp[i][prev] = dp[i + 1][0];

                    // place '1' after '1' → found one pair of consecutive '1's,
                    // rest (n - i) bits can be anything: 2^(n - i)
                    dp[i][prev] += (1 << (n - i));
                }
            }
        }

        // start from index 1, with prev = 0
        return dp[1][0];
    }

    public static void main(String[] args) {
        int n = 3;
        System.out.println(countConsec(n));
    }
}
Python
def countConsec(n):
    # dp[i][prev] = number of binary strings from index i to n
    # with previous bit 'prev' and at least one pair of consecutive '1's
    dp = [[0] * 2 for _ in range(n + 2)]

    # iterate from i = n to 1
    for i in range(n, 0, -1):
        for prev in range(2):
            if prev == 0:
                # place '0' or '1'
                dp[i][prev] = dp[i + 1][0] + dp[i + 1][1]
            else:
                # place '0' after '1'
                dp[i][prev] = dp[i + 1][0]

                # place '1' after '1' → found one pair of consecutive '1's,
                # rest (n - i) bits can be anything: 2^(n - i)
                dp[i][prev] += (1 << (n - i))

    # start from index 1, with prev = 0
    return dp[1][0]


if __name__ == "__main__":
    n = 3
    print(countConsec(n))
C#
using System;

class GfG {
    public static int countConsec(int n) {
        // dp[i][prev] = number of binary strings from index i to n
        // with previous bit 'prev' and at least one pair of consecutive '1's
        int[,] dp = new int[n + 2, 2];

        // iterate from i = n to 1
        for (int i = n; i >= 1; i--) {
            for (int prev = 0; prev <= 1; prev++) {
                if (prev == 0) {
                    // place '0' or '1'
                    dp[i, prev] = dp[i + 1, 0] + dp[i + 1, 1];
                } else {
                    // place '0' after '1'
                    dp[i, prev] = dp[i + 1, 0];

                    // place '1' after '1' → found one pair of consecutive '1's,
                    // rest (n - i) bits can be anything: 2^(n - i)
                    dp[i, prev] += (1 << (n - i));
                }
            }
        }

        // start from index 1, with prev = 0
        return dp[1, 0];
    }

    public static void Main() {
        int n = 3;
        Console.WriteLine(countConsec(n));
    }
}
Javascript
function countConsec(n) {
    // dp[i][prev] = number of binary strings from index i to n
    // with previous bit 'prev' and at least one pair of consecutive '1's
    let dp = Array.from({ length: n + 2 }, () => [0, 0]);

    // iterate from i = n to 1
    for (let i = n; i >= 1; i--) {
        for (let prev = 0; prev <= 1; prev++) {
            if (prev === 0) {
                // place '0' or '1'
                dp[i][prev] = dp[i + 1][0] + dp[i + 1][1];
            } else {
                // place '0' after '1'
                dp[i][prev] = dp[i + 1][0];

                // place '1' after '1' → found one pair of consecutive '1's,
                // rest (n - i) bits can be anything: 2^(n - i)
                dp[i][prev] += (1 << (n - i));
            }
        }
    }

    // start from index 1, with prev = 0
    return dp[1][0];
}

// Driver Code
let n = 3;
console.log(countConsec(n))

Output
3

[Expected Approach 1] Space-Optimized Bottom-Up Dynamic Programming - O(n) Time and O(1) Space

We iterate from position n to 1, maintaining two states: one for previous bit being 0 and one for 1.
If the previous bit is 0, both 0 and 1 can be placed.
If the previous bit is 1, placing another 1 forms a valid pair, and the rest of the bits can take any value (2^(n - i))

Transitions:

  • prev0 = count when the previous bit is 0
  • prev1 = count when the previous bit is 1

Then at each position i from n to 1:

  • If previous bit is 0, we can place either 0 or 1, so curr0 = prev0 + prev1
  • If previous bit is 1:
    -> We can place 0 (continue safely)
    -> Or place 1 (forms a valid "11", then rest bits can be anything)curr1 = prev0 + 2^(n - i)

Finally, we return the value of prev0 after the loop since we begin with previous bit as 0.

C++
#include <iostream>
using namespace std;

int countConsec(int n) {
    int prev0 = 0, prev1 = 0;

    for (int i = n; i >= 1; i--) {
        // if previous bit is 0, we can place 0 or 1
        int curr0 = prev0 + prev1;

        // if previous bit is 1, placing another 1 creates a valid pair,
        // remaining bits can be anything: 2^(n - i)
        int curr1 = prev0 + (1 << (n - i));

        // update for next round
        prev0 = curr0;
        prev1 = curr1;
    }

    // start from position 1 with previous bit 0
    return prev0;
}

int main() {
    
    int n = 3;
    cout << countConsec(n) << endl;
    return 0;
    
}
Java
class GfG {
    public static int countConsec(int n) {
        int prev0 = 0, prev1 = 0;

        for (int i = n; i >= 1; i--) {
            // if previous bit is 0, we can place 0 or 1
            int curr0 = prev0 + prev1;

            // if previous bit is 1, placing another 1 creates a valid pair,
            // remaining bits can be anything: 2^(n - i)
            int curr1 = prev0 + (1 << (n - i));

            // update for next round
            prev0 = curr0;
            prev1 = curr1;
        }

        // start from position 1 with previous bit 0
        return prev0;
    }

    public static void main(String[] args) {
        int n = 3;
        System.out.println(countConsec(n));
    }
}
Python
def countConsec(n):
    prev0, prev1 = 0, 0

    for i in range(n, 0, -1):
        # if previous bit is 0, we can place 0 or 1
        curr0 = prev0 + prev1

        # if previous bit is 1, placing another 1 creates a valid pair,
        # remaining bits can be anything: 2^(n - i)
        curr1 = prev0 + (1 << (n - i))

        # update for next round
        prev0, prev1 = curr0, curr1

    # start from position 1 with previous bit 0
    return prev0

if __name__ == "__main__":
    n = 3
    print(countConsec(n))    
C#
using System;

class GfG {
    public static int countConsec(int n) {
        int prev0 = 0, prev1 = 0;

        for (int i = n; i >= 1; i--) {
            // if previous bit is 0, we can place 0 or 1
            int curr0 = prev0 + prev1;

            // if previous bit is 1, placing another 1 creates a valid pair,
            // remaining bits can be anything: 2^(n - i)
            int curr1 = prev0 + (1 << (n - i));

            // update for next round
            prev0 = curr0;
            prev1 = curr1;
        }

        // start from position 1 with previous bit 0
        return prev0;
    }

    public static void Main() {
        int n = 3;
        Console.WriteLine(countConsec(n));
    }
}
JavaScript
function countConsec(n) {
    let prev0 = 0, prev1 = 0;

    for (let i = n; i >= 1; i--) {
        // if previous bit is 0, we can place 0 or 1
        let curr0 = prev0 + prev1;

        // if previous bit is 1, placing another 1 creates a valid pair,
        // remaining bits can be anything: 2^(n - i)
        let curr1 = prev0 + (1 << (n - i));

        // update for next round
        prev0 = curr0;
        prev1 = curr1;
    }

    // start from position 1 with previous bit 0
    return prev0;
}

// Driver Code
let n = 3;
console.log(countConsec(n));

Output
3

[Expected Approach 2] Complement Counting using Dynamic Programming - O(n) Time and O(1) Space

The idea behind this approach is to first count all binary strings of length n that do not contain consecutive 1s, and then subtract that count from the total number of binary strings of length n (which is 2^n).

Transitions:

  • curr0: number of valid binary strings of length i ending in '0' without consecutive 1s.
  • curr1: number of valid binary strings of length i ending in '1' without consecutive 1s.
  • Transition for curr0:
    -> A '0' can be added after both '0' and '1' (no restriction).
    -> So, curr0 = prev0 + prev1
  • Transition for curr1:
    -> A '1' can only be added after a '0' (to avoid consecutive 1s).
    -> So, curr1 = prev0
  • Calculation:
    -> Total number of binary string = 2n
    -> number of strings without consecutive 1s: noConsec = prev0 + prev1
    -> number of strings with at least one pair of consecutive 1s: consec = total - noConsec
C++
#include <iostream>
using namespace std;

int countConsec(int n) {
    
    // prev0 ->  number of strings of length i ending 
    // in '0' with no consecutive 1s
        
    // prev1 ->  number of strings of length i ending 
    // in '1' with no consecutive 1s
    
    int prev0 = 1, prev1 = 1;

    for (int i = 2; i <= n; i++) {
        // if we add '0', it can follow both '0' and '1'
        int curr0 = prev0 + prev1;

        // if we add '1', it can only follow '0' (to avoid consecutive 1s)
        int curr1 = prev0;

        // update for the next length
        prev0 = curr0;
        prev1 = curr1;
    }

    // total number of binary strings of length n
    int total = 1 << n;

    // subtract the number of strings with no consecutive 1s
    int noConsec = prev0 + prev1;

    int consec = total - noConsec;
    
    return consec;
}

int main() {
    int n = 3;
    cout << countConsec(n) << endl;
    return 0;
}
Java
class GfG {

    public static int countConsec(int n) {
        // prev0 -> number of strings of length i ending 
        // in '0' with no consecutive 1s

        // prev1 -> number of strings of length i ending 
        // in '1' with no consecutive 1s
        int prev0 = 1, prev1 = 1;

        for (int i = 2; i <= n; i++) {
            // if we add '0', it can follow both '0' and '1'
            int curr0 = prev0 + prev1;

            // if we add '1', it can only follow '0'
            int curr1 = prev0;

            // update for the next length
            prev0 = curr0;
            prev1 = curr1;
        }

        // total number of binary strings of length n
        int total = 1 << n;

        // subtract the number of strings with no consecutive 1s
        int noConsec = prev0 + prev1;

        int consec = total - noConsec;
        return consec;
    }

    public static void main(String[] args) {
        int n = 3;
        System.out.println(countConsec(n));
    }
}
Python
def countConsec(n):
    # prev0 -> number of strings of length i ending 
    # in '0' with no consecutive 1s

    # prev1 -> number of strings of length i ending 
    # in '1' with no consecutive 1s
    prev0, prev1 = 1, 1

    for i in range(2, n + 1):
        # if we add '0', it can follow both '0' and '1'
        curr0 = prev0 + prev1

        # if we add '1', it can only follow '0'
        curr1 = prev0

        prev0, prev1 = curr0, curr1

    total = 1 << n
    noConsec = prev0 + prev1
    consec = total - noConsec
    return consec


if __name__ == "__main__":
    n = 3
    print(countConsec(n))
C#
using System;

class GfG {
    public static int countConsec(int n) {
        // prev0 -> number of strings of length i ending 
        // in '0' with no consecutive 1s

        // prev1 -> number of strings of length i ending 
        // in '1' with no consecutive 1s
        int prev0 = 1, prev1 = 1;

        for (int i = 2; i <= n; i++) {
            // if we add '0', it can follow both '0' and '1'
            int curr0 = prev0 + prev1;

            // if we add '1', it can only follow '0'
            int curr1 = prev0;

            prev0 = curr0;
            prev1 = curr1;
        }

        int total = 1 << n;
        int noConsec = prev0 + prev1;
        int consec = total - noConsec;

        return consec;
    }

    public static void Main() {
        int n = 3;
        Console.WriteLine(countConsec(n));
    }
}
JavaScript
function countConsec(n) {
    // prev0 -> number of strings of length i ending 
    // in '0' with no consecutive 1s

    // prev1 -> number of strings of length i ending 
    // in '1' with no consecutive 1s
    let prev0 = 1, prev1 = 1;

    for (let i = 2; i <= n; i++) {
        // if we add '0', it can follow both '0' and '1'
        let curr0 = prev0 + prev1;

        // if we add '1', it can only follow '0'
        let curr1 = prev0;

        prev0 = curr0;
        prev1 = curr1;
    }

    let total = 1 << n;
    let noConsec = prev0 + prev1;
    let consec = total - noConsec;
    return consec;
}

// Driver Code
let n = 3;
console.log(countConsec(n));

Output
3

[Optimized Approach] Using nth Fibonacci - O(log(n)) Time and O(log(n)) Space

The idea is to compute the total number of strings without consecutive 1's and subtract that from the total number of binary strings. The key observation is that the count of binary strings without consecutive 1's of length n follows the (n + 2)th Fibonacci number. This is because each valid string of length n can be formed by appending a 0 or 1 to shorter valid strings, similar to Fibonacci recurrence.

To optimize the solution, we use matrix exponentiation which allows us to compute the nth Fibonacci number in O(log n) time instead of linear time or dynamic programming.

If we take a closer look at the pattern of counting strings without consecutive 1's, we can observe that the count is actually the (n + 2)th Fibonacci number for n >= 1. The Fibonacci numbers are: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …

Examples:

  • n = 1 → total = 2 → without = fib(3) = 2 → result = 0
  • n = 2 → total = 4 → without = fib(4) = 3 → result = 1
  • n = 3 → total = 8 → without = fib(5) = 5 → result = 3
  • n = 4 → total = 16 → without = fib(6) = 8 → result = 8
  • n = 5 → total = 32 → without = fib(7) = 13 → result = 19
C++
#include <iostream>
#include <vector>
using namespace std;

// Function to multiply two 2x2 matrices
void multiply(vector<vector<int>>& mat1,
                                vector<vector<int>>& mat2) {

    // Perform matrix multiplication
    int x = mat1[0][0] * mat2[0][0] + mat1[0][1] * mat2[1][0];
    int y = mat1[0][0] * mat2[0][1] + mat1[0][1] * mat2[1][1];
    int z = mat1[1][0] * mat2[0][0] + mat1[1][1] * mat2[1][0];
    int w = mat1[1][0] * mat2[0][1] + mat1[1][1] * mat2[1][1];

    // Update matrix mat1 with the result
    mat1[0][0] = x;
    mat1[0][1] = y;
    mat1[1][0] = z;
    mat1[1][1] = w;
}

// Function to perform matrix exponentiation
void matrixPower(vector<vector<int>>& mat1, int n) {

    // Base case for recursion
    if (n == 0 || n == 1) return;

    // Initialize a helper matrix
    vector<vector<int>> mat2 = {{1, 1}, {1, 0}};

    // Recursively calculate mat1^(n/2)
    matrixPower(mat1, n / 2);

    // Square the matrix mat1
    multiply(mat1, mat1);

    // If n is odd, multiply by the helper matrix mat2
    if (n % 2 != 0) {
        multiply(mat1, mat2);
    }
}

// Function to calculate the nth Fibonacci number
// using matrix exponentiation
int nthFibonacci(int n) {
    if (n <= 1) return n;

    vector<vector<int>> mat1 = {{1, 1}, {1, 0}};

    // Raise the matrix mat1 to the power of (n - 1)
    matrixPower(mat1, n - 1);

    return mat1[0][0];
}

// Function to count binary strings of length n
// that have at least one pair of consecutive 1's
int countConsec(int n) {

    // Total binary strings of length n = 2^n
    int total = 1 << n;

    // Count of strings without consecutive 1's = Fib(n + 2)
    int noConsec = nthFibonacci(n + 2);

    return total - noConsec;
}

int main() {
    int n = 3;
    cout << countConsec(n);
    return 0;
}
Java
class GfG {

    // Function to multiply two 2x2 matrices
    static void multiply(int[][] mat1, int[][] mat2) {

        // Perform matrix multiplication
        int x = mat1[0][0] * mat2[0][0] + mat1[0][1] * mat2[1][0];
        int y = mat1[0][0] * mat2[0][1] + mat1[0][1] * mat2[1][1];
        int z = mat1[1][0] * mat2[0][0] + mat1[1][1] * mat2[1][0];
        int w = mat1[1][0] * mat2[0][1] + mat1[1][1] * mat2[1][1];

        // Update matrix mat1 with the result
        mat1[0][0] = x;
        mat1[0][1] = y;
        mat1[1][0] = z;
        mat1[1][1] = w;
    }

    // Function to perform matrix exponentiation
    static void matrixPower(int[][] mat1, int n) {

        // Base case for recursion
        if (n == 0 || n == 1) return;

        // Initialize a helper matrix
        int[][] mat2 = {{1, 1}, {1, 0}};

        // Recursively calculate mat1^(n/2)
        matrixPower(mat1, n / 2);

        // Square the matrix mat1
        multiply(mat1, mat1);

        // If n is odd, multiply by the helper matrix mat2
        if (n % 2 != 0) {
            multiply(mat1, mat2);
        }
    }

    // Function to calculate the nth Fibonacci number
    // using matrix exponentiation
    static int nthFibonacci(int n) {
        if (n <= 1) return n;

        int[][] mat1 = {{1, 1}, {1, 0}};

        // Raise the matrix mat1 to the power of (n - 1)
        matrixPower(mat1, n - 1);

        return mat1[0][0];
    }

    // Function to count binary strings of length n
    // that have at least one pair of consecutive 1's
    static int countConsec(int n) {

        // Total binary strings of length n = 2^n
        int total = 1 << n;

        // Count of strings without consecutive 1's = Fib(n + 2)
        int noConsec = nthFibonacci(n + 2);

        return total - noConsec;
    }

    public static void main(String[] args) {
        int n = 3;
        System.out.println(countConsec(n));
    }
}
Python
# Function to multiply two 2x2 matrices
def multiply(mat1, mat2):

    # Perform matrix multiplication
    x = mat1[0][0] * mat2[0][0] + mat1[0][1] * mat2[1][0]
    y = mat1[0][0] * mat2[0][1] + mat1[0][1] * mat2[1][1]
    z = mat1[1][0] * mat2[0][0] + mat1[1][1] * mat2[1][0]
    w = mat1[1][0] * mat2[0][1] + mat1[1][1] * mat2[1][1]

    # Update matrix mat1 with the result
    mat1[0][0] = x
    mat1[0][1] = y
    mat1[1][0] = z
    mat1[1][1] = w

# Function to perform matrix exponentiation
def matrixPower(mat1, n):

    # Base case for recursion
    if n == 0 or n == 1:
        return

    # Initialize a helper matrix
    mat2 = [[1, 1], [1, 0]]

    # Recursively calculate mat1^(n/2)
    matrixPower(mat1, n // 2)

    # Square the matrix mat1
    multiply(mat1, mat1)

    # If n is odd, multiply by the helper matrix mat2
    if n % 2 != 0:
        multiply(mat1, mat2)

# Function to calculate the nth Fibonacci number
# using matrix exponentiation
def nthFibonacci(n):
    if n <= 1:
        return n

    mat1 = [[1, 1], [1, 0]]

    # Raise the matrix mat1 to the power of (n - 1)
    matrixPower(mat1, n - 1)

    return mat1[0][0]

# Function to count binary strings of length n
# that have at least one pair of consecutive 1's
def countConsec(n):
    # Total binary strings of length n = 2^n
    total = 1 << n
    # Count of strings without consecutive 1's = Fib(n + 2)
    noConsec = nthFibonacci(n + 2)
    return total - noConsec

if __name__ == "__main__":
    n = 3
    print(countConsec(n))
C#
using System;

class GfG {

    // Function to multiply two 2x2 matrices
    static void multiply(int[,] mat1, int[,] mat2) {

        // Perform matrix multiplication
        int x = mat1[0,0] * mat2[0,0] + mat1[0,1] * mat2[1,0];
        int y = mat1[0,0] * mat2[0,1] + mat1[0,1] * mat2[1,1];
        int z = mat1[1,0] * mat2[0,0] + mat1[1,1] * mat2[1,0];
        int w = mat1[1,0] * mat2[0,1] + mat1[1,1] * mat2[1,1];

        // Update matrix mat1 with the result
        mat1[0,0] = x;
        mat1[0,1] = y;
        mat1[1,0] = z;
        mat1[1,1] = w;
    }

    // Function to perform matrix exponentiation
    static void matrixPower(int[,] mat1, int n) {

        // Base case for recursion
        if (n == 0 || n == 1) return;

        // Initialize a helper matrix
        int[,] mat2 = {{1, 1}, {1, 0}};

        // Recursively calculate mat1^(n/2)
        matrixPower(mat1, n / 2);

        // Square the matrix mat1
        multiply(mat1, mat1);

        // If n is odd, multiply by the helper matrix mat2
        if (n % 2 != 0) {
            multiply(mat1, mat2);
        }
    }

    // Function to calculate the nth Fibonacci number
    // using matrix exponentiation
    static int nthFibonacci(int n) {
        if (n <= 1) return n;

        int[,] mat1 = {{1, 1}, {1, 0}};

        // Raise the matrix mat1 to the power of (n - 1)
        matrixPower(mat1, n - 1);

        return mat1[0,0];
    }

    // Function to count binary strings of length n
    // that have at least one pair of consecutive 1's
    static int countConsec(int n) {
        // Total binary strings of length n = 2^n
        int total = 1 << n;

        // Count of strings without consecutive 1's = Fib(n + 2)
        int noConsec = nthFibonacci(n + 2);
        return total - noConsec;
    }

    static void Main() {
        int n = 3;
        Console.WriteLine(countConsec(n));
    }
}
JavaScript
// Function to multiply two 2x2 matrices
function multiply(mat1, mat2) {

    // Perform matrix multiplication
    let x = mat1[0][0] * mat2[0][0] + mat1[0][1] * mat2[1][0];
    let y = mat1[0][0] * mat2[0][1] + mat1[0][1] * mat2[1][1];
    let z = mat1[1][0] * mat2[0][0] + mat1[1][1] * mat2[1][0];
    let w = mat1[1][0] * mat2[0][1] + mat1[1][1] * mat2[1][1];

    // Update matrix mat1 with the result
    mat1[0][0] = x;
    mat1[0][1] = y;
    mat1[1][0] = z;
    mat1[1][1] = w;
}

// Function to perform matrix exponentiation
function matrixPower(mat1, n) {

    // Base case for recursion
    if (n === 0 || n === 1) return;

    // Initialize a helper matrix
    let mat2 = [[1, 1], [1, 0]];

    // Recursively calculate mat1^(n/2)
    matrixPower(mat1, Math.floor(n / 2));

    // Square the matrix mat1
    multiply(mat1, mat1);

    // If n is odd, multiply by the helper matrix mat2
    if (n % 2 !== 0) {
        multiply(mat1, mat2);
    }
}

// Function to calculate the nth Fibonacci number
// using matrix exponentiation
function nthFibonacci(n) {
    if (n <= 1) return n;

    let mat1 = [[1, 1], [1, 0]];

    // Raise the matrix mat1 to the power of (n - 1)
    matrixPower(mat1, n - 1);

    return mat1[0][0];
}

// Function to count binary strings of length n
// that have at least one pair of consecutive 1's
function countConsec(n) {

    // Total binary strings of length n = 2^n
    let total = 1 << n;

    // Count of strings without consecutive 1's = Fib(n + 2)
    let noConsec = nthFibonacci(n + 2);

    return total - noConsec;
}

// Driver Code
let n = 3;
console.log(countConsec(n));

Output
3

 


Practice Tags :

Similar Reads