题解:小C的糖果分配问题
题目描述
小C有一堆糖果,总共有 n 颗。她需要将糖果分给小朋友们,每个小朋友的糖果数量必须在 l 到 r 之间。小C希望知道在满足条件的前提下:
- 最少可以分给多少个小朋友。
- 最多可以分给多少个小朋友。
- 如果无法正好分完糖果,返回
-1。
解题思路
要解决这个问题,首先我们需要理解 完全分配 和 人数限制 的含义。
- 完全分配:我们要求糖果能够精确地分给若干个小朋友,即每个小朋友获得的糖果数量和为总糖果数
n。 - 人数限制:每个小朋友的糖果数量必须满足在
l到r的范围内。换句话说,对于每个小朋友分配糖果的数量,必须是介于l和r之间的一个整数。
我们希望通过最少和最多的人数来分配糖果,同时保证糖果数能够被完全分配。
核心思路
-
最少人数:为了使分配的人数尽量少,每个小朋友应该分配尽可能多的糖果,即每个人最多分
r个糖果。这样最少的人数min_people就是总糖果数n除以r,然后向上取整。公式为: [ \text{min_people} = \left\lceil \frac{n}{r} \right\rceil ] 其中向上取整可以通过min_people = (n + r - 1) / r来实现。 -
最多人数:为了使分配的人数尽量多,每个小朋友应该分配尽可能少的糖果,即每个人最少分
l个糖果。这样最多的人数max_people就是总糖果数n除以l,然后向下取整。公式为: [ \text{max_people} = \left\lfloor \frac{n}{l} \right\rfloor ] -
检查合理性:首先检查分配是否可能。我们可以用以下两个条件来验证:
- 如果最少的人数
min_people每个人分r个糖果,总糖果数应该不小于n。即:min_people * r >= n。 - 如果最多的人数
max_people每个人分l个糖果,总糖果数应该不大于n。即:max_people * l <= n。
如果以上条件不成立,说明无法正好分配糖果,应返回
-1。 - 如果最少的人数
-
进一步验证:对于从
min_people到max_people之间的每一个人数,检查是否可以用l和r之间的糖果数量恰好分配所有糖果。可以通过以下步骤来进行验证:- 计算
people个小朋友,每个小朋友分配l个糖果后剩余的糖果数remainder = n - people * l。 - 然后,检查剩余的糖果是否能通过给每个小朋友分配多余的糖果(最多每人
r-l个)来完成。即:remainder <= people * (r - l)。
- 计算
代码实现
#include <iostream>
#include <vector>
using namespace std;
vector<int> solution(int n, int l, int r) {
// 计算最少人数和最多人数
int min_people = (n + r - 1) / r; // ceil(n / r)
int max_people = n / l; // floor(n / l)
// 检查人数范围是否合理
if (min_people * r < n || max_people * l > n) {
return {-1};
}
// 校验每个可能人数是否可以正好分配
for (int people = min_people; people <= max_people; ++people) {
int remainder = n - people * l;
if (remainder >= 0 && remainder <= people * (r - l)) {
return {min_people, max_people};
}
}
return {-1};
}
int main() {
int n = 10, l = 2, r = 3;
vector<int> result = solution(n, l, r);
if (result[0] == -1) {
cout << "-1" << endl;
} else {
cout << result[0] << " " << result[1] << endl;
}
return 0;
}
复杂度分析
时间复杂度
- 枚举人数范围 min_people 到 max_people。
- 最多遍历 max_people−min_people+1 次。
- 时间复杂度为 O(n/l)。
空间复杂度
- 仅使用常数空间。
- 空间复杂度为 O(1)。
测试样例
| 输入 | 输出 | 解释 |
|---|---|---|
| n=10,l=2,r=3n = 10, l = 2, r = 3n=10,l=2,r=3 | [4,5][4, 5][4,5] | 可分为 4 人或 5 人,糖果可以正好分配。 |
| n=7,l=3,r=5n = 7, l = 3, r = 5n=7,l=3,r=5 | [2,2][2, 2][2,2] | 只能分为 2 人,每人 3 或 4 个糖果。 |
| n=8,l=1,r=4n = 8, l = 1, r = 4n=8,l=1,r=4 | [2,8][2, 8][2,8] | 可以分给 2 至 8 人,每人 1 至 4 个糖果。 |
| n=6,l=2,r=3n = 6, l = 2, r = 3n=6,l=2,r=3 | [−1][-1][−1] | 无法正好分配糖果,返回 -1。 |
总结
这道题的核心在于:
- 缩小解空间:通过计算最少人数和最多人数快速界定可能范围。
- 校验可行性:验证糖果能否正好分配。
- 时间效率高:算法在合理范围内枚举,能快速得出解答。