Program to calculate value of nCr (original) (raw)

Given two numbers **n and **r, The task is to find the value of **n C r . Combinations represent the number of ways to choose r elements from a set of n distinct elements, without regard to the order in which they are selected. The formula for calculating combinations is :

Combinations

**Note: If r is greater than n, return **0.

**Examples

**Input: n = 5, r = 2
**Output: 10
**Explanation: The value of 5C2 is calculated as 5! / ((5−2)! * 2!​)= 10.

**Input: n = 2, r = 4
*Output: 0
*Explanation: Since r is greater than n, thus *2C**4
*= 0

**Input: n = 5, r = 0
**Output: 1
**Explanation: The value of 5C0 is calculated as 5!/(5−0)!*0! = 5!/5!*0! = 1.

Table of Content

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

The idea is to use a recursive function to calculate the value of nCr. The base cases are:

For other values of n and r, the function calculates the value of nCr by adding the number of combinations possible by including the current element and the number of combinations possible by not including the current element.

C++ `

#include using namespace std;

int nCr(int n, int r) {

// No valid combinations if r is greater than n
if (r > n) 
    return 0;

// Base case: only one way to choose 0 or all elements
if (r == 0 || r == n) 
    return 1;

// include or exclude current element
return nCr(n - 1, r - 1) + nCr(n - 1, r);

}

// Driver Code int main() { int n = 5; int r = 2; cout << nCr(n, r); return 0; }

Java

import java.util.*;

class GfG {

public static int nCr(int n, int r) {
  
    // No valid combinations if r is greater than n
    if (r > n) 
        return 0;
  
    // Base case: only one way to choose 0 or all elements    
    if (r == 0 || r == n) 
        return 1;
  
    // include or exclude current element
    return nCr(n - 1, r - 1) + nCr(n - 1, r);
}

// Driver Code public static void main(String[] args) { int n = 5; int r = 2; System.out.println(nCr(n, r)); } }

Python

def nCr(n, r):

# No valid combinations if r is greater than n
if r > n:  
    return 0

# Base case: only one way to choose 0 or all elements    
if r == 0 or r == n:  
    return 1

# include or exclude current element
return nCr(n - 1, r - 1) + nCr(n - 1, r)

Driver Code

if name == "main": n = 5 r = 2 print(nCr(n, r))

C#

using System;

class GfG {

static public int nCr(int n, int r) {
   
    // No valid combinations if r is greater than n
    if (r > n) 
        return 0;
   
    // Base case: only one way to choose 0 or all elements    
    if (r == 0 || r == n) 
        return 1;
   
    // include or exclude current element
    return nCr(n - 1, r - 1) + nCr(n - 1, r);
}

// Driver Code static public void Main(string[] args) { int n = 5; int r = 2; Console.WriteLine(nCr(n, r)); } }

JavaScript

function nCr(n, r) {

// No valid combinations if r is greater than n
if (r > n) 
    return 0;

// Base case: only one way to choose 0 or all elements    
if (r === 0 || r === n) 
    return 1;

// include or exclude current element
return nCr(n - 1, r - 1) + nCr(n - 1, r);

}

// Driver Code let n = 5; let r = 2; console.log(nCr(n, r));

`

[Better Approach - 1] Using Factorial - O(n) Time and O(1) Space

This approach calculates the nCr using the factorial formula. It first computes the factorial of a given number by multiplying all integers from 1 to that number.
To find nCr, it calculates the factorial of n, r, and (n - r) separately, then applies the formula n! / (r!(n-r)!) to determine the result. Since factorial values grow rapidly, this method is inefficient for large values due to integer overflow and excessive computations.

**Note: This approach may produce incorrect results due to **integer overflow when handling large values of n and r.

C++ `

#include using namespace std;

// Returns factorial of n int fact(int n) { int res = 1; for (int i = 2; i <= n; i++) res *= i; return res; }

int nCr(int n, int r) {

// No valid combinations if r is greater than n
if (r > n)
    return 0;
return fact(n) / (fact(r) * fact(n - r));

}

// Driver Code int main() { int n = 5, r = 2; cout << nCr(n, r); return 0; }

Java

class GfG {

static int nCr(int n, int r) {
    
    // No valid combinations if r is greater than n
    if (r > n) 
        return 0;
    return fact(n) / (fact(r) * fact(n - r));
}

// Returns factorial of n
static int fact(int n) {
    int res = 1;
    for (int i = 2; i <= n; i++)
        res *= i;
    return res;
}

// Driver code
public static void main(String[] args) {
    int n = 5, r = 2;
    System.out.println(nCr(n, r));
}

}

Python

def nCr(n, r):

# No valid combinations if r is greater than n
if r > n:  
    return 0
    
# Calculate nCr using factorial formula
return fact(n) // (fact(r) * fact(n - r))

Returns factorial of n

def fact(n): res = 1 for i in range(2, n + 1): res *= i return res

if name == "main": n = 5 r = 2 print(int(nCr(n, r)))

C#

using System;

class GFG {

// Calculates nCr using factorial formula
static int nCr(int n, int r) {
    
    // No valid combinations if r is greater than n
    if (r > n) 
        return 0;
    return fact(n) / (fact(r) * fact(n - r));
}

// Returns factorial of n
static int fact(int n) {
    int res = 1;
    for (int i = 2; i <= n; i++)
        res *= i;
    return res;
}

public static void Main() {
    int n = 5, r = 2;
    Console.Write(nCr(n, r)); 
}

}

JavaScript

function nCr(n, r) {

// No valid combinations if r is greater than n
if (r > n) 
    return 0;
    
// Calculate nCr using factorial formula
return fact(n) / (fact(r) * fact(n - r)); 

}

// Returns factorial of n function fact(n) { let res = 1; for (let i = 2; i <= n; i++) res *= i; return res; }

// Driver code let n = 5, r = 2; console.log(nCr(n, r));

`

[Better Approach - 2] Avoiding Factorial Computations - O(n) Time and O(1) Space

The formula for nCr is n! / (r!(n-r)!).
Instead of computing full factorials, we avoid redundant calculations by recognizing that r! and (n-r)! share common terms that cancel out.
To optimize, we compute the product of numbers from r+1 to n and divide it by the product of numbers from 1 to (n-r).
Here, r is chosen as the maximum of r and (n-r) to reduce the number of multiplications.
This approach avoids large factorial values, reducing computational overhead and preventing integer overflow.

**Note: This approach may produce incorrect results due to **integer overflow when handling large values of n and r.

C++ `

#include using namespace std;

// Calculates the product of natural // numbers from start to end double Multiplier(int start, int end) { if (start == end) return start;

double res = 1;
while (start <= end) {
    res *= start;
    start++;
}
return res;

}

int nCr(int n, int r) { // No valid combinations if r > n if (n < r) return 0; // Base cases: nC0 or nCn = 1
if (n == r || r == 0) return 1;

// Use max(r, n-r) to minimize the 
// number of multiplications
int max_val = max(r, n - r);
int min_val = min(r, n - r);

double nume = Multiplier(max_val + 1, n);
double deno = Multiplier(1, min_val);

return int(nume / deno);

}

int main() { int n = 5; int r = 2; cout << nCr(n,min(r,n-r)) << endl; return 0; }

Java

class GfG {

// Calculates the product of natural 
// numbers from start to end
public static double Multiplier(int start, int end) {
    if (start == end)
        return start;

    double res = 1;
    while (start <= end) {
        res *= start;
        start++;
    }
    return res;
}

public static int nCr(int n, int r) {
    // No valid combinations if r > n
    if (n < r) 
        return 0;
    // Base cases: nC0 or nCn = 1
    if (n == r || r == 0) 
        return 1;

    // Use max(r, n-r) to reduce the 
    // number of multiplications
    int max_val = Math.max(r, n - r);
    int min_val = Math.min(r, n - r);

    double nume = Multiplier(max_val + 1, n);
    double deno = Multiplier(1, min_val);

    return (int)(nume / deno);
}

public static void main(String[] args) {
    int n = 5;
    int r = 2;
    System.out.println(nCr(n, r)); // Output the result of 5C2
}

}

Python

def Multiplier(start, end): if start == end: return start res = 1 while start <= end: res *= start start += 1 return res

def nCr(n, r): # No valid combinations if r > n if n < r:
return 0 # Base cases: nC0 or nCn = 1 if n == r or r == 0:
return 1

# Use max(r, n - r) to reduce 
# number of multiplications
max_val = max(r, n - r)
min_val = min(r, n - r)

nume = Multiplier(max_val + 1, n)
deno = Multiplier(1, min_val)
return nume // deno

if name == "main": n = 5 r = 2 print(nCr(n, r))

C#

using System;

class Program {

// Calculates the product of natural 
// numbers from start to end
static double Multiplier(int start, int end) {
    if (start == end)
        return start;

    double res = 1;
    while (start <= end) {
        res *= start;
        start++;
    }
    return res;
}

static int nCr(int n, int r) {
    // No valid combinations if r > n
    if (n < r) 
        return 0;
    // Base cases: nC0 or nCn = 1
    if (n == r || r == 0) 
        return 1;

    // Use max(r, n - r) to minimize 
    // number of multiplications
    int max_val = Math.Max(r, n - r);
    int min_val = Math.Min(r, n - r);

    double nume = Multiplier(max_val + 1, n);
    double deno = Multiplier(1, min_val);

    return (int)(nume / deno);
}

static void Main() {
    int n = 5;
    int r = 2;
    Console.WriteLine(nCr(n, r));
}

}

JavaScript

// Calculate multiplication of natural // numbers from start to end function Multiplier(start, end) { if (start === end) { return start; } let res = 1; while (start <= end) { res *= start; start++; } return res; }

function nCr(n, r) { // No valid combinations if r > n if (n < r) { return 0; } // Base cases: nC0 or nCn = 1 if (n === r || r === 0) { return 1; }

// Use max(r, n - r) to reduce the 
// number of multiplications
const max_val = Math.max(r, n - r);
const min_val = Math.min(r, n - r);

const nume = Multiplier(max_val + 1, n);
const deno = Multiplier(1, min_val);

return Math.round(nume / deno);

}

// Driver Code const n = 5; const r = 2; console.log(nCr(n, r));

`

[Expected Approach] By using Binomial Coefficient formula - O(r) Time and O(1) Space

A binomial coefficient C(n, k) can be defined as the coefficient of Xk in the expansion of (1 + X)n.
A binomial coefficient C(n, k) also gives the number of ways, disregarding order, that k objects can be chosen from among n objects; more formally, the number of k-element subsets (or k-combinations) of an n-element set.
Iterative way of calculating **n C r using binomial coefficient formula.

C++ `

#include using namespace std; int nCr(int n, int r){

double sum = 1;

// Calculate the value of n choose
// r using the binomial coefficient formula
for (int i = 1; i <= r; i++){
    
    sum = sum * (n - r + i) / i;
}
return (int)sum;

} int main(){

int n = 5;
int r = 2;
cout << nCr(n, r);

return 0;

}

Java

import java.util.*;

class GfG{

public static int nCr(int n, int r){
    
    double sum = 1;

    // Calculate the value of n choose r using the
    // binomial coefficient formula
    for (int i = 1; i <= r; i++) {
        sum = sum * (n - r + i) / i;
    }

    return (int)sum;
}
public static void main(String[] args){

    int n = 5;
    int r = 2;
    System.out.println(nCr(n,r));
}

}

Python

def nCr(n, r):

sum = 1

# Calculate the value of n choose r 
# using the binomial coefficient formula
for i in range(1, r+1):
    sum = sum * (n - r + i) // i

return sum

if name == "main": n = 5 r = 2

print(nCr(n, r))

C#

using System;

class GfG { static int nCr(int n, int r){ double sum = 1;

    // Calculate the value of n choose r
    // using the binomial coefficient formula
    for(int i = 1; i <= r; i++){
        sum = sum * (n - r + i) / i;
    }
    return (int)sum;
}
static void Main() {
    int n = 5;
    int r = 2;
    
    Console.WriteLine(nCr(n,r));
}

}

JavaScript

function nCr(n, r){ let sum = 1;

// Calculate the value of n choose r 
// using the binomial coefficient formula
for(let i = 1; i <= r; i++){
  sum = sum * (n - r + i) / i;
}

return Math.floor(sum);

}

// Driver Code let n = 5; let r = 2;

console.log(nCr(n,r));

`

[Alternate Approach] Using Logarithmic Formula - O(r) Time and O(1)

Logarithmic formula for nCr is an alternative to the factorial formula that avoids computing factorials directly and it's more efficient for large values of n and r. It uses the identity log(n!) = log(1) + log(2) + ... + log(n) to express the numerator and denominator of the nCr in terms of sums of logarithms which allows to calculate the nCr using the Logarithmic operations. This approach is faster and very efficient.
The logarithmic formula for nCr is: **n C r **= exp( log(n!) - log(r!) - log((n-r)!))

C++ `

#include #include using namespace std;

// Calculates the binomial coefficient nCr using logarithmic formula int nCr(int n, int r) { // Invalid case if (r > n) return 0;
// Base cases if (r == 0 || n == r) return 1;

double res = 0;
for (int i = 0; i < r; i++) {
    // log(n!) - log(r!) - log((n-r)!)
    res += log(n - i) - log(i + 1);  
}

return (int)round(exp(res));

}

int main() { int n = 5; int r = 2; cout << nCr(n, r) << endl; return 0; }

Java

import java.lang.Math;

// Calculates the binomial coefficient nCr using the logarithmic formula public class GfG { public static int nCr(int n, int r) { // Invalid case if (r > n) return 0;
// Base cases if (r == 0 || n == r) return 1;

    double res = 0;
    for (int i = 0; i < r; i++) {
        // log(n!) - log(r!) - log((n-r)!)
        res += Math.log(n - i) - Math.log(i + 1);  
    }

    return (int)Math.round(Math.exp(res));  
}

public static void main(String[] args) {
    int n = 5;
    int r = 2;
    System.out.println(nCr(n, r)); 
}

}

Python

import math

Calculates the binomial coefficient nCr using the logarithmic formula

def nCr(n, r): # Invalid case if r > n:
return 0 # Base cases if r == 0 or n == r:
return 1

res = 0
for i in range(r):
    # log(n!) - log(r!) - log((n-r)!)
    res += math.log(n - i) - math.log(i + 1)  

return round(math.exp(res))  

if name == "main": n = 5 r = 2 print(nCr(n, r))

C#

using System;

class GfG {

// Calculates the binomial coefficient nCr using the logarithmic formula
public static int nCr(int n, int r) {
    // Invalid case
    if (r > n) return 0;    
    // Base cases
    if (r == 0 || n == r) return 1;       

    double res = 0;
    for (int i = 0; i < r; i++) {
        // log(n!) - log(r!) - log((n-r)!)
        res += Math.Log(n - i) - Math.Log(i + 1);  
    }

    return (int)Math.Round(Math.Exp(res)); 
}

static void Main(string[] args) {
    int n = 5;
    int r = 2;
    Console.WriteLine(nCr(n, r));  
}

}

JavaScript

// Calculates the binomial coefficient nCr using the logarithmic formula function nCr(n, r) { // Invalid case if (r > n) return 0;
// Base cases if (r === 0 || n === r) return 1;

let res = 0;
for (let i = 0; i < r; i++) {
     // log(n!) - log(r!) - log((n-r)!)
    res += Math.log(n - i) - Math.log(i + 1); 
}

return Math.round(Math.exp(res));  

}

// Driver code const n = 5; const r = 2; console.log(nCr(n, r));

`