【LeetCode】1103分糖果Ⅱ

问题

排排坐,分糖果。

我们买了一些糖果 candies,打算把它们分给排好队的 n = num_people 个小朋友。

给第一个小朋友 1 颗糖果,第二个小朋友 2 颗,依此类推,直到给最后一个小朋友 n 颗糖果。

然后,我们再回到队伍的起点,给第一个小朋友 n + 1 颗糖果,第二个小朋友 n + 2 颗,依此类推,直到给最后一个小朋友 2 * n 颗糖果。

重复上述过程(每次都比上一次多给出一颗糖果,当到达队伍终点后再次从队伍起点开始),直到我们分完所有的糖果。注意,就算我们手中的剩下糖果数不够(不比前一次发出的糖果多),这些糖果也会全部发给当前的小朋友。

返回一个长度为 num_people、元素之和为 candies 的数组,以表示糖果的最终分发情况(即 ans[i] 表示第 i 个小朋友分到的糖果数)。

思想:

1、先计算出循环的次数times(将小朋友得到的糖果数量视为等差数列1,2…,n,n+1,n+2…),low为下界,high为上界。

low = (1+(times-1)*num_people)*(times-1)*num_people;
high = (1+times*num_people)*times*num_people;

2、如果恰好能走完完整的循环,调用add函数。这里不必每次根据times计算数组,因为相邻位置总是相差times,所以计算出result[0]即可。

public int[] add(int times , int num_people) { //完整
    int[] result = new int[num_people];
    result[0] = times+times*(times-1)/2*num_people;
    for(int i=1 ; i<num_people ; i++) {
        result[i]=result[i-1]+times;
    }
    return result;
}

3、如果存在某一趟不能完整走完糖果就分完了,就计算剩下的糖果数量。

public int getRemain(int[] res , int candies) {
    int remain = candies;
    for(int i=0 ; i<res.length ; i++) {
        remain = remain-res[i];
    }
    return remain;
}

然后将剩下的糖果按顺序分,此时一趟之内肯定能分完。

public int[] addRemain(int[] res , int remain ,int times) {
    int cut = 0;
    for(int i=1 ; i<res.length ; i++) {
        cut = (times-1)*res.length+i;
        if(cut<remain) {
            remain = remain-cut;
            res[i-1]+=cut;
        } else {
            res[i-1]+=remain;
            remain = 0;
        }
        if(remain==0) {
            break;
        }
    }
    return res;
}

完整代码:

class Solution {
    public int[] distributeCandies(int candies, int num_people) {
        int times = 0; //循环次数
        int low = 0;
        int high = 0;
        int compare = 2*candies;
        int[] result = new int[num_people];
        boolean flag = false;
        while(true) {
            times++;
            low = (1+(times-1)*num_people)*times*num_people;//必定整除
            high = (1+times*num_people)*(times+1)*num_people;
            if(low==compare) {  //完整的
                flag = true;
                break;
            }
            if(high>compare&&low<compare) { //不能完整的
                break;
            }
        }
        if(times==1) {
            return this.addRemain(result,candies,1);
        }
        if(flag==true) {
            result = this.add(times,num_people);
        } else {
            result = this.add(times-1,num_people);
            int remain = this.getRemain(result,candies);
            result = this.addRemain(result,remain,times);
        }
        return result;
    }

    public int[] add(int times , int num_people) { //完整
        int[] result = new int[num_people];
        result[0] = times+times*(times-1)/2*num_people;
        for(int i=1 ; i<=num_people ; i++) {
            result[i]=result[i-1]+times;
        }
        return result;
    }

    public int getRemain(int[] res , int candies) {
        int remain = candies;
        for(int i=0 ; i<res.length ; i++) {
            remain = remain-res[i];
        }
        return remain;
    }

    public int[] addRemain(int[] res , int remain ,int times) {
        int cut = 0;
        for(int i=1 ; i<res.length ; i++) {
            cut = (times-1)*res.length+i;
            if(cut<remain) {
                remain = remain-cut;
                res[i-1]+=cut;
            } else {
                res[i-1]+=remain;
                remain = 0;
            }
            if(remain==0) {
                break;
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值