一、题目:
一群人做游戏,现在请你根据游戏得分来发糖果,要求如下:
1.每个孩子不管得分多少,起码分到一个糖果。
2.任意两个相邻的孩子之间,得分较多的孩子必须拿多一些的糖果
二、大体思路:
用到了上坡下坡的思想,并且坡顶的值为坡度较高的值
三、具体实现
1、方法一:
· 时间复杂度为O(N),空间复杂度为O(N)
基本思路:第一步从左往右扫描建立从左往右的上坡,第二部从右往左扫描,建立从右往左的上坡(也就是从左往右的下坡)
代码如下:
int Candy1(int arr[], int length)
{
if (arr == NULL || length <= 0)
{
return 0;
}
int* newArray = new int[length]();
for (int i = 0; i < length; ++i)
{
newArray[i] = 1;
}
for (int i = 1; i < length; ++i)
{
if (arr[i] > arr[i - 1])
{
newArray[i] = newArray[i - 1]+1;
}
}
for (int i = length-2; i >= 0; i--)
{
if (arr[i] > arr[i + 1]&&newArray[i]<newArray[i+1]+1)<span style="color:#ff0000;">//注意这里是+1</span> {
newArray[i]=newArray[i+1]+1;
}
}
int res = 0;
for (int i = 0; i < length; ++i)
{
cout << newArray[i] << endl;
res += newArray[i];
}
return res;
}
注意那里的判断条件是+1,假如arr[6]={1,4,5,9,3,2},若不+1,则newArray是[1,2,3,4,1,1],其实为[1,2,3,4,2,1]
启发:本来的值将要得到的值,而不是比肩现有的值,这样不容易出错
2、方法二:
· 时间复杂度为O(N),空间复杂度为O(N),
虽然时间复杂度和空间复杂度都是一样的但是这次的解法比较巧妙,是因为主要的遍历过程,是朝着一个方向遍历的
代码如下:
int Candy1(int arr[], int length)
{
if (arr == NULL || length<=0)
{
return 0;
}
int* newArray = new int[length]();
for (int i = 0; i < length; ++i)
{
newArray[i] = 1;
}
for (int i = 1; i < length; ++i)
{
if (arr[i] == arr[i - 1])
{
newArray[i] = newArray[i];
}
else if (arr[i]>arr[i-1]&&newArray[i]<newArray[i-1]+1)<span style="color:#ff0000;">//注意是+1</span>
{
newArray[i] = newArray[i - 1] + 1;
}
else if (arr[i]<arr[i-1]&&newArray[i]>newArray[i-1]-1)
{
newArray[i-1] = newArray[i-1] + 1;<span style="color:#ff0000;">//最特殊的一个地方,也是核心所在,是因为这里修改的前面的值而不是当前值</span>
if (i > 1)
{
i -= 2;<span style="color:#ff0000;">//巧妙</span>
}
}
}
int res = 0;
for (int i = 0; i < length; ++i)
{
res += newArray[i];
}
return res;
}