Open In App

Count all unique outcomes possible by performing S flips on N coins

Given two positive integers N and S, the task is to count the number of unique outcomes possible when S flip operations are performed on N coins.

Examples:



Input: N = 3, S = 4
Output: 3
Explanation: Considering the initial configuration of coins to be “HHH”, then the possible combinations of 4 flips are:

  1. Flipping the 1st and 2nd coins once and the third coin twice modifies the configuration to “TTH”.
  2. Flipping the 1st and 3rd coins once and the 2nd coin twice modifies the configuration to “THT”.
  3. Flipping the 2nd and 3rd coins once and the 1st coin twice modifies the configuration to “HTT”.

The above three combinations are unique. Therefore, the total count is 3.



Input: N = 3, S = 6
Output: 4

Naive Approach: The given problem can be solved by using recursion whose recursive state is defined as:

F(N, S) = F(N – 1, S – 1) + F(N – 1, S – 2)

Follow the below steps to solve the problem:

return numberOfUniqueOutcomes(N – 1, S – 1) + numberOfUniqueOutcomes(N – 1, S – 2)

Below is the implementation of the above approach:




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to recursively count the
// number of unique outcomes possible
// S flips are performed on N coins
int numberOfUniqueOutcomes(int N, int S)
{
    // Base Cases
    if (S < N)
        return 0;
    if (N == 1 || N == S)
        return 1;
 
    // Recursive Calls
    return (numberOfUniqueOutcomes(N - 1, S - 1)
            + numberOfUniqueOutcomes(N - 1, S - 2));
}
 
// Driver Code
int main()
{
    int N = 3, S = 4;
 
    cout << numberOfUniqueOutcomes(N, S);
 
    return 0;
}




// Java program for the above approach
import java.io.*;
class GFG
{
 
  // Function to recursively count the
  // number of unique outcomes possible
  // S flips are performed on N coins
  static int numberOfUniqueOutcomes(int N, int S)
  {
 
    // Base Cases
    if (S < N)
      return 0;
    if (N == 1 || N == S)
      return 1;
 
    // Recursive Calls
    return (numberOfUniqueOutcomes(N - 1, S - 1)
            + numberOfUniqueOutcomes(N - 1, S - 2));
  }
 
  // Driver Code
  public static void main (String[] args)
  {
    int N = 3, S = 4;
    System.out.println(numberOfUniqueOutcomes(N, S));
  }
}
 
//  This code is contributed by avanitrachhadiya2155




# Python3 program for the above approach
 
# Function to recursively count the
# number of unique outcomes possible
# S flips are performed on N coins
def numberOfUniqueOutcomes(N, S):
     
    # Base Cases
    if (S < N):
        return 0
    if (N == 1 or N == S):
        return 1
 
    # Recursive Calls
    return (numberOfUniqueOutcomes(N - 1, S - 1) +
            numberOfUniqueOutcomes(N - 1, S - 2))
 
# Driver Code
if __name__ == '__main__':
     
    N, S = 3, 4
 
    print (numberOfUniqueOutcomes(N, S))
 
# This code is contributed by mohit kumar 29




// C# program for the above approach
using System;
 
class GFG{
 
// Function to recursively count the
// number of unique outcomes possible
// S flips are performed on N coins
static int numberOfUniqueOutcomes(int N, int S)
{
     
    // Base Cases
    if (S < N)
        return 0;
    if (N == 1 || N == S)
        return 1;
     
    // Recursive Calls
    return (numberOfUniqueOutcomes(N - 1, S - 1) +
            numberOfUniqueOutcomes(N - 1, S - 2));
}
 
// Driver Code
static public void Main()
{
    int N = 3, S = 4;
     
    Console.WriteLine(numberOfUniqueOutcomes(N, S));
}
}
 
// This code is contributed by sanjoy_62




<script>
        // Javascript program for the above approach
 
        // Function to recursively count the
        // number of unique outcomes possible
        // S flips are performed on N coins
        function numberOfUniqueOutcomes(N, S) {
            // Base Cases
            if (S < N)
                return 0;
            if (N == 1 || N == S)
                return 1;
 
            // Recursive Calls
            return (numberOfUniqueOutcomes(N - 1, S - 1)
                + numberOfUniqueOutcomes(N - 1, S - 2));
        }
 
        // Driver Code
 
        let N = 3, S = 4;
 
        document.write(numberOfUniqueOutcomes(N, S))
 
        // This code is contributed by Hritik
    </script>

Output: 
3

 

Time Complexity: O(2N)
Auxiliary Space: O(N)

Efficient Approach: The above approach can also be optimized by storing the recursive states as it contains overlapping subproblems. Therefore, the idea is to use memoization to store the repeated states. Follow the steps below to solve the problem:

dp[N][S] = numberOfUniqueOutcomes(N – 1, S – 1) + numberOfUniqueOutcomes(N – 1, S – 2)

Below is the implementation of the above approach:




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Dimensions of the DP table
#define size 1001
 
// Stores the dp states
int ans[size][size] = { 0 };
 
// Function to recursively count the
// number of unique outcomes possible
// by performing S flips on N coins
int numberOfUniqueOutcomes(int n, int s)
{
    // Base Case
    if (s < n)
        ans[n][s] = 0;
 
    else if (n == 1 || n == s)
        ans[n][s] = 1;
 
    // If the count for the current
    // state is not calculated, then
    // calculate it recursively
    else if (!ans[n][s]) {
        ans[n][s] = numberOfUniqueOutcomes(n - 1,
                                           s - 1)
                    + numberOfUniqueOutcomes(n - 1,
                                             s - 2);
    }
 
    // Otherwise return the
    // already calculated value
    return ans[n][s];
}
 
// Driver Code
int main()
{
    int N = 5, S = 8;
 
    cout << numberOfUniqueOutcomes(N, S);
 
    return 0;
}




// Java program for the above approach
 
import java.util.*;
 
class GFG{
  
 // Dimensions of the DP table
static int size = 100;
static int [][]ans = new int[size][size];
   
static void initialize()
{
   
  // Stores the dp states
  for(int i = 0; i < size; i++)
  {
    for(int j = 0; j < size; j++)
    {
        ans[i][j] = 0;
    }
}
}
 
// Function to recursively count the
// number of unique outcomes possible
// by performing S flips on N coins
static int numberOfUniqueOutcomes(int n, int s)
{
    // Base Case
    if (s < n)
        ans[n][s] = 0;
 
    else if (n == 1 || n == s)
        ans[n][s] = 1;
 
    // If the count for the current
    // state is not calculated, then
    // calculate it recursively
    else if (ans[n][s] == 0) {
        ans[n][s] = numberOfUniqueOutcomes(n - 1,
                                           s - 1)
                    + numberOfUniqueOutcomes(n - 1,
                                             s - 2);
    }
 
    // Otherwise return the
    // already calculated value
    return ans[n][s];
}
 
// Driver Code
public static void main(String args[])
{
    initialize();
    int N = 5, S = 8;
    System.out.println(numberOfUniqueOutcomes(N, S));
}
}
 
// This code is contributed by SURENDRA_GANGWAR.




# Python3 program for the above approach
 
# Dimensions of the DP table
size = 100
 
# Stores the dp states
ans = [[0 for i in range(size)]
          for j in range(size)]
 
# Function to recursively count the
# number of unique outcomes possible
# by performing S flips on N coins
def numberOfUniqueOutcomes(n, s):
     
    # Base Case
    if (s < n):
        ans[n][s] = 0;
     
    elif (n == 1 or n == s):
        ans[n][s] = 1;
     
    # If the count for the current
    # state is not calculated, then
    # calculate it recursively
    elif(ans[n][s] == 0):
        ans[n][s] = (numberOfUniqueOutcomes(n - 1, s - 1) +
                     numberOfUniqueOutcomes(n - 1, s - 2))
     
    # Otherwise return the
    # already calculated value
    return ans[n][s];
 
# Driver Code
N = 5
S = 8
 
print(numberOfUniqueOutcomes(N, S))
 
# This code is contributed by rag2127




// C# program for the above approach
using System;
 
class GFG{
  
// Dimensions of the DP table
static int size = 100;
static int [,]ans = new int[size, size];
   
static void initialize()
{
   
    // Stores the dp states
    for(int i = 0; i < size; i++)
    {
        for(int j = 0; j < size; j++)
        {
            ans[i, j] = 0;
        }
    }
}
 
// Function to recursively count the
// number of unique outcomes possible
// by performing S flips on N coins
static int numberOfUniqueOutcomes(int n, int s)
{
     
    // Base Case
    if (s < n)
        ans[n, s] = 0;
 
    else if (n == 1 || n == s)
        ans[n, s] = 1;
 
    // If the count for the current
    // state is not calculated, then
    // calculate it recursively
    else if (ans[n, s] == 0)
    {
        ans[n, s] = numberOfUniqueOutcomes(n - 1,
                                           s - 1) +
                    numberOfUniqueOutcomes(n - 1,
                                           s - 2);
    }
 
    // Otherwise return the
    // already calculated value
    return ans[n,s];
}
 
// Driver Code
public static void Main(string []args)
{
    initialize();
    int N = 5, S = 8;
     
    Console.WriteLine(numberOfUniqueOutcomes(N, S));
}
}
 
// This code is contributed by AnkThon




<script>
 
    // JavaScript program for the above approach
     
    // Dimensions of the DP table
    let size = 100;
    let ans = new Array(size);
 
    function initialize()
    {
 
      // Stores the dp states
      for(let i = 0; i < size; i++)
      {
          ans[i] = new Array(size);
        for(let j = 0; j < size; j++)
        {
            ans[i][j] = 0;
        }
      }
    }
 
    // Function to recursively count the
    // number of unique outcomes possible
    // by performing S flips on N coins
    function numberOfUniqueOutcomes(n, s)
    {
        // Base Case
        if (s < n)
            ans[n][s] = 0;
 
        else if (n == 1 || n == s)
            ans[n][s] = 1;
 
        // If the count for the current
        // state is not calculated, then
        // calculate it recursively
        else if (ans[n][s] == 0) {
            ans[n][s] = numberOfUniqueOutcomes(n - 1,
                                               s - 1)
                        + numberOfUniqueOutcomes(n - 1,
                                                 s - 2);
        }
 
        // Otherwise return the
        // already calculated value
        return ans[n][s];
    }
     
    initialize();
    let N = 5, S = 8;
    document.write(numberOfUniqueOutcomes(N, S));
     
</script>

Output: 
15

 

Time Complexity: O(N*S)
Auxiliary Space: O(N*S)

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 + memorization(top-down) because memorization method needs extra stack space of recursion calls.

Steps to solve this problem :

Implementation :
 




#include <bits/stdc++.h>
using namespace std;
 
// Function to count the number of unique outcomes possible
// by performing S flips on N coins
int numberOfUniqueOutcomes(int n, int s)
{
    // Declare and initialize the DP table with 0s
    int dp[n + 1][s + 1];
    memset(dp, 0, sizeof(dp));
 
    // Base cases
    for (int i = 1; i <= n; i++) {
        for (int j = i; j <= s; j++) {
            if (i == 1 || j == i) {
                dp[i][j] = 1;
            }
        }
    }
 
    // Fill up the DP table using bottom-up approach
    for (int i = 2; i <= n; i++) {
        for (int j = i + 1; j <= s; j++) {
            dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j - 2];
        }
    }
 
    // Return the final answer
    return dp[n][s];
}
 
// Driver Code
int main()
{
    int N = 5, S = 8;
 
    cout << numberOfUniqueOutcomes(N, S);
 
    return 0;
}
 
// this code is contributed by bhardwajji




import java.util.Arrays;
 
public class Main
{
 
  // Function to count the number of unique outcomes possible
  // by performing S flips on N coins
  static int numberOfUniqueOutcomes(int n, int s)
  {
 
    // Declare and initialize the DP table with 0s
    int[][] dp = new int[n + 1][s + 1];
    for (int[] row : dp) {
      Arrays.fill(row, 0);
    }
 
    // Base cases
    for (int i = 1; i <= n; i++) {
      for (int j = i; j <= s; j++) {
        if (i == 1 || j == i) {
          dp[i][j] = 1;
        }
      }
    }
 
    // Fill up the DP table using bottom-up approach
    for (int i = 2; i <= n; i++) {
      for (int j = i + 1; j <= s; j++) {
        dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j - 2];
      }
    }
 
    // Return the final answer
    return dp[n][s];
  }
 
  // Driver Code
  public static void main(String[] args) {
    int N = 5, S = 8;
    System.out.println(numberOfUniqueOutcomes(N, S));
  }
}




# Function to count the number of unique outcomes possible
# by performing S flips on N coins
 
 
def number_of_unique_outcomes(n, s):
    # Declare and initialize the DP table with 0s
    dp = [[0 for i in range(s + 1)] for j in range(n + 1)]
 
    # Base cases
    for i in range(1, n + 1):
        for j in range(i, s + 1):
            if i == 1 or j == i:
                dp[i][j] = 1
 
    # Fill up the DP table using bottom-up approach
    for i in range(2, n + 1):
        for j in range(i + 1, s + 1):
            dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j - 2]
 
    # Return the final answer
    return dp[n][s]
 
 
# Driver Code
if __name__ == '__main__':
    N = 5
    S = 8
 
    print(number_of_unique_outcomes(N, S))




// Function to count the number of unique outcomes possible
// by performing S flips on N coins
function numberOfUniqueOutcomes(n, s) {
// Declare and initialize the DP table with 0s
let dp = new Array(n + 1).fill(null).map(() => new Array(s + 1).fill(0));
 
// Base cases
for (let i = 1; i <= n; i++) {
for (let j = i; j <= s; j++) {
if (i == 1 || j == i) {
dp[i][j] = 1;
}
}
}
 
// Fill up the DP table using bottom-up approach
for (let i = 2; i <= n; i++) {
for (let j = i + 1; j <= s; j++) {
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j - 2];
}
}
 
// Return the final answer
return dp[n][s];
}
 
// Driver Code
let N = 5, S = 8;
console.log(numberOfUniqueOutcomes(N, S));




// C# program for the above approach
using System;
 
public class Program {
   
    // Function to count the number of
    // unique outcomes possible by performing
    // S flips on N coins
    static int numberOfUniqueOutcomes(int n, int s)
    {
        // Declare and initialize the DP
        // table with 0s
        int[, ] dp = new int[n + 1, s + 1];
 
        // Base cases
        for (int i = 1; i <= n; i++) {
            for (int j = i; j <= s; j++) {
                if (i == 1 || j == i) {
                    dp[i, j] = 1;
                }
            }
        }
 
        // Fill up the DP table using
        // bottom-up approach
        for (int i = 2; i <= n; i++) {
            for (int j = i + 1; j <= s; j++) {
                dp[i, j]
                    = dp[i - 1, j - 1] + dp[i - 1, j - 2];
            }
        }
 
        // Return the final answer
        return dp[n, s];
    }
 
    // Driver Code
    public static void Main()
    {
        int N = 5, S = 8;
        Console.WriteLine(numberOfUniqueOutcomes(N, S));
    }
}

Output
15

Time Complexity: O(N*S)
Auxiliary Space: O(N*S)


Article Tags :