Leetcode 1692. Count Ways to Distribute Candies

Problem Explanation:

Given n unique candies and k bags, the problem asks to distribute all the candies into the bags such that every bag has at least one candy. However, the way those candies are put inside the bags will matter. So the task is to find the number of different ways to distribute the candies. The output will be returned modulo 10^9 + 7 due to the large possibilities.

For example,

If n=3(candies) and k=2(bags), the number of different possible ways will be 3. The possibilities are:

  • bag1: {candy1}, bag2: {candy2, candy3}
  • bag1: {candy1, candy2}, bag2: {candy3}
  • bag1: {candy1, candy3}, bag2: {candy2}

Solution Approach:

The problem can be solved using dynamic programming. A two-dimensional array dp[i][j] is used, where i represents the number of candies and j represents the number of bags. dp[i][j] will store the number of ways to distribute the candies. The base cases are dp[i][i] = 1 because there is only one way to distribute i candies into i bags, and that is one candy per bag.

To compute other dp[i][j] values, dp[i][j] will be the sum of dp[i - 1][j - 1] + (dp[i - 1][j] * j) with modulus 10^9 + 7 applied, where:

  • dp[i - 1][j - 1] represents the case where the new candy occupies a new bag.
  • dp[i - 1][j] * j represents the case where the new candy can be put in any of the j bags.

The final answer will be the value at dp[n][k].

Python Solution:

1
2python
3class Solution:
4    def waysToDistribute(self, n: int, k: int) -> int:
5        mod = 10**9 + 7
6        dp = [[0] * (k + 1)] * (n + 1)
7        for i in range(k):
8            dp[i][i]=1
9        for i in range(1,n+1):
10            for j in range(1,k+1):
11                dp[i][j] = (dp[i-1][j-1] + dp[i-1][j] * j) % mod
12        return dp[n][k]

Java Solution:

1
2java
3class Solution {
4    public int waysToDistribute(int n, int k) {
5        long[][] dp = new long[n + 1][k + 1]; 
6        int mod = 1000000007; 
7        for(int i = 0; i <= k; i++) 
8            dp[i][i]=1;
9        for(int i = 1; i <=n; ++i)
10            for(int j = 1; j <=k; ++j)
11                dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j] * j) % mod;
12        return (int)dp[n][k];
13    }
14}

Javascript Solution:

1
2javascript
3class Solution {
4    waysToDistribute(n, k) { 
5        let dp = Array.from(Array(n + 1), () => new Array(k + 1));
6        let modulo = 1000000007;
7        for (let i = 0; i <= k; i++) 
8            dp[i][i] = 1;
9        for (let i = 1; i <= n; i++) 
10            for (let j = 1; j <= k; j++)
11                dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j] * j) % modulo;
12        return dp[n][k];
13    }
14}

C++ Solution:

1
2cpp
3class Solution {
4public:
5    int waysToDistribute(int n, int k) {
6        vector<vector<long long>> dp(n+1, vector<long long>(k+1, 0));
7        int modulo = pow(10, 9)+7;
8        for(int i=0; i<=k; i++)
9            dp[i][i]=1;
10        for(int i=1; i<=n; i++)
11            for(int j=1; j<=k; j++)
12                dp[i][j] = (dp[i-1][j-1] + dp[i-1][j]*j) % modulo;
13        return dp[n][k];
14    }
15};

C# Solution:

1
2csharp
3public class Solution {
4    public int WaysToDistribute(int n, int k) {
5        long[][] dp = new long[n + 1][];
6        for (int i = 0; i < n+1; i++)
7            dp[i] = new long[k+1]; 
8        int mod = 1000000007;
9        for(int i = 0; i <= k; i++) 
10            dp[i][i]=1;
11        for(int i = 1; i <=n; ++i)
12            for(int j = 1; j <=k; ++j)
13                dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j] * j) % mod;
14        return (int)dp[n][k];
15    }
16}

In all the solutions above, the dynamic programming approach is used to solve the problem as explained in the approach section. For the range of 1 to n, it goes over the range of 1 to k inside it and updates dp[i][j] according to the formula mentioned above. The response is then returned from dp[n][k].With both the problem and solution being discussed along with specific language implementations provided, it is evident that each language offers a similar approach to solving the problem using Dynamic Programming. The time complexity for all these solutions is O(n*k) because we have two nested loops running until n and k.

Some languages like Python and JavaScript are preferred for their clear syntax and dynamic typing which makes them easier to write and understand. Others like Java and C# might seem verbose, but they provide strong type checking which helps catch mistakes earlier and allows IDEs to provide better auto-completion and refactoring support. C++ is fast, which makes it suitable for solving complex problems where performance is critical.

Therefore, the choice of the language to solve this problem largely depends on the programmers' preferences, the requirements of the system, and the specific use case at hand.

In conclusion, the way to distribute candies into bags in distinctive orders can be solved using dynamic programming by creating a 2D array where each cell denotes a subproblem of the general problem. Using the base case and transition function given in the problem, we iterate through the 2D array to obtain the final number of distributions possible. This is a typical dynamic programming problem which requires a fair understanding of DP concept and its implementation. These skills are highly useful while preparing for coding interviews or competitive programming.


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫