Count number of ways to partition a set into k subsets

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.
    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)
    2. 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)
    3. Total count = k * S(n-1, k) + S(n-1, k-1).

    S(n, k) is called Stirling numbers of the second kind

  • Algorithm:
    1. Create a recursive function which accepts two parameters, n and k. The function returns total number of partitions of n elements into k sets.
    2. 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.
    3. 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).
    4. Return the sum.
  • Implementation:

    C++

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // 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 subsets
    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
    int main()
    {
       cout <<  countP(3, 2);
       return 0;
    }

    chevron_right

    
    

    Java

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Java  program to count number 
    // of partitions of a set with 
    // n elements into k subsets
    import 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.

    chevron_right

    
    

    Python 3

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    # 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 subsets
    def 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 Code
    if __name__ == "__main__":
        print(countP(3, 2))
      
    # This code is contributed 
    # by Akanksha Rai(Abby_akku)

    chevron_right

    
    

    C#

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // C# program to count number 
    // of partitions of a set with 
    // n elements into k subsets
    using 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.

    chevron_right

    
    

    PHP

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    <?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 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 Code
        echo countP(3, 2);
      
    // This code is contributed by aj_36
    ?>

    chevron_right

    
    

    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(1).
      no extra space is required.

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:

    1. 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.
    2. 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:
    1. Create a Dp array dp[n+1][k+1] of size ( n + 1 )* ( k + 1 ) .
    2. 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
    3. Run a nested loop, the outer loop from 1 to n and inner loop from 1 to j.
    4. 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.
    5. Print values dp[n][k]
  • Implementation:

    C++

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // 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 subsets
    int 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 program
    int main()
    {
       cout <<  countP(5, 2);
       return 0;
    }

    chevron_right

    
    

    Java

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // A Dynamic Programming based Java program to count 
    // number of partitions of a set with n elements 
    // into k subsets 
    class GFG{
      
    // Returns count of different partitions of n 
    // elements in k subsets 
    static 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 program 
    public static void main(String[] args ) 
        System.out.println(countP(5, 2)); 
    }
      
    // This code is contributed by Rajput-Ji

    chevron_right

    
    

    Python3

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    # 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 subsets
    def 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 Code
    if __name__ == '__main__':
        print(countP(5, 2))
      
    # This code is contributed by
    # Surendra_Gangwar

    chevron_right

    
    

    C#

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // A Dynamic Programming based C# program  
    // to count number of partitions of a  
    // set with n elements into k subsets 
    using System;
      
    class GFG
    {
      
    // Returns count of different partitions of n 
    // elements in k subsets 
    static 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 code 
    public static void Main( ) 
        Console.Write(countP(5, 2)); 
    }
      
    // This code is contributed by Ita_c.

    chevron_right

    
    

    PHP

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    <?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 subsets 
    function countP($n, $k
          
    // Table to store results 
    // of subproblems 
    $dp[$n + 1][$k + 1] = array(array()); 
      
    // Base cases 
    for ($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 manner 
    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]; 
      
    // Driver Code
    echo countP(5, 2); 
      
    // This code is contributed by jit_t
    ?>

    chevron_right

    
    

    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.

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.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up