Count number of ways to partition a set into k subsets - GeeksforGeeks

13 Apr, 2021
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).
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).
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 recuried parameter and calculate the value of S(n, k).Return the sum.
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 recuried parameter and calculate the value of S(n, k).Return the sum.
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 recuried parameter and calculate the value of S(n, k).
Return the sum.
Implementation:
C++
Java
Python 3
C#
PHP
Javascript
// A C++ program to count number of partitions// of a set with n elements into k subsets#include<iostream>using namespace std; // Returns count of different partitions of n// elements in k subsetsint countP(int n, int k){  // Base cases  if (n == 0 || k == 0 || k > n)     return 0;  if (k == 1 || k == n)      return 1;   // S(n+1, k) = k*S(n, k) + S(n, k-1)  return  k*countP(n-1, k) + countP(n-1, k-1);} // Driver programint main(){   cout <<  countP(3, 2);   return 0;}
// Java  program to count number// of partitions of a set with// n elements into k subsetsimport java.io.*; class GFG{    // Returns count of different    // partitions of n elements in    // k subsets    public static int countP(int n, int k)    {       // Base cases       if (n == 0 || k == 0 || k > n)          return 0;       if (k == 1 || k == n)          return 1;        // S(n+1, k) = k*S(n, k) + S(n, k-1)       return (k * countP(n - 1, k)              + countP(n - 1, k - 1));    }     // Driver program    public static void main(String args[])    {       System.out.println(countP(3, 2));     }} //This code is contributed by Anshika Goyal.
# A Python3 program to count number# of partitions of a set with n# elements into k subsets # Returns count of different partitions# of n elements in k subsetsdef countP(n, k):         # Base cases    if (n == 0 or k == 0 or k > n):        return 0    if (k == 1 or k == n):        return 1         # S(n+1, k) = k*S(n, k) + S(n, k-1)    return (k * countP(n - 1, k) +                countP(n - 1, k - 1)) # Driver Codeif __name__ == "__main__":    print(countP(3, 2)) # This code is contributed# by Akanksha Rai(Abby_akku)
// C# program to count number// of partitions of a set with// n elements into k subsetsusing System; class GFG {         // Returns count of different    // partitions of n elements in    // k subsets    public static int countP(int n, int k)    {                 // Base cases        if (n == 0 || k == 0 || k > n)            return 0;        if (k == 1 || k == n)            return 1;             // S(n+1, k) = k*S(n, k) + S(n, k-1)        return (k * countP(n - 1, k)                + countP(n - 1, k - 1));    }     // Driver program    public static void Main()    {        Console.WriteLine(countP(3, 2));    }} // This code is contributed by anuj_67.
<?php// A PHP program to count// number of partitions of// a set with n elements// into k subsets // Returns count of different// partitions of n elements// in k subsetsfunction countP($n, $k){    // Base cases    if ($n == 0 || $k == 0 || $k > $n)        return 0;    if ($k == 1 || $k == $n)        return 1;         // S(n+1, k) = k*S(n, k)    // + S(n, k-1)    return $k * countP($n - 1, $k) +            countP($n - 1, $k - 1);}     // Driver Code    echo countP(3, 2); // This code is contributed by aj_36?>
<script>// Javascript  program to count number// of partitions of a set with// n elements into k subsets         // Returns count of different    // partitions of n elements in    // k subsets    function countP(n, k)    {             // Base cases       if (n == 0 || k == 0 || k > n)          return 0;       if (k == 1 || k == n)          return 1;         // S(n + 1, k) = k*S(n, k) + S(n, k - 1)       return (k * countP(n - 1, k)              + countP(n - 1, k - 1));    }         // Driver program    document.write(countP(3, 2));         // This code is contributed by avanitrachhadiya2155   </script>
Output:
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).  
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).  
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.
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.
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] = 0Run 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]
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] = 0Run 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]
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++
Java
Python3
C#
PHP
Javascript
// A Dynamic Programming based C++ program to count// number of partitions of a set with n elements// into k subsets#include<iostream>using namespace std; // Returns count of different partitions of n// elements in k subsetsint countP(int n, int k){  // Table to store results of subproblems  int dp[n+1][k+1];   // Base cases  for (int i = 0; i <= n; i++)     dp[i][0] = 0;  for (int i = 0; i <= k; i++)     dp[0][k] = 0;   // Fill rest of the entries in dp[][]  // in bottom up manner  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];} // Driver programint main(){   cout <<  countP(5, 2);   return 0;}
// A Dynamic Programming based Java program to count// number of partitions of a set with n elements// into k subsetsclass GFG{ // Returns count of different partitions of n// elements in k subsetsstatic int countP(int n, int k){    // Table to store results of subproblems    int[][] dp = new int[n+1][k+1];         // Base cases    for (int i = 0; i <= n; i++)    dp[i][0] = 0;    for (int i = 0; i <= k; i++)    dp[0][k] = 0;         // Fill rest of the entries in dp[][]    // in bottom up manner    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];     } // Driver programpublic static void main(String[] args ){    System.out.println(countP(5, 2));}} // This code is contributed by Rajput-Ji
# A Dynamic Programming based Python3 program# to count number of partitions of a set with# n elements into k subsets # Returns count of different partitions# of n elements in k subsetsdef countP(n, k):         # Table to store results of subproblems    dp = [[0 for i in range(k + 1)]             for j in range(n + 1)]     # Base cases    for i in range(n + 1):        dp[i][0] = 0     for i in range(k + 1):        dp[0][k] = 0     # Fill rest of the entries in    # dp[][] in bottom up manner    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] # Driver Codeif __name__ == '__main__':    print(countP(5, 2)) # This code is contributed by# Surendra_Gangwar
// A Dynamic Programming based C# program // to count number of partitions of a // set with n elements into k subsetsusing System; class GFG{ // Returns count of different partitions of n// elements in k subsetsstatic int countP(int n, int k){    // Table to store results of subproblems    int[,] dp = new int[n + 1, k + 1];         // Base cases    for (int i = 0; i <= n; i++)        dp[i, 0] = 0;    for (int i = 0; i <= k; i++)        dp[0, k] = 0;         // Fill rest of the entries in dp[][]    // in bottom up manner    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];     } // Driver codepublic static void Main( ){    Console.Write(countP(5, 2));}} // This code is contributed by Ita_c.
<?php// A Dynamic Programming based PHP// program to count number of// partitions of a set with n // elements into k subsets // Returns count of different// partitions of n elements in// k subsetsfunction countP($n, $k){     // Table to store results// of subproblems$dp[$n + 1][$k + 1] = array(array()); // Base casesfor ($i = 0; $i <= $n; $i++)    $dp[$i][0] = 0;for ($i = 0; $i <= $k; $i++)    $dp[0][$k] = 0; // Fill rest of the entries in// dp[][] in bottom up mannerfor ($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];} // Driver Codeecho countP(5, 2); // This code is contributed by jit_t?>
<script>// A Dynamic Programming based Javascript program to count// number of partitions of a set with n elements// into k subsets         // Returns count of different partitions of n    // elements in k subsets    function countP(n,k)    {        // Table to store results of subproblems        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;            }        }                           // Base cases        for (let i = 0; i <= n; i++)            dp[i][0] = 0;        for (let i = 0; i <= k; i++)            dp[0][k] = 0;                  // Fill rest of the entries in dp[][]        // in bottom up manner        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];    }         // Driver program    document.write(countP(5, 2))         // This code is contributed by rag2127</script>
Output:
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.
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.
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.
jit_t
vt_m
Akanksha_Rai
Rajput-Ji
ukasp
SURENDRA_GANGWAR
andrew1234
almasashruffkhan
satyampd5340
avanitrachhadiya2155
rag2127
Modular Arithmetic
Dynamic Programming
Recursion
Dynamic Programming
Recursion
Modular Arithmetic
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Matrix Chain Multiplication | DP-8
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Sieve of Eratosthenes
Write a program to print all permutations of a given string
Given an array A[] and a number x, check for pair in A[] with sum as x (aka Two Sum)
Program for Tower of Hanoi
Recursion
Program for Sum of the digits of a given number