题目链接:1005. K 次取反后最大化的数组和
代码
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
int t = 0;
for (int i = 0; i < k && i < nums.size(); i++) {
if (nums[i] >= 0) {
break;
}
if (nums[i] < 0) nums[i] = -nums[i];
t++;
}
k = k - t;
sort(nums.begin(), nums.end());
if (k % 2 != 0 && k > 0) nums[0] = -nums[0];
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
}
return sum;
}
};
思路
先排序,先把最小的负数排序,遇到正数就不反转了,当反转了,后面再排序,反转最小的
题目链接:134. 加油站
暴力
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int size = cost.size();
int flag = -1;
for (int i = 0; i < size; i++) {
int sum = 0;
sum += gas[i] - cost[i];
if (sum < 0) continue;
int j = (i + 1) % size;
int index = i % size;
while (j != index) {
sum += gas[j] - cost[j];
if (sum < 0) break;
j = (j + 1) % size;
}
if (j == index) flag = index;
}
return flag;
}
};
思考
先判断如果当前小于0,就停止,后面不断前进,进到前一个就成功
贪心
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int size = gas.size();
int cursum =0;
int totalsum = 0;
int start = 0;
for (int i = 0; i < size; i++) {
cursum += gas[i] - cost[i];
totalsum += gas[i] - cost[i];
if (cursum < 0) {
start = i + 1;
cursum = 0;
}
}
if (totalsum < 0) return -1;
else return start;
}
};
官方题解
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0;
int totalSum = 0;
int start = 0;
for (int i = 0; i < gas.size(); i++) {
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if (curSum < 0) { // 当前累加rest[i]和 curSum一旦小于0
start = i + 1; // 起始位置更新为i+1
curSum = 0; // curSum从0开始
}
}
if (totalSum < 0) return -1; // 说明怎么走都不可能跑一圈了
return start;
}
};
思路
因为只有一个结果
135. 分发糖果
代码
class Solution {
public:
int candy(vector<int>& ratings) {
int size = ratings.size();
vector<int>result(size, 1);
for (int i = 0; i < size - 1; i++) {
if (ratings[i] < ratings[i + 1]) result[i + 1] = result[i] + 1;
}
for (int i = size - 1; i > 0; i--) {
if (ratings[i - 1] > ratings[i]) result[i - 1] = max(result[i - 1], result[i] + 1);
}
int sum = 0;
for (int i = 0; i < size; i++) {
sum += result[i];
}
return sum;
}
};
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candyVec(ratings.size(), 1);
// 从前向后
for (int i = 1; i < ratings.size(); i++) {
if (ratings[i] > ratings[i - 1]) candyVec[i] = candyVec[i - 1] + 1;
}
// 从后向前
for (int i = ratings.size() - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1] ) {
candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1);
}
}
// 统计结果
int result = 0;
for (int i = 0; i < candyVec.size(); i++) result += candyVec[i];
return result;
}
};
思考
不能看两边,先局部看一边,把一边的东西整好,另一边再整好,相等的因为一开始初始化为1,所以就不用改变。
那么又要贪心了,局部最优:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量既大于左边的也大于右边的。全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。
局部最优可以推出全局最优。
所以就取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,candyVec[i]只有取最大的才能既保持对左边candyVec[i - 1]的糖果多,也比右边candyVec[i + 1]的糖果多。
二刷错误点
1.需要一个新数组来储存结果,在for循环中所用的数组不相同
2.第一次推导一遍可以直接加1,推理另一边时会出现错误
比如最后两个元素,result分别为4和1,所以不能用1+1,需要使用4,所以我们需要比较大小,
result[i] = max(result[i] + 1, result[i - 1]);