小C的糖果分配问题 | 豆包MarsCode AI刷题

163 阅读4分钟

题解:小C的糖果分配问题

题目描述

小C有一堆糖果,总共有 n 颗。她需要将糖果分给小朋友们,每个小朋友的糖果数量必须在 lr 之间。小C希望知道在满足条件的前提下:

  1. 最少可以分给多少个小朋友。
  2. 最多可以分给多少个小朋友。
  3. 如果无法正好分完糖果,返回 -1

解题思路

要解决这个问题,首先我们需要理解 完全分配人数限制 的含义。

  1. 完全分配:我们要求糖果能够精确地分给若干个小朋友,即每个小朋友获得的糖果数量和为总糖果数 n
  2. 人数限制:每个小朋友的糖果数量必须满足在 lr 的范围内。换句话说,对于每个小朋友分配糖果的数量,必须是介于 lr 之间的一个整数。

我们希望通过最少和最多的人数来分配糖果,同时保证糖果数能够被完全分配。

核心思路

  1. 最少人数:为了使分配的人数尽量少,每个小朋友应该分配尽可能多的糖果,即每个人最多分 r 个糖果。这样最少的人数 min_people 就是总糖果数 n 除以 r,然后向上取整。公式为: [ \text{min_people} = \left\lceil \frac{n}{r} \right\rceil ] 其中向上取整可以通过 min_people = (n + r - 1) / r 来实现。

  2. 最多人数:为了使分配的人数尽量多,每个小朋友应该分配尽可能少的糖果,即每个人最少分 l 个糖果。这样最多的人数 max_people 就是总糖果数 n 除以 l,然后向下取整。公式为: [ \text{max_people} = \left\lfloor \frac{n}{l} \right\rfloor ]

  3. 检查合理性:首先检查分配是否可能。我们可以用以下两个条件来验证:

    • 如果最少的人数 min_people 每个人分 r 个糖果,总糖果数应该不小于 n。即:min_people * r >= n
    • 如果最多的人数 max_people 每个人分 l 个糖果,总糖果数应该不大于 n。即:max_people * l <= n

    如果以上条件不成立,说明无法正好分配糖果,应返回 -1

  4. 进一步验证:对于从 min_peoplemax_people 之间的每一个人数,检查是否可以用 lr 之间的糖果数量恰好分配所有糖果。可以通过以下步骤来进行验证:

    • 计算 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

总结

这道题的核心在于:

  1. 缩小解空间:通过计算最少人数和最多人数快速界定可能范围。
  2. 校验可行性:验证糖果能否正好分配。
  3. 时间效率高:算法在合理范围内枚举,能快速得出解答。