这一题思路还是比较容易想出来的,从数组中绝对值大的负数开始变,直到k=0;如果k没用完就变数组中最小点数
class Solution {
public:
static bool cmp(int a, int b) {
return abs(a) > abs(b); //abs求整型数据的绝对值
}
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(), nums.end(), cmp); //按 绝对值 从大到小 排序,确保先改变绝对值大的负数
for (int i = 0; i < nums.size(); i++) { //从前向后遍历
if (nums[i] < 0 && k>0) { //遇到负数就将其变为正数、k-1
nums[i] = -nums[i];
k--;
}
}
while (k > 0) {
nums[nums.size() - 1] *= -1; //遍历完数组k仍大于0,那么翻转数值最小的元素直到k为0
k--;
}
//if(k %2 ==1) nums[nums.size() - 1] *= -1; k取模2余1(k为奇数),相当于要对数值最小的元素进行奇数次修改;如果k取模2余0,相当于对一个数进行偶数次修改,等价于不修改
int result = 0;
for (int a : nums) result += a; //求和
return result;
}
};
从头开始遍历每个加油站,看最后能够返回。
for循环适合模拟从头到尾的遍历,而while循环适合模拟环形遍历
class Solution {
public:
int canCompleteCirecuit(vector<int>& gas, vector<int>& cost) {
for (int i = 0; i < cost.size(); i++) { //遍历加油站,以每一个加油站为起点
int rest = gas[i] - cost[i]; //剩余油量
int next = (i + 1) % cost.size(); //(i+1)
while (rest > 0 && next != i) { //以i加油站为起点行驶一圈
rest += gas[next] - cost[next]; //累计剩余油量
next = (next + 1) % cost.size(); //更新下一站位置
}
if (rest >= 0 && next == i) return i; //行驶一圈后剩余油量>=0说明能环绕一周,返回加油站编号
}
return -1;
}
};
暴力解法的缺点就是进行了很多重复计算
如果 总油量减去总消耗大于零,那么就一定存在一个加油站可以跑完一圈;
此外,如果某个区间的剩余总油量小于零,那肯定起点肯定不会在这个区间
class Solution {
public:
int canCompleteCirecuit(vector<int>& gas, vector<int>& cost) {
int currest = 0;
int totalrest = 0; //剩余总油量
int start = 0; //开始位置
for (int i = 0; i < gas.size(); i++) {
currest += gas[i] - cost[i];
totalrest += gas[i] - cost[i];
if (currest < 0) { //[0,i]的总油量小于零,那肯定起点肯定不会在这个区间
start = i + 1; //更新起点
currest = 0; //当前区间总油量
}
}
if (totalrest < 0) return -1; //剩余总油量小于0,那么从哪都不能行驶一圈
return start;
}
};
相邻的孩子中,评分高的孩子必须获得更多的糖果 可以拆分成:
左规则:当ratings[i-1] < ratings[i]时,i号学生的糖果数比i-1号孩子的糖果数多。
右规则:当ratings[i]>ratings[i+1]时,i号学生的糖果数比i+1号孩子的糖果数多。
在相邻的学生中,评分高的孩子必须获得更多的糖果等价于 必须同时满足左右规则。
局部最优:取candyvec[i + 1] + 1 和 candyvec[i] 最大的糖果数量,保证第i个小孩的糖果数量即大于左边的也大于右边的;
全局最优:相邻的孩子中,评分高的孩子获得更多的糖果
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 < ratings.size(); i++) result += candyvec[i];
return result;
}
};
收钱时有三种情况:(1)顾客支付五美元,直接收下;(2)顾客支付十美元,找五美元;(3)顾客支付二十美元,找一张五美元和十美元、或找三张五美元
这里有用到贪心,就是支付二十美元时,优先找零一张五美元和一张十美元
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int five = 0, ten = 0, twenty = 0;
//for (int i = 0; i < bills.size(); i++) 用bills[i]判断
for (int bill : bills) {
if (bill == 5) five++; //五美元,直接收下
if (bill == 10) { //十美元
if (five <= 0) return false; //如果没有五美元就寄
ten++; //如果有五美元就找零
five--;
}
if (bill == 20) { //二十美元
if (five > 0 && ten > 0) { //有十美元和五美元就找零
five--;
ten--;
twenty++;
}
else if (five >= 3) { //没有十美元的话如果有三张五美元也行
five -= 3;
twenty++;
}
else return false;
}
}
return true;
}
};
和135题类似,同样是有两个规则:
规则1:按身高h从高到低排序,身高相同则k小的在前面
规则2:排序后按k为下标重新插入队列
class Solution {
public:
static bool cmp(const vector<int>& a, const vector<int>& b) { //身高从大到小排(身高相同k小的站前面)
if (a[0] == b[0]) return a[1] < b[1];
return a[0] > b[0];
}
vector<vector<int>> reconstructQurue(vector<vector<int>>& people) {
sort(people.begin(), people.end(), cmp);
vector<vector<int>> que;
for (int i = 0; i < people.size(); i++) {
int position = people[i][1]; //插入到下标为position的位置
que.insert(que.begin() + position, people[i]);
}
return que;
}
};