LeetCode-1103. Distribute Candies to People(分糖果 II)

分糖果 II

在这里插入图片描述

Distribute Candies to People

在这里插入图片描述

方法一:暴力法
遍历一遍,这里有一点小优化,即假设最后一名正好分完,最后再把多的糖果减去,这样少了一行判断

class Solution {
public:
    vector<int> distributeCandies(int candies, int num_people) {
        int i = 0;
        vector<int>ret(num_people, 0);
        while (candies > 0) {
            ret[i % num_people] += i + 1;
            candies -= i + 1;
            i++;
        }
        ret[(i - 1) % num_people] += candies;

        return ret;
    }
};

方法二:等差数列
除了最后一份以外,其他礼物的数量都是从 1 开始构成的等差数列。
假设有complete份完整礼物,糖果总数量为C
剩余糖果为
r e m a i n i n g = C − ∑ k = 0 c o m p l e t e p = C − ∑ k = 0 c o m p l e t e p ( p − 1 ) 2 remaining=C-\sum_{k=0}^{complete} {p}=C-\sum_{k=0}^{complete}{\frac{p(p-1)}{2}} remaining=Ck=0completep=Ck=0complete2p(p1)
且我们知道
0 ≤ r e m a i n i n g < c o m p l e t e + 1 0 \leq remaining < complete+1 0remaining<complete+1
化简得
2 C + 1 4 − 2 3 < c o m p l e t e ≤ 2 C + 1 4 − 1 2 \sqrt{2C+\frac{1}{4}}-\frac{2}{3} <complete \leq \sqrt{2C+\frac{1}{4}}-\frac{1}{2} 2C+41 32<complete2C+41 21

c o m p l e t e = ⌊ 2 C + 1 4 − 1 2 ⌋ complete=\lfloor \sqrt{2C+\frac{1}{4}}-\frac{1}{2} \rfloor complete=2C+41 21
complete份完整的礼物分发给 N 个人,共可以分发的回合数:rows = complete / N
rows个完整回合中,第 i 个人获得礼物
r e t [ i ] = i + ( i + N ) + ( i + 2 N ) + ( i + ( r o w s − 1 ) N ) = i × r o w s + N r o w s ( r o w s − 1 ) 2 ret[i]=i+(i+N)+(i+2N)+(i+(rows−1)N)=i×rows+N \frac{rows(rows-1)}{2} ret[i]=i+(i+N)+(i+2N)+(i+(rows1)N)=i×rows+N2rows(rows1)
在最后一个回合中,可以计算出收到完整礼物的人数 cols = p % N
他们得到的
r e t [ i ] + = i + N × r o w s ret[i]+=i+N×rows ret[i]+=i+N×rows
最后一名
r e t [ c o l s ] + = r e m a i n i n g ret[cols]+=remaining ret[cols]+=remaining
最后返回ret即可

class Solution {
public:
    vector<int> distributeCandies(int candies, int num_people) {
        vector<int>ret(num_people, 0);
        int complete = (int)(sqrt(2 * candies + 0.25) - 0.5);
        int remaining = (int)(candies - (complete + 1) * complete * 0.5);
        int rows = complete / num_people;
        int cols = complete % num_people;

        for (int i = 0; i < num_people; i++) {
            ret[i] = (i + 1) * rows + (int)(rows * (rows - 1) * 0.5) * num_people;
            if (i < cols) {
                ret[i] += i + 1 + rows * num_people;
            }
        }

        ret[cols] += remaining;

        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值