day34
1005.K次取反后最大化的数组和
题目链接:1005. K 次取反后最大化的数组和
第一步:将数组按照绝对值大小从大到小排序
第二步:从前向后遍历,遇到负数变为正数,同时k–;
第三步:如果k还大于0,反复转变数值最小的元素,将K用完
第四步:求和
// 注意比较函数写法
class Solution {
static bool cmp(int a, int b){
return abs(a) > abs(b);
}
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
int result = 0;
sort(nums.begin(),nums.end(),cmp); //第一步
// 第二步
for( int i = 0; i < nums.size(); i++){
if( nums[i] < 0 && k > 0){
nums[i] *= -1;
k--;
}
}
if( k%2 == 1) nums[nums.size()-1] *= -1; //第三步
for( int i = 0; i < nums.size(); i++){ // 第四步
result += nums[i];
}
return result;
}
};
134.加油站
题目链接:134. 加油站
如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。
每个加油站的剩余量rest[i]为gas[i] - cost[i]。
那么局部最优:当前累加rest[i]的和curSum一旦小于0,起始位置至少要是i+1,因为从i之前开始一定不行。全局最优:找到可以跑一圈的起始位置。
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 ){
cursum = 0;
start = i + 1;
}
}
if( totalsum < 0) return -1;
return start;
}
};
135.分发糖果
题目链接:135. 分发糖果
1.先从前向后遍历,如果右边大于左边就加1
2.从后向前遍历,如果左边大于右边就加1
- 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
- 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
这样从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candy( ratings.size(),1); //初始每个人都有糖果
// 从左向右遍历
for( int i = 1; i < ratings.size(); i++){
if( ratings[i - 1] < ratings[i]){
candy[i] = candy[i-1] + 1;
}
}
// 从右向左
for( int i = ratings.size()-2; i >=0; i--){
if( ratings[i] > ratings[i+1]){
candy[i] = max( candy[i] , candy[i+1] + 1);
}
}
int result = 0;
for( int i = 0; i < candy.size(); i++){
result += candy[i];
}
return result;
}
};