leetcode
leetcode 2501 ~ 2550
给小朋友们分糖果 II

给小朋友们分糖果 II

难度:

标签:

题目描述

You are given two positive integers n and limit.

Return the total number of ways to distribute n candies among 3 children such that no child gets more than limit candies.

 

Example 1:

Input: n = 5, limit = 2
Output: 3
Explanation: There are 3 ways to distribute 5 candies such that no child gets more than 2 candies: (1, 2, 2), (2, 1, 2) and (2, 2, 1).

Example 2:

Input: n = 3, limit = 3
Output: 10
Explanation: There are 10 ways to distribute 3 candies such that no child gets more than 3 candies: (0, 0, 3), (0, 1, 2), (0, 2, 1), (0, 3, 0), (1, 0, 2), (1, 1, 1), (1, 2, 0), (2, 0, 1), (2, 1, 0) and (3, 0, 0).

 

Constraints:

  • 1 <= n <= 106
  • 1 <= limit <= 106

代码结果

运行时间: 28 ms, 内存: 16.7 MB


/*
 * 思路:
 * 使用 Java Stream API,我们可以通过流的方式处理糖果的分配。利用 IntStream 来枚举每位小朋友分到的糖果数,
 * 并通过过滤条件筛选出符合要求的组合。最后通过计数来获取满足条件的总方案数。
 */

import java.util.stream.IntStream;

public class Solution {
    public long countWays(int n, int limit) {
        return IntStream.rangeClosed(0, Math.min(limit, n)).boxed()
            .flatMap(i -> IntStream.rangeClosed(0, Math.min(limit, n - i)).boxed()
            .filter(j -> n - i - j >= 0 && n - i - j <= limit)
            .map(j -> new int[]{i, j, n - i - j}))
            .count();
    }
}

解释

方法:

这个题解使用了容斥原理来计算分配糖果的总方案数。首先定义一个辅助函数 c2(n),它计算从 n 个不同元素中选择 2 个元素的组合数,即 n * (n - 1) / 2。对于给定的 n 和 limit,我们可以将问题转化为计算总方案数,然后减去不合法的方案数(即某个小朋友得到的糖果数超过 limit)。具体来说,总方案数为从 n + 2 个不同元素中选择 2 个元素的组合数(相当于给每位小朋友分配 0 到 n 颗糖果,再减去两个额外的'边界'元素)。不合法的方案数可以通过容斥原理计算,即减去每位小朋友得到超过 limit 颗糖果的方案数,加上每两位小朋友都得到超过 limit 颗糖果的方案数,再减去所有三位小朋友都得到超过 limit 颗糖果的方案数。

时间复杂度:

O(1)

空间复杂度:

O(1)

代码细节讲解

🦆
在题解中,如何确保减去的不合法方案确实包含了所有超过limit的情况?
在题解中,使用了容斥原理来确保考虑了所有不合法的方案。首先,我们计算每个小朋友得到超过 limit 颗糖果的情况,这是通过 `c2(n - limit + 1)` 计算,代表从 n - limit + 1 个糖果中选择 2 个糖果的组合数,相当于每个小朋友至少得到 limit + 1 颗糖果的情况。然后,通过容斥原理,我们加上了两位小朋友同时得到超过 limit 颗糖果的方案数,再减去三位小朋友都得到超过 limit 颗糖果的方案数,以此类推。这种方法能够确保所有组合的不合法情况被精确地计算和考虑。
🦆
函数c2(n)在n <= 1时返回0,这是否正确处理了所有情况,例如当n为负数时?
函数 c2(n) 在 n <= 1 时返回 0 是基于组合数学的原理,即从 n 个元素中选择 2 个元素的组合数。当 n 小于 2 时,无法选出 2 个元素,因此返回 0 是合理的。对于 n 为负数的情况,根据组合数学的定义,负数个元素中选择两个元素是没有意义的,因此返回 0 依然是合理且正确的处理方法。
🦆
为什么在计算总方案数时使用了`c2(n + 2)`,这里的'+2'是如何得出的?
在计算总方案数时使用 `c2(n + 2)` 是为了模拟 '边界元素' 的概念。在给小朋友分糖果时,我们可以考虑每个小朋友分到的糖果数为从 0 到 n 之间的任意数。这里的 '+2' 代表两个虚拟的或边界元素,这样做可以帮助我们处理边界情况,确保每位小朋友分到的糖果数在正确的范围内。它实际上是在数轴上添加两个额外点来帮助计算从 0 到 n 颗糖果的分配方式。

相关问题