您的位置:首页 > 其它

leetcode candy分糖果问题 两次遍历和一次遍历

2017-12-18 22:51 369 查看
here are N children standing in a line. Each child is assigned a rating value.

You are giving candies to these children subjected to the following requirements:

Each child must have at least one candy.

Children with a higher rating get more candies than their neighbors.

What is the minimum candies you must give?

就是有一群小孩(数组),数组中每个值代表一个等级,每个小孩必须有一颗糖,相邻的两个小孩中等级高的比等级低的糖多,求如何使得分出去的糖果最少

数组rating :2,4,3,2

分糖果:1,3,2,1

两次遍历:

先从头开始,后面大的比前面多一个

public int candy(int[] ratings) {
int size = ratings.length;
if (size == 0) return -1;
if (size == 1) return 1;

int[] cans = new int[size];
cans[0] = 1;
//正向扫描一遍,如果右边的rating比左边高,那么右边的糖果数就比左边多一个,否则只给一个糖果
for (int i = 1; i < size; i++) {
if (ratings[i] > ratings[i - 1]) cans[i] = cans[i - 1] + 1;
else cans[i] = 1;
}
//反向扫描一遍,如果左边的rating比右边高,并且左边的糖果数比右边少,那么左边的糖果数应比右边多一
for (int i = size - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1] && cans[i] <= cans[i + 1]) {
cans[i] = cans[i + 1] + 1;
}
}

int ret = 0;  //实际上这里可以把ret在上面一个循环中加,减少一次循环,不过本文主要是来实现一次循环,这个简单,大家都会
for (int i = 0; i < size; i++) {
ret += cans[i];
}

return ret;
}


一次遍历:利用等差数列

public int candy(int[] ratings) {
if (ratings == null || ratings.length == 0) return 0;
int total = 1, prev = 1, countDown = 0;
for (int i = 1; i < ratings.length; i++)
{
if (ratings[i] >= ratings[i-1])
{
if (countDown > 0)
{
total += countDown*(countDown+1)/2; // 1+2+3+4=(1+4)*4/2
if (countDown >= prev) total += countDown - prev + 1;//如果,连续的等级下降的孩子个数,大于这个下降孩子序列之前的那个孩子的分的糖果数,需要对那个孩子,再加糖果
countDown = 0;
prev = 1;
}
prev = ratings[i] == ratings[i-1] ? 1 : prev+1;//比较当前i位置处值和前面的i-1处,是否相等,不等,则需要比i-1处多一个糖果
total += prev;
}
else countDown++;
}
if (countDown > 0) { // if we were descending at the end
total += countDown*(countDown+1)/2;
if (countDown >= prev) total += countDown - prev + 1;
}
return total;
}


prev表示的是孩子分的糖果,不断更行。countDown表示的是右边孩子的等级比左边低的孩子个数。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode 遍历 candy
相关文章推荐