LeetCode- algorithm - points candy

Stay button topic Address: https://leetcode-cn.com/problems/distribute-candies-to-people/

First look at the subject :
Cruncher, sub-candy.

We bought some candy candies, they are going to give queued n = num_people two children.

A child to the first confectionery, the second two children, and so on, until the last child to n pieces of candy.

Then, we go back to the starting point of the team, to the first pieces of candy children n + 1, n + 2 second child stars, and so on, until the last child to 2 * n pieces of candy.

Repeat the process (and more each time than the last given a candy, when the team arrived at the end from the beginning starting point for the team again) until we finish all the sub-candy. Note that even if the rest is not in our hands the number of candy (candy before issuing more than once), these candies will be distributed to all current children.

Returns an array of NUM_PEOPLE length, and for the elements of the candies to represent the case of candies final distribution (i.e. ANS [i] represents the number of i-th candy assigned to children).

Example :

示例一:
输入:candies = 7, num_people = 4
输出:[1,2,3,1]
解释:
第一次,ans[0] += 1,数组变为 [1,0,0,0]。
第二次,ans[1] += 2,数组变为 [1,2,0,0]。
第三次,ans[2] += 3,数组变为 [1,2,3,0]。
第四次,ans[3] += 1(因为此时只剩下 1 颗糖果),最终数组变为 [1,2,3,1]。

示例二:
输入:candies = 10, num_people = 3
输出:[5,2,3]
解释:
第一次,ans[0] += 1,数组变为 [1,0,0]。
第二次,ans[1] += 2,数组变为 [1,2,0]。
第三次,ans[2] += 3,数组变为 [1,2,3]。
第四次,ans[0] += 4,最终数组变为 [5,2,3]
提示:

1 <= candies <= 10^9
1 <= num_people <= 1000

Solutions :
This question is the solution people think of first is the brute force method to estimate the. Calculating a candy with constant number of array elements required if the current is greater than required number of remaining tree candy candy, candy required allocated, if not the whole portion of a current element; and then returns an array.

I personally do not think this brute force, so there is no use of this approach, trying to find a solution to save time by some rules.

That is why this blog was only released today; next to you talk about my show operation.

Start solving our journey:
I probably thinking is this. First, I know the number of elements in the total number of candies and sweets array num_people.
The first step : Because of candy each element are assigned increasing; how much candy sum so I can cycle through num_people need to know every altogether. We compare the size of the sum and candies, to calculate how many times the current cycle.
Step Two : Then subtract the total number of candy cycle to the current cycle of our total some candy, calculates the difference value, and then the last one is derived from the reverse Wang Qianmian current cycle to calculate the finished candy element position end_index.
The third step : after calculating end_index, we know that the other elements are less than end_index sum count + 1 cycle, the first element is the sum end_index cycle count of the remaining number plus the candy, the element is greater than the other elements are end_index is the sum of the first count cycle.

The first step in code implementation:

第一次循环分配糖果总和:从 1 到 num_people  
递增正整数列求和公式:sum = (1+n)n/2;

循环示例:
第一次循环:1 到 num_people  
int sum1 = (1+num_people)*num_people/2;
第二次循环:num_people+12*num_people 
int sum2 = (1+3*num_people)*num_people/2;
第三次循环:2*num_people+13*num_people 
int sum3 = (1+5*num_people)*num_people/2;
第四次循环:3*num_people+14*num_people 
int sum4 = (1+7*num_people)*num_people/2;
总结规律:
完成第 count 次循环所需糖果数量总和:
(1+(2*count-1)*num_people)*num_people/2

代码实现:
	//知道了规律我们接下来就可以计算 循环次数
	//完成循环次数;从0开始,因为不知道第一次循环的糖果是否能分配完
	int count = 0;
	//计算完成第一次循环需要的糖果数量
	int sum = (1+num_people)*num_people/2;
	//算出循环次数  判断总糖果数量是否大于循环增加的糖果数量总和
	while (candies > sum){
	    //循环次数加一
	    count++;
		//计算出下次循环所需要的糖果数 并加入sum
	    sum += (1+(2*(count+1)-1)*num_people)*num_people/2;
	}

The second step code implementation:

1.注意count是完成循环的次数,并不是循环到的次数,所以我们能够循环到第count+1次循环。
2.计算出 candies 数量的糖果能够循环到第 count + 1次之后。
3.我们接下来要考虑的是我们如何定位到 count+1 次循环时,糖果分配完的那个元素位置。
4.首先利用上面计算循环次数的sum和糖果总数candies,计算出完成第count+1次循环所差的糖果值。

反向推导示例:
第 count 次循环最后 1 位所需糖果数:
int sub1 = count*num_people-0;
第 count 次循环倒数第 2 位所需糖果数:
int sub2 = count*num_people-1;
第 count 次循环倒数第 3 位所需糖果数:
int sub3 = count*num_people-2;
第 count 次循环倒数第 4 位所需糖果数:
int sub4 = count*num_people-3;
总结规律:
倒数第 sub_count 位所需要的糖果数:
count*num_people-sub_count 

代码实现:
	//计算差值
	int sub = sum - candies;
	//反向推导次数
    int sub_count = 0;
    //反向推导:倒数第一个位置所需要的糖果数量
    int sub_now = (count+1)*num_people-sub_count;
    //当剩余糖果数量小于下一个位置所需的糖果数量,说明剩余糖果不够分配给下一个位置了。
    while(sub >= sub_now){
    	//下一个位置所需的糖果数量
        sub_now = (count+1)*num_people-sub_count;
        //剩余糖果数量减去当前位置所需糖果数量;
        sub -= sub_now;
        //完成反向推导次数+1
        sub_count++;
    }
    //计算出下一个位置需要的糖果数
    sub_now = (count+1)*num_people-sub_count;
    //计算出下一个位置剩余的糖果数
    sub = sub_now - sub;
    //循环到糖果不足的位置
    int end_index = num_people - sub_count;

The third step code implementation:

1.计算 end_index 之后;小于 end_index 的其他元素都是count+1次循环的总和。
2.第 end_index 元素是第count次循环的总和加上剩余糖果数量。
3.大于 end_index 元素的其他元素都是第 count 次循环的总和。

元素总和计算示例:
//计算每一位元素需要的值,并放入
第一次循环第一个元素所需糖果数总和:
int number1_1 = 1;
int number1_2 = 2+num_people;(1+1+num_people)
int number1_3 = 3+3*num_people;(1 + 1+num_people + 1+2*num_people)
int number1_4 = 4+6*num_people;
int number1_5 = 5+10*num_people;
int number1_6 = 6+15*num_people;
int number1_7 = 7+21*num_people;
int number1_8 = 8+28*num_people;
第二次循环第一个元素所需糖果数总和:
int number2_1 = 2;
int number2_2 = 4+num_people;
第三次循环第一个元素所需糖果数总和:
int number3_1 = 3;
int number3_2 = 6+num_people;
总结规律:
x 等于从 1 到 count 的和,递增正整数列求和公式:
x = (1+count)*count/2
第 count 次循环 第 i 个位置所需糖果总数:
count*(i+1) + x * num_people

代码实现:
		//计算x的值
        int x = count*(count+1)/2;
        //循环设置值
        for(int i = 0; i < num_people; i++) {
            if(i < end_index-1){
            	//1.小于 end_index 的其他元素都是count+1次循环的总和。
                result[i] = (count+1)*(i+1) + x * num_people;
            }else if(i == end_index-1){
            	//2.第 end_index 元素是第count次循环的总和加上剩余糖果数量。
                result[i] = count*(i+1) +(x-count) * num_people + sub;
            }else{
            	//3.大于 end_index 元素的其他元素都是第 count 次循环的总和。
                result[i] = count*(i+1) +(x-count) * num_people;
            }
        }

Complete code:

/**
     * 分糖果   https://leetcode-cn.com/problems/distribute-candies-to-people/
     * @param candies
     * @param num_people
     * @author GeYuxuan 2020-03-06 22:18:03
     * @return int[]
     */
    public int[] distributeCandies(int candies, int num_people) {
        int [] result = new int[num_people];
        //循环次数
        int count = 0;
        int sum = (1+num_people)*num_people/2;
        //算出循环次数
        while (candies > sum){
            //循环次数加一
            count++;
            //计算出下次循环所需要的糖果数 并加入sum
            sum += (1+(2*(count+1)-1)*num_people)*num_people/2;
        }
        //计算差值
        int sub = sum - candies;
        int sub_count = 0;
        int sub_now = (count+1)*num_people-sub_count;
        while(sub >= sub_now){
            sub_now = (count+1)*num_people-sub_count;
            sub -= sub_now;
            sub_count++;
        }
        sub_now = (count+1)*num_people-sub_count;
        sub = sub_now - sub;
        //循环到余额不足的位置
        int end_index = num_people - sub_count;
        //计算count总和
        int x = count*(count+1)/2;
        //计算每一位需要的值,并放入
        for(int i = 0; i < num_people; i++) {
            if(i < end_index-1){
                result[i] = (count+1)*(i+1) + x * num_people;
            }else if(i == end_index-1){
                result[i] = count*(i+1) +(x-count) * num_people + sub;
            }else{
                result[i] = count*(i+1) +(x-count) * num_people;
            }
        }
        return result;
    }

This blog is the article No. 5 March should be issued, but the three hours that night did not head out the problem, in fact, I have thought of giving up in the middle of such a solution, but I did not want to understand where my solution problem. Because the next day to go to work, in order not to affect the work, which I intend to question again the next day free solution. Until the time when the next night to solve this question, I am very excited; I think the violence will always be a last resort solution, only the mindless will let his mind be flexible.

He did not forget the early heart, temper forward.

Published 25 original articles · won praise 4 · Views 5738

Guess you like

Origin blog.csdn.net/we_tian/article/details/104721505