分苹果问题最easy题解:最大化小明所得苹果数的策略(云智春招笔试、b站春招笔试)

分苹果问题最easy题解:最大化小明所得苹果数的策略(云智春招笔试、b站春招笔试)

题目描述

有 m 个苹果和 n 个小孩,每个小孩有一个编号,小明的编号是 k。要求分配苹果时满足以下条件:

  1. 每个小孩至少分到 1 个苹果。
  2. 相邻编号的小孩分到的苹果数目差距不能超过 1。
  3. 在满足上述条件的情况下,小明分到的苹果数目要尽可能多。

求小明能分到的苹果的最大值。

解题思路

我们需要在保证相邻苹果数差不超过 1 的前提下,使小明分到的苹果最多。关键思路是以小明为中心,逐层向外扩展,每次尽可能多地分配苹果,直到苹果不足为止。

为什么选择逐层扩展?
  • 由于相邻苹果数差不能超过 1,小明的位置若分到最多苹果,周围小孩的苹果数只能比小明少 1 或相等。
  • 为了最大化小明的苹果数,我们每次尝试给小明所在的层增加一个苹果,并扩展相邻层,确保不违反相邻差的条件。

算法流程

  1. 初始化:每个小孩先分 1 个苹果,保证最小值。此时已用掉 n 个苹果,剩余 m-n 个苹果用于后续分配。
  2. 逐层扩展:以小明为中心,每次向外扩展一层,给该层所有小孩各加 1 个苹果。
    • 第 1 层:仅小明自己,加 1 个苹果。
    • 第 2 层:扩展到小明左右相邻的小孩。
    • 后续每层继续向外扩展,直到苹果不够分配。
  3. 终止条件:当剩余苹果不足以分配当前层所需时停止,此时小明的苹果数即为最大值。

代码解析

static long dfs(int n, int m, int k) {
    k = k - 1; // 转为从0开始的索引
    long ans = 2; // 初始层数为2,表示小明至少分到2个苹果(后续会调整)
    long need = n; // 初始需要n个苹果(每个小孩1个)
    int l = 0, r = 0; // 当前层的左右边界
    
    while (true) {
        if (ans == 2) {
            // 第一层仅小明自己
            l = k;
            r = k;
        } else {
            // 向外扩展一层
            l = Math.max(0, l - 1);
            r = Math.min(n - 1, r + 1);
        }
        // 当前层需要增加的苹果数
        need += r - l + 1;
        if (need > m) {
            break;
        }
        ans++; // 进入下一层
    }
    return ans - 1; // 最终层数减1为小明的苹果数
}
  • 变量说明
    • lr 表示当前层的左右边界。
    • need 记录已分配的苹果总数。
    • ans 表示当前层数,每增加一层,小明的苹果数加 1。
  • 关键逻辑
    • 初始层(ans=2)仅给小明加 1 个苹果。
    • 后续每层扩展左右边界,计算需要新增的苹果数。
    • 当总苹果数超过 m 时终止,返回 ans-1 作为小明的最大值。

复杂度分析

  • 时间复杂度:O(t),其中 t 为扩展的层数。每次扩展的层数所需苹果数递增,最坏情况下 t 约为 O(√m)。
  • 空间复杂度:O(1),仅需常数空间。

示例分析

假设 n=5(5个小孩),m=15(15个苹果),小明编号 k=3(转为索引 2)。

  1. 初始分配:每个小孩 1 个苹果,已用 5 个,剩余 10 个。
  2. 逐层扩展
    • 第 1 层(ans=2):仅索引 2 加 1 个,总苹果 6。
    • 第 2 层(ans=3):扩展至索引 1-3,加 3 个,总 9。
    • 第 3 层(ans=4):扩展至索引 0-4,加 5 个,总 14。
    • 第 4 层(ans=5):需要加 5 个,总 19 > 15,终止。
  3. 结果:返回 ans-1=4,小明最多分到 4 个苹果。

总结

通过逐层扩展的策略,我们能够高效地找到小明能分到的最大苹果数,同时确保相邻小孩的苹果数差不超过 1。该算法的时间复杂度较低,适用于较大规模的数据。

特别提醒

在两个ans解之间的苹果数都是合理的,假设刚刚好ans为x时苹果数为20,x+1时苹果数为30,那么20到30之间都是合理的,假设取25,那么可以从底部开始往上分,可以保证符合规则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值