Given two numbers n and k where n represents a number of elements in a set, find a number of ways to partition the set into k subsets.
Example:
Input: n = 3, k = 2
Output: 3
Explanation: Let the set be {1, 2, 3}, we can partition
it into 2 subsets in following ways
{{1,2}, {3}}, {{1}, {2,3}}, {{1,3}, {2}}
Input: n = 3, k = 1
Output: 1
Explanation: There is only one way {{1, 2, 3}}
Recursive Solution
- Approach: Firstly, let’s define a recursive solution to find the solution for nth element. There are two cases.
- The previous n – 1 elements are divided into k partitions, i.e S(n-1, k) ways. Put this nth element into one of the previous k partitions. So, count = k * S(n-1, k)
- The previous n – 1 elements are divided into k – 1 partitions, i.e S(n-1, k-1) ways. Put the nth element into a new partition ( single element partition).So, count = S(n-1, k-1)
- Total count = k * S(n-1, k) + S(n-1, k-1).
- Algorithm:
- Create a recursive function which accepts two parameters, n and k. The function returns total number of partitions of n elements into k sets.
- Handle the base cases. If n = 0 or k = 0 or k > n return 0 as there cannot be any subset. If n is equal to k or k is equal to 1 return 1.
- Else calculate the value as follows: S(n, k) = k*S(n-1, k) + S(n-1, k-1), i.e call recursive function with the required parameter and calculate the value of S(n, k).
- Return the sum.
- Implementation:
C++
#include<iostream>
using namespace std;
int countP( int n, int k)
{
if (n == 0 || k == 0 || k > n)
return 0;
if (k == 1 || k == n)
return 1;
return k*countP(n-1, k) + countP(n-1, k-1);
}
int main()
{
cout << countP(3, 2);
return 0;
}
|
Java
import java.io.*;
class GFG
{
public static int countP( int n, int k)
{
if (n == 0 || k == 0 || k > n)
return 0 ;
if (k == 1 || k == n)
return 1 ;
return (k * countP(n - 1 , k)
+ countP(n - 1 , k - 1 ));
}
public static void main(String args[])
{
System.out.println(countP( 3 , 2 ));
}
}
|
Python 3
def countP(n, k):
if (n = = 0 or k = = 0 or k > n):
return 0
if (k = = 1 or k = = n):
return 1
return (k * countP(n - 1 , k) +
countP(n - 1 , k - 1 ))
if __name__ = = "__main__" :
print (countP( 3 , 2 ))
|
C#
using System;
class GFG {
public static int countP( int n, int k)
{
if (n == 0 || k == 0 || k > n)
return 0;
if (k == 1 || k == n)
return 1;
return (k * countP(n - 1, k)
+ countP(n - 1, k - 1));
}
public static void Main()
{
Console.WriteLine(countP(3, 2));
}
}
|
PHP
<?php
function countP( $n , $k )
{
if ( $n == 0 || $k == 0 || $k > $n )
return 0;
if ( $k == 1 || $k == $n )
return 1;
return $k * countP( $n - 1, $k ) +
countP( $n - 1, $k - 1);
}
echo countP(3, 2);
?>
|
Javascript
<script>
function countP(n, k)
{
if (n == 0 || k == 0 || k > n)
return 0;
if (k == 1 || k == n)
return 1;
return (k * countP(n - 1, k)
+ countP(n - 1, k - 1));
}
document.write(countP(3, 2));
</script>
|
3
- Complexity Analysis:
- Time complexity: O(2^n).
For every value of n, two recursive function is called. More specifically the Time complexity is exponential. - Space complexity: O(n)(Due to call stack), since n extra space has been taken.
Efficient Solution
- Approach: The time complexity of above recursive solution is exponential. The solution can be optimized by reducing the overlapping subproblems. Below is recursion tree of countP(10,7). The subproblem countP(8,6) or CP(8,6) is called multiple times.

- So this problem has both properties (see Type 1 and Type 2) of a dynamic programming problem. Like other typical Dynamic Programming(DP) problems, recomputations of same subproblems can be avoided by constructing a temporary array dp[][] in bottom up manner using the shown recursive formula.
Next comes the reduction of the sub-problems to optimize the complexity of the problem. This can be done in two ways: - bottom-up manner: This keeps the recursive structure intact and stores the values in a hashmap or a 2D array. Then compute the value only once and when the function is called next return the value.
- top-down manner: This keeps a 2D array of size n*k, where dp[i][j] represents a total number of partitions of i elements into j sets. Fill in the base cases for dp[i][0] and dp[0][i]. For a value (i,j), the values of dp[i-1][j] and dp[i-1][j-1] is needed. So fill the DP from row 0 to n and column 0 to k.
- Algorithm:
- Create a Dp array dp[n+1][k+1] of size ( n + 1 )* ( k + 1 ) .
- Fill the values of basic cases. For all values of i from 0 to n fill dp[i][0] = 0 and for all values of i from 0 to k fill dp[0][k] = 0
- Run a nested loop, the outer loop from 1 to n, and inner loop from 1 to k.
- For index i and j (outer loop and inner loop respectively), calculate dp[i][j] = j * dp[i – 1][j] + dp[i – 1][j – 1] and if j == 1 or i == j, calculate dp[i][j] = 1.
- Print values dp[n][k]
- Implementation:
C++
#include<iostream>
using namespace std;
int countP( int n, int k)
{
int dp[n+1][k+1];
for ( int i = 0; i <= n; i++)
dp[i][0] = 0;
for ( int i = 0; i <= k; i++)
dp[0][k] = 0;
for ( int i = 1; i <= n; i++)
for ( int j = 1; j <= i; j++)
if (j == 1 || i == j)
dp[i][j] = 1;
else
dp[i][j] = j * dp[i - 1][j] + dp[i - 1][j - 1];
return dp[n][k];
}
int main()
{
cout << countP(5, 2);
return 0;
}
|
Java
import java.util.*;
import java.io.*;
class GFG{
static int countP( int n, int k)
{
int [][] dp = new int [n+ 1 ][k+ 1 ];
for ( int i = 0 ; i <= n; i++)
dp[i][ 0 ] = 0 ;
for ( int i = 0 ; i <= k; i++)
dp[ 0 ][k] = 0 ;
for ( int i = 1 ; i <= n; i++)
for ( int j = 1 ; j <= k; j++)
if (j == 1 || i == j)
dp[i][j] = 1 ;
else
dp[i][j] = j * dp[i - 1 ][j] + dp[i - 1 ][j - 1 ];
return dp[n][k];
}
public static void main(String[] args )
{
System.out.println(countP( 5 , 2 ));
}
}
|
Python3
def countP(n, k):
dp = [[ 0 for i in range (k + 1 )]
for j in range (n + 1 )]
for i in range (n + 1 ):
dp[i][ 0 ] = 0
for i in range (k + 1 ):
dp[ 0 ][k] = 0
for i in range ( 1 , n + 1 ):
for j in range ( 1 , k + 1 ):
if (j = = 1 or i = = j):
dp[i][j] = 1
else :
dp[i][j] = (j * dp[i - 1 ][j] +
dp[i - 1 ][j - 1 ])
return dp[n][k]
if __name__ = = '__main__' :
print (countP( 5 , 2 ))
|
C#
using System;
class GFG
{
static int countP( int n, int k)
{
int [,] dp = new int [n + 1, k + 1];
for ( int i = 0; i <= n; i++)
dp[i, 0] = 0;
for ( int i = 0; i <= k; i++)
dp[0, k] = 0;
for ( int i = 1; i <= n; i++)
for ( int j = 1; j <= k; j++)
if (j == 1 || i == j)
dp[i, j] = 1;
else
dp[i, j] = j * dp[i - 1, j] + dp[i - 1, j - 1];
return dp[n, k];
}
public static void Main( )
{
Console.Write(countP(5, 2));
}
}
|
PHP
<?php
function countP( $n , $k )
{
$dp [ $n + 1][ $k + 1] = array ( array ());
for ( $i = 0; $i <= $n ; $i ++)
$dp [ $i ][0] = 0;
for ( $i = 0; $i <= $k ; $i ++)
$dp [0][ $k ] = 0;
for ( $i = 1; $i <= $n ; $i ++)
for ( $j = 1; $j <= $i ; $j ++)
if ( $j == 1 || $i == $j )
$dp [ $i ][ $j ] = 1;
else
$dp [ $i ][ $j ] = $j * $dp [ $i - 1][ $j ] +
$dp [ $i - 1][ $j - 1];
return $dp [ $n ][ $k ];
}
echo countP(5, 2);
?>
|
Javascript
<script>
function countP(n,k)
{
let dp = new Array(n+1);
for (let i = 0; i < n + 1; i++)
{
dp[i] = new Array(k+1);
for (let j = 0; j < k + 1; j++)
{
dp[i][j] = -1;
}
}
for (let i = 0; i <= n; i++)
dp[i][0] = 0;
for (let i = 0; i <= k; i++)
dp[0][k] = 0;
for (let i = 1; i <= n; i++)
for (let j = 1; j <= k; j++)
if (j == 1 || i == j)
dp[i][j] = 1;
else
dp[i][j] = j * dp[i - 1][j] + dp[i - 1][j - 1];
return dp[n][k];
}
document.write(countP(5, 2))
</script>
|
15
- Complexity Analysis:
- Time complexity:O(n*k).
The 2D dp array of size n*k is filled, so the time Complexity is O(n*k). - Space complexity:O(n*k).
An extra 2D DP array is required.
Efficient approach : Space optimization
In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation steps:
- Create a 1D vector dp of size n+1.
- Set a base case dp[0] = 1 .
- Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
- Initialize variable prev and temp used to store the previous values from current computations.
- After every iteration assign the value of temp to prev for further iteration.
- At last return and print the final answer stored in dp[n].
Implementation:
C++
#include<bits/stdc++.h>
using namespace std;
int countP( int n, int k) {
vector< int > dp(n+1, 0);
dp[0] = 1;
for ( int j = 1; j <= k; j++) {
int prev = dp[0];
for ( int i = 1; i <= n; i++) {
int temp = dp[i];
if (j == 1 || i == j) {
dp[i] = 1;
} else {
dp[i] = j * dp[i - 1] + prev;
}
prev = temp;
}
}
return dp[n];
}
int main() {
cout << countP(5, 2);
return 0;
}
|
Output:
15
Time complexity: O(n*k).
Space complexity: O(n).
Similar Article: Bell Numbers
This article is contributed by Rajeev Agrawal. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Please Login to comment...