局部最优是将绝对值最小的数进行反转,然后将所有的数加起来
那么本题的解题步骤为:
- 第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
- 第二步:从前向后遍历,遇到负数将其变为正数,同时K--
- 第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
- 第四步:求和
#define abs(a) (((a) > 0) ? (a) : (-(a)))
int sum(int *nums, int numsSize) {
int sum = 0;
int i;
for(i = 0; i < numsSize; ++i) {
sum += nums[i];
}
return sum;
}
int cmp(const void* v1, const void* v2) {
return abs(*(int*)v2) - abs(*(int*)v1);
}
int largestSumAfterKNegations(int* nums, int numsSize, int k){
qsort(nums, numsSize, sizeof(int), cmp);
int i;
for(i = 0; i < numsSize; ++i) {
if(nums[i] < 0 && k > 0) {
nums[i] *= -1;
--k;
}
}
if(k % 2 == 1)
nums[numsSize - 1] *= -1;
return sum(nums, numsSize);
}
当前累加rest[i]的和curSum一旦小于0,起始位置至少要是i+1,因为从i之前开始一定不行。全局最优:找到可以跑一圈的起始位置。
int canCompleteCircuit(int* gas, int gasSize, int* cost, int costSize) {
int curSum = 0;
int totalSum = 0;
int start = 0;
int i;
for(i = 0; i < gasSize; ++i){
int diff = gas[i] - cost[i];
curSum += diff;
totalSum += diff;
if(curSum < 0){
curSum = 0;
start = i + 1;
}
}
if(totalSum < 0)
return -1;
return start;
}
思路:左右两边不可以一起讨论,
有两种情况
1,右孩子比左孩子大——从前向后遍历
2,左孩子比右孩子大——从后向前遍历
——为什么要从后向前遍历?
因为题目要求,评分高的要比评分低的糖果要多,实际模拟过后,如果从前往后的话,会出现错误
#define max(a, b) (a > b ? a : b);
int *initCandyArr(int size) {
int *candyArr = (int*)malloc(sizeof(int) * size);
int i;
for(i = 0; i < size; ++i)
candyArr[i] = 1;
return candyArr;
}
int candy(int* ratings, int ratingsSize) {
int* candyArr = initCandyArr(ratingsSize);
int i;
for(i = 1; i < ratingsSize; ++i){
if(ratings[i] > ratings[i - 1])
candyArr[i] = candyArr[i - 1] + 1;
}
for(i = ratingsSize - 2; i >= 0; --i){
if(ratings[i] > ratings[i + 1])
candyArr[i] = max(candyArr[i], candyArr[i + 1] + 1);
}
int result = 0;
for(i = 0; i < ratingsSize; ++i){
result += candyArr[i];
}
return result;
}