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:
- Flipping the 1st and 2nd coins once and the third coin twice modifies the configuration to “TTH”.
- Flipping the 1st and 3rd coins once and the 2nd coin twice modifies the configuration to “THT”.
- 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:
- Consider F(N, S) represents the number of unique outcomes when N coins are tossed with the total number of flips equals to S.
- Then F(N, S) can also be expressed as the sum of all combinations with 1 flip or 2 flips i.e.,
F(N, S) = F(N – 1, S – 1) + F(N – 1, S – 2)
- The base case for this recurrence relation is F(K, K) whose value is 1 for all (K > 1).
- Below is the table that shows the distribution of F(N, S) = F(N – 1, S – 1) + F(N – 1, S – 2), where F(K, K) = 1.
Follow the below steps to solve the problem:
- Declare a function, say numberOfUniqueOutcomes(N, S) that takes the number of coins and flips allowed as the parameters respectively and perform the following steps:
- If the value of S is less than N, then return 0 from the function.
- If the value of N is S or 1, then return 1 from the function as this is one of the unique combinations.
- Recursively return summation of the two recursive states as:
return numberOfUniqueOutcomes(N – 1, S – 1) + numberOfUniqueOutcomes(N – 1, S – 2)
- After completing the above steps, print the value returned by the function numberOfUniqueOutcomes(N, S) as the resultant number of outcomes.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int numberOfUniqueOutcomes( int N, int S)
{
if (S < N)
return 0;
if (N == 1 || N == S)
return 1;
return (numberOfUniqueOutcomes(N - 1, S - 1)
+ numberOfUniqueOutcomes(N - 1, S - 2));
}
int main()
{
int N = 3, S = 4;
cout << numberOfUniqueOutcomes(N, S);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static int numberOfUniqueOutcomes( int N, int S)
{
if (S < N)
return 0 ;
if (N == 1 || N == S)
return 1 ;
return (numberOfUniqueOutcomes(N - 1 , S - 1 )
+ numberOfUniqueOutcomes(N - 1 , S - 2 ));
}
public static void main (String[] args)
{
int N = 3 , S = 4 ;
System.out.println(numberOfUniqueOutcomes(N, S));
}
}
|
Python3
def numberOfUniqueOutcomes(N, S):
if (S < N):
return 0
if (N = = 1 or N = = S):
return 1
return (numberOfUniqueOutcomes(N - 1 , S - 1 ) +
numberOfUniqueOutcomes(N - 1 , S - 2 ))
if __name__ = = '__main__' :
N, S = 3 , 4
print (numberOfUniqueOutcomes(N, S))
|
C#
using System;
class GFG{
static int numberOfUniqueOutcomes( int N, int S)
{
if (S < N)
return 0;
if (N == 1 || N == S)
return 1;
return (numberOfUniqueOutcomes(N - 1, S - 1) +
numberOfUniqueOutcomes(N - 1, S - 2));
}
static public void Main()
{
int N = 3, S = 4;
Console.WriteLine(numberOfUniqueOutcomes(N, S));
}
}
|
Javascript
<script>
function numberOfUniqueOutcomes(N, S) {
if (S < N)
return 0;
if (N == 1 || N == S)
return 1;
return (numberOfUniqueOutcomes(N - 1, S - 1)
+ numberOfUniqueOutcomes(N - 1, S - 2));
}
let N = 3, S = 4;
document.write(numberOfUniqueOutcomes(N, S))
</script>
|
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:
- Initialize a 2D array, say dp[][] of dimensions N*M such that dp[i][j] stores the number of possible outcomes using i coins and j number of flips.
- Declare a function, say numberOfUniqueOutcomes(N, S), that takes the number of coins and flips allowed as the parameters respectively and perform the following steps:
- If the value of S is less than N, then update the value of dp[N][S] as 0 and return this value from the function.
- If the value of N is S or 1, then update the value of dp[N][S] as 1 and return this value from the function as this is one of the unique combinations.
- If the value of dp[N][S] is already calculated, then return the value dp[N][S] from the function.
- Recursively update the value of dp[N][S] summation of the two recursive states as shown below and return this value from the function.
dp[N][S] = numberOfUniqueOutcomes(N – 1, S – 1) + numberOfUniqueOutcomes(N – 1, S – 2)
- After completing the above steps, print the value returned by the function numberOfUniqueOutcomes(N, S) as the resultant number of outcomes.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define size 1001
int ans[size][size] = { 0 };
int numberOfUniqueOutcomes( int n, int s)
{
if (s < n)
ans[n][s] = 0;
else if (n == 1 || n == s)
ans[n][s] = 1;
else if (!ans[n][s]) {
ans[n][s] = numberOfUniqueOutcomes(n - 1,
s - 1)
+ numberOfUniqueOutcomes(n - 1,
s - 2);
}
return ans[n][s];
}
int main()
{
int N = 5, S = 8;
cout << numberOfUniqueOutcomes(N, S);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int size = 100 ;
static int [][]ans = new int [size][size];
static void initialize()
{
for ( int i = 0 ; i < size; i++)
{
for ( int j = 0 ; j < size; j++)
{
ans[i][j] = 0 ;
}
}
}
static int numberOfUniqueOutcomes( int n, int s)
{
if (s < n)
ans[n][s] = 0 ;
else if (n == 1 || n == s)
ans[n][s] = 1 ;
else if (ans[n][s] == 0 ) {
ans[n][s] = numberOfUniqueOutcomes(n - 1 ,
s - 1 )
+ numberOfUniqueOutcomes(n - 1 ,
s - 2 );
}
return ans[n][s];
}
public static void main(String args[])
{
initialize();
int N = 5 , S = 8 ;
System.out.println(numberOfUniqueOutcomes(N, S));
}
}
|
Python3
size = 100
ans = [[ 0 for i in range (size)]
for j in range (size)]
def numberOfUniqueOutcomes(n, s):
if (s < n):
ans[n][s] = 0 ;
elif (n = = 1 or n = = s):
ans[n][s] = 1 ;
elif (ans[n][s] = = 0 ):
ans[n][s] = (numberOfUniqueOutcomes(n - 1 , s - 1 ) +
numberOfUniqueOutcomes(n - 1 , s - 2 ))
return ans[n][s];
N = 5
S = 8
print (numberOfUniqueOutcomes(N, S))
|
C#
using System;
class GFG{
static int size = 100;
static int [,]ans = new int [size, size];
static void initialize()
{
for ( int i = 0; i < size; i++)
{
for ( int j = 0; j < size; j++)
{
ans[i, j] = 0;
}
}
}
static int numberOfUniqueOutcomes( int n, int s)
{
if (s < n)
ans[n, s] = 0;
else if (n == 1 || n == s)
ans[n, s] = 1;
else if (ans[n, s] == 0)
{
ans[n, s] = numberOfUniqueOutcomes(n - 1,
s - 1) +
numberOfUniqueOutcomes(n - 1,
s - 2);
}
return ans[n,s];
}
public static void Main( string []args)
{
initialize();
int N = 5, S = 8;
Console.WriteLine(numberOfUniqueOutcomes(N, S));
}
}
|
Javascript
<script>
let size = 100;
let ans = new Array(size);
function initialize()
{
for (let i = 0; i < size; i++)
{
ans[i] = new Array(size);
for (let j = 0; j < size; j++)
{
ans[i][j] = 0;
}
}
}
function numberOfUniqueOutcomes(n, s)
{
if (s < n)
ans[n][s] = 0;
else if (n == 1 || n == s)
ans[n][s] = 1;
else if (ans[n][s] == 0) {
ans[n][s] = numberOfUniqueOutcomes(n - 1,
s - 1)
+ numberOfUniqueOutcomes(n - 1,
s - 2);
}
return ans[n][s];
}
initialize();
let N = 5, S = 8;
document.write(numberOfUniqueOutcomes(N, S));
</script>
|
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 :
- Declare and initialize the 2D DP table with 0s.
- Set base cases, i.e., if there is only one coin or if the number of flips is equal to the number of coins, then there is only one way to get the outcome.
- Use bottom-up approach to fill up the DP table, iterating over the number of coins and number of flips.
- For each (i, j) combination, calculate the number of outcomes by flipping i-th coin and the number of outcomes by not flipping it.
- The total number of unique outcomes is the value at dp[n][s], where n is the number of coins and s is the number of flips.
- Return the final answer stored in dp[n][s].
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int numberOfUniqueOutcomes( int n, int s)
{
int dp[n + 1][s + 1];
memset (dp, 0, sizeof (dp));
for ( int i = 1; i <= n; i++) {
for ( int j = i; j <= s; j++) {
if (i == 1 || j == i) {
dp[i][j] = 1;
}
}
}
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 dp[n][s];
}
int main()
{
int N = 5, S = 8;
cout << numberOfUniqueOutcomes(N, S);
return 0;
}
|
Java
import java.util.Arrays;
public class Main
{
static int numberOfUniqueOutcomes( int n, int s)
{
int [][] dp = new int [n + 1 ][s + 1 ];
for ( int [] row : dp) {
Arrays.fill(row, 0 );
}
for ( int i = 1 ; i <= n; i++) {
for ( int j = i; j <= s; j++) {
if (i == 1 || j == i) {
dp[i][j] = 1 ;
}
}
}
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 dp[n][s];
}
public static void main(String[] args) {
int N = 5 , S = 8 ;
System.out.println(numberOfUniqueOutcomes(N, S));
}
}
|
Python3
def number_of_unique_outcomes(n, s):
dp = [[ 0 for i in range (s + 1 )] for j in range (n + 1 )]
for i in range ( 1 , n + 1 ):
for j in range (i, s + 1 ):
if i = = 1 or j = = i:
dp[i][j] = 1
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 dp[n][s]
if __name__ = = '__main__' :
N = 5
S = 8
print (number_of_unique_outcomes(N, S))
|
Javascript
function numberOfUniqueOutcomes(n, s) {
let dp = new Array(n + 1).fill( null ).map(() => new Array(s + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let j = i; j <= s; j++) {
if (i == 1 || j == i) {
dp[i][j] = 1;
}
}
}
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 dp[n][s];
}
let N = 5, S = 8;
console.log(numberOfUniqueOutcomes(N, S));
|
C#
using System;
public class Program {
static int numberOfUniqueOutcomes( int n, int s)
{
int [, ] dp = new int [n + 1, s + 1];
for ( int i = 1; i <= n; i++) {
for ( int j = i; j <= s; j++) {
if (i == 1 || j == i) {
dp[i, j] = 1;
}
}
}
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 dp[n, s];
}
public static void Main()
{
int N = 5, S = 8;
Console.WriteLine(numberOfUniqueOutcomes(N, S));
}
}
|
Time Complexity: O(N*S)
Auxiliary Space: O(N*S)
Last Updated :
09 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...