Calculate Stirling numbers which represents the number of ways to arrange r objects around n different circles
Last Updated :
07 Nov, 2023
S(r, n), represents the number of ways that we can arrange r objects around indistinguishable circles of length n, and every circle n must have at least one object around it.
Examples:
Input: r = 9, n = 2
Output: 109584
Input: r = 6, n = 3
Output: 225
The special cases are:
- S(r, 0) = 0, trivial.
- S(r, 1) represents the circular permutation which is equal to (r – 1)!
- S(r, n) where r = n, equals 1.
- S(r, r -1) = rC2
An important identity of the Stirling numbers that S(r, n) = S(r – 1, n – 1) + (r – 1) * S(r – 1, n)
Approach: For simplicity, denote the r distinct objects by 1, 2, …, r. Consider the object “1”. In any arrangement of the objects, either
- “1” is the only object in a circle or
- “1” is mixed with others in a circle.
In case 1, there are s(r – 1, n – 1) ways to form such arrangements. In case 2, first of all, the r — 1 objects 2, 3, …, r are put in n circles in s(r — 1, n) ways; then “1” can be placed in one of the r — 1 distinct space to the “immediate right” of the corresponding r — 1 distinct objects. By multiplication principle, there are (r — 1)s(r — 1, n) ways to form such arrangements in case 2. The identity now follows from the definition of s(r, n) and addition principle.
Using the initial values S(0, 0) = 1, s(r, 0) = 0 for r > 1 and s(r, 1) = (r — 1)! for r > 1, and applying the identity we proved, we can easily get the Stirling number by computing it in a recursive way.
In the code, we have three functions that are used to generate the Stirling numbers, which are nCr(n, r), which is a function to compute what we call (n – choose – r), the number of ways we can take r objects from n objects without the importance of orderings. factorial (int n) is, unsurprisingly, used to compute the factorial of a number n. The function Stirling number(r, n) works recursively using the four base cases discussed above and then recursing using the identity we proved.
Below is the implementation of the above approach:
C++
#include <iostream>
using namespace std;
long long factorial( int n)
{
if (n == 0)
return 1;
if (n < 0)
return -1;
long long res = 1;
for ( int i = 2; i < n + 1; ++i)
res *= i;
return res;
}
int nCr( int n, int r)
{
if (r > n)
return -1;
if (n == r)
return 1;
if (r == 0)
return 1;
return nCr(n - 1, r - 1) + nCr(n - 1, r);
}
long long stirlingNumber( int r, int n)
{
if (n > r)
return -1;
if (n == 0)
return 0;
if (r == n)
return 1;
if (n == 1)
return factorial(r - 1);
if (r - n == 1)
return nCr(r, 2);
else
return stirlingNumber(r - 1, n - 1)
+ (r - 1) * stirlingNumber(r - 1, n);
}
int main()
{
int r = 9, n = 2;
long long val = stirlingNumber(r, n);
if (val == -1)
cout << " No stirling number" ;
else
cout << "The Stirling Number s(" << r
<< ", " << n << ") is : " << val;
return 0;
}
|
Java
import java.io.*;
class GFG
{
static long factorial( int n)
{
if (n == 0 )
return 1 ;
if (n < 0 )
return - 1 ;
long res = 1 ;
for ( int i = 2 ; i < n + 1 ; ++i)
res *= i;
return res;
}
static int nCr( int n, int r)
{
if (r > n)
return - 1 ;
if (n == r)
return 1 ;
if (r == 0 )
return 1 ;
return nCr(n - 1 , r - 1 ) +
nCr(n - 1 , r);
}
static long stirlingNumber( int r, int n)
{
if (n > r)
return - 1 ;
if (n == 0 )
return 0 ;
if (r == n)
return 1 ;
if (n == 1 )
return factorial(r - 1 );
if (r - n == 1 )
return nCr(r, 2 );
else
return stirlingNumber(r - 1 , n - 1 ) +
(r - 1 ) *
stirlingNumber(r - 1 , n);
}
public static void main (String[] args)
{
int r = 9 , n = 2 ;
long val = stirlingNumber(r, n);
if (val == - 1 )
System.out.println( " No stirling number" );
else
System.out.println( "The Stirling Number s(" +
r + ", " + n + ") is : " + val);
}
}
|
Python 3
def nCr(n, r):
if (n = = r):
return 1
if (r = = 0 ):
return 1
return nCr(n - 1 , r - 1 ) + nCr(n - 1 , r)
def factorial(n):
res = 1
if (n < = 1 ):
return res
for i in range ( 1 , n + 1 ):
res * = i
return res
def stirlingNumber(r, n):
if (r = = n):
return 1
if (n = = 0 ):
return 0
if (n = = r - 1 ):
return nCr(r, 2 )
if (r - n = = 1 ):
return factorial(r - 1 )
return (stirlingNumber(r - 1 , n - 1 )
+ (r - 1 ) * stirlingNumber(r - 1 , n))
r, n = 9 , 2
print (stirlingNumber(r, n))
|
C#
using System;
class GFG
{
static long factorial( int n)
{
if (n == 0)
return 1;
if (n < 0)
return -1;
long res = 1;
for ( int i = 2; i < n + 1; ++i)
res *= i;
return res;
}
static int nCr( int n, int r)
{
if (r > n)
return -1;
if (n == r)
return 1;
if (r == 0)
return 1;
return nCr(n - 1, r - 1) +
nCr(n - 1, r);
}
static long stirlingNumber( int r, int n)
{
if (n > r)
return -1;
if (n == 0)
return 0;
if (r == n)
return 1;
if (n == 1)
return factorial(r - 1);
if (r - n == 1)
return nCr(r, 2);
else
return stirlingNumber(r - 1, n - 1) +
(r - 1) *
stirlingNumber(r - 1, n);
}
public static void Main ()
{
int r = 9, n = 2;
long val = stirlingNumber(r, n);
if (val == -1)
Console.WriteLine( " No stirling number" );
else
Console.WriteLine( "The Stirling Number s(" +
r + ", " + n + ") is : " + val);
}
}
|
Javascript
<script>
function factorial( n)
{
if (n == 0)
return 1;
if (n < 0)
return -1;
let res = 1;
for (let i = 2; i < n + 1; ++i)
res *= i;
return res;
}
function nCr(n, r)
{
if (r > n)
return -1;
if (n == r)
return 1;
if (r == 0)
return 1;
return nCr(n - 1, r - 1) + nCr(n - 1, r);
}
function stirlingNumber( r, n)
{
if (n > r)
return -1;
if (n == 0)
return 0;
if (r == n)
return 1;
if (n == 1)
return factorial(r - 1);
if (r - n == 1)
return nCr(r, 2);
else
return stirlingNumber(r - 1, n - 1)
+ (r - 1) * stirlingNumber(r - 1, n);
}
let r = 9, n = 2;
let val = stirlingNumber(r, n);
if (val == -1)
document.write( " No stirling number" );
else
document.write( "The Stirling Number s(" , r
, ", " , n , ") is : " , val);
</script>
|
PHP
<?php
function factorial( $n )
{
if ( $n == 0)
return 1;
if ( $n < 0)
return -1;
$res = 1;
for ( $i = 2; $i < $n + 1; ++ $i )
$res *= $i ;
return $res ;
}
function nCr( $n , $r )
{
if ( $r > $n )
return -1;
if ( $n == $r )
return 1;
if ( $r == 0)
return 1;
return nCr( $n - 1, $r - 1) + nCr( $n - 1, $r );
}
function stirlingNumber( $r , $n )
{
if ( $n > $r )
return -1;
if ( $n == 0)
return 0;
if ( $r == $n )
return 1;
if ( $n == 1)
return factorial( $r - 1);
if ( $r - $n == 1)
return nCr( $r , 2);
else
return stirlingNumber( $r - 1, $n - 1)
+ ( $r - 1) * stirlingNumber( $r - 1, $n );
}
$r = 9;
$n = 2;
$val = stirlingNumber( $r , $n );
if ( $val == -1)
echo " No stirling number" ;
else
echo "The Stirling Number s(" , $r
, ", " , $n , ") is : " , $val ;
?>
|
Output
The Stirling Number s(9, 2) is : 109584
Time Complexity : O(r * n)
Auxiliary Space : O(r * n)
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 + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Implementation :
C++
#include <iostream>
#include <vector>
using namespace std;
long long factorial( int n)
{
if (n == 0 || n == 1)
return 1;
long long res = 1;
for ( int i = 2; i <= n; ++i) {
res *= i;
}
return res;
}
long long stirlingNumber( int r, int n)
{
vector<vector< long long > > dp(
n + 1, vector< long long >(r + 1, 0));
for ( int i = 0; i <= n; i++) {
dp[i][i] = 1;
}
for ( int i = 1; i <= r; i++) {
dp[1][i] = factorial(i - 1);
}
for ( int i = 2; i <= n; i++) {
for ( int j = 2; j <= r; j++) {
dp[i][j]
= dp[i - 1][j - 1] + (j - 1) * dp[i][j - 1];
}
}
return dp[n][r];
}
int main()
{
int r = 9, n = 2;
long long val = stirlingNumber(r, n);
if (val == -1)
cout << " No stirling number" ;
else
cout << "The Stirling Number s(" << r << ", " << n
<< ") is : " << val;
return 0;
}
|
Java
import java.util.Arrays;
public class StirlingNumbers {
public static long factorial( int n) {
if (n == 0 || n == 1 ) {
return 1 ;
}
long res = 1 ;
for ( int i = 2 ; i <= n; ++i) {
res *= i;
}
return res;
}
public static long stirlingNumber( int r, int n) {
long [][] dp = new long [n + 1 ][r + 1 ];
for ( int i = 0 ; i <= n; i++) {
dp[i][i] = 1 ;
}
for ( int i = 1 ; i <= r; i++) {
dp[ 1 ][i] = factorial(i - 1 );
}
for ( int i = 2 ; i <= n; i++) {
for ( int j = 2 ; j <= r; j++) {
dp[i][j] = dp[i - 1 ][j - 1 ] + (j - 1 ) * dp[i][j - 1 ];
}
}
return dp[n][r];
}
public static void main(String[] args) {
int r = 9 , n = 2 ;
long val = stirlingNumber(r, n);
if (val == - 1 )
System.out.println( "No Stirling number" );
else
System.out.println( "The Stirling Number s(" + r + ", " + n + ") is : " + val);
}
}
|
Python3
def factorial(n):
if n = = 0 or n = = 1 :
return 1
res = 1
for i in range ( 2 , n + 1 ):
res * = i
return res
def stirling_number(r, n):
dp = [[ 0 ] * (r + 1 ) for _ in range (n + 1 )]
for i in range (n + 1 ):
dp[i][i] = 1
for i in range ( 1 , r + 1 ):
dp[ 1 ][i] = factorial(i - 1 )
for i in range ( 2 , n + 1 ):
for j in range ( 2 , r + 1 ):
dp[i][j] = dp[i - 1 ][j - 1 ] + (j - 1 ) * dp[i][j - 1 ]
return dp[n][r]
if __name__ = = "__main__" :
r = 9
n = 2
val = stirling_number(r, n)
if val = = - 1 :
print ( "No Stirling number" )
else :
print (f "The Stirling Number s({r}, {n}) is: {val}" )
|
C#
using System;
public class StirlingNumbers {
public static long Factorial( int n)
{
if (n == 0 || n == 1) {
return 1;
}
long res = 1;
for ( int i = 2; i <= n; i++) {
res *= i;
}
return res;
}
public static long StirlingNumber( int r, int n)
{
long [, ] dp = new long [n + 1, r + 1];
for ( int i = 0; i <= n; i++) {
dp[i, i] = 1;
}
for ( int i = 1; i <= r; i++) {
dp[1, i] = Factorial(i - 1);
}
for ( int i = 2; i <= n; i++) {
for ( int j = 2; j <= r; j++) {
dp[i, j] = dp[i - 1, j - 1]
+ (j - 1) * dp[i, j - 1];
}
}
return dp[n, r];
}
public static void Main( string [] args)
{
int r = 9;
int n = 2;
long val = StirlingNumber(r, n);
if (val == -1) {
Console.WriteLine( "No Stirling number" );
}
else {
Console.WriteLine( "The Stirling Number s(" + r
+ ", " + n + ") is: " + val);
}
}
}
|
Javascript
function factorial(n) {
if (n === 0 || n === 1) {
return 1;
}
let res = 1;
for (let i = 2; i <= n; i++) {
res *= i;
}
return res;
}
function stirlingNumber(r, n) {
const dp = new Array(n + 1).fill( null ).map(() => new Array(r + 1).fill(0));
for (let i = 0; i <= n; i++) {
dp[i][i] = 1;
}
for (let i = 1; i <= r; i++) {
dp[1][i] = factorial(i - 1);
}
for (let i = 2; i <= n; i++) {
for (let j = 2; j <= r; j++) {
dp[i][j] = dp[i - 1][j - 1] + (j - 1) * dp[i][j - 1];
}
}
return dp[n][r];
}
function main() {
const r = 9;
const n = 2;
const val = stirlingNumber(r, n);
if (val === -1) {
console.log( "No Stirling number" );
} else {
console.log( "The Stirling Number s(" + r + ", " + n + ") is : " + val);
}
}
main();
|
Output
The Stirling Number s(9, 2) is : 109584
Time Complexity : O(r * n)
Auxiliary Space : O(r * n)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...