Open In App

Count number of ways to partition a set into k subsets

Improve
Improve
Like Article
Like
Save
Share
Report

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).
  • 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 required parameter and calculate the value of S(n, k).
    4. Return the sum.
  • Implementation:

C++




// 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;
}


Java




// 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.


Python 3




# 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)


C#




// 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.


Javascript




<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>


PHP




<?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
?>


  • 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), 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: 
    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 k.
    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++




// 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;
}


Java




// A Dynamic Programming based Java program to count
// number of partitions of a set with n elements
// into k subsets
import java.util.*;
import java.io.*;
 
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


Python3




# 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


C#




// 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.


Javascript




<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>


PHP




<?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
?>


  • 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.

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++




//c++ code for above approach
#include<bits/stdc++.h>
using namespace std;
 
// Returns count of different partitions of n
// elements in k subsets
int countP(int n, int k) {
    // Vector to store results of subproblems
    vector<int> dp(n+1, 0);
 
    // Base cases
    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 finala answer
    return dp[n];
}
 
// Driver program
int main() {
    cout << countP(5, 2);
    return 0;
}


Java




public class Main {
    // Function to count different partitions of n elements
    // in k subsets
    static int countPartitions(int n, int k)
    {
        // Create an array to store results of subproblems
        int[] dp = new int[n + 1];
 
        // Base cases
        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 the final answer
        return dp[n];
    }
 
    // Driver program
    public static void main(String[] args)
    {
        int n = 5;
        int k = 2;
        System.out.println("Number of partitions: "
                           + countPartitions(n, k));
    }
}


Python3




def countP(n, k):
    # List to store results of subproblems
    dp = [0] * (n + 1)
 
    # Base cases
    dp[0] = 1
 
    for j in range(1, k + 1):
        prev = dp[0]
        for i in range(1, n + 1):
            temp = dp[i]
            if j == 1 or i == j:
                dp[i] = 1
            else:
                dp[i] = j * dp[i - 1] + prev
            prev = temp
 
    # Return the final answer
    return dp[n]
 
# Driver program
if __name__ == "__main__":
    print(countP(5, 2))


C#




// c# code for above approach
using System;
 
class GFG
{
    // Returns count of different partitions of n
    // elements in k subsets
    static int CountP(int n, int k)
    {
        // store results of subproblems
        int[] dp = new int[n + 1];
        // Base cases
        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
                {
                    // Otherwise, calculate the number of partitions using the recurrence relation:
                    // dp[i] = j * dp[i - 1] + prev
                    dp[i] = j * dp[i - 1] + prev;
                }
                prev = temp;
            }
        }
        // The final answer is stored in dp[n]
        return dp[n];
    }
    static void Main()
    {
        // Test the function with n=5 and k=2
        int n = 5;
        int k = 2;
        int result = CountP(n, k);
        Console.WriteLine(result);
    }
}


Javascript




function GFG(n, k) {
    // Array to store results of
    // subproblems
    const dp = new Array(n + 1).fill(0);
    // Base cases
    dp[0] = 1;
    for (let j = 1; j <= k; j++) {
        let prev = dp[0];
        for (let i = 1; i <= n; i++) {
            const temp = dp[i];
            if (j === 1 || i === j) {
                dp[i] = 1;
            } else {
                dp[i] = j * dp[i - 1] + prev;
            }
            prev = temp;
        }
    }
    // Return the final answer
    return dp[n];
}
// Driver program
console.log(GFG(5, 2));


Output:

15

Time complexity: O(n*k). 
Space complexity: O(n). 
 

Similar Article: Bell Numbers 



Last Updated : 15 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads