day 33 是休息日
#1005 K次取反后最大化的数组和, easy 5min
其实做有些贪心的题完全没想着贪心,完全按常识做的。注意:把负数和0反转完之后,剩的k是偶数就完全不用管了(转两次等于没做),是奇数的话就把k当还剩1次就行
int largestSumAfterKNegations(vector& nums, int k) {
sort(nums.begin(),nums.end());
for(int i=0;i0;i++){
k--;
nums[i]*=-1;
}
sort(nums.begin(),nums.end());
if(k>0 && k%2!=0) nums[0]=-1*nums[0];
int sum=0;
for(int &ele:nums) sum+=ele;
return sum;
}
随想录思路有点不同,但我感觉这题不重要,没看。先粘上来:
static bool cmp(int a, int b) {
return abs(a) > abs(b);
}
public:
int largestSumAfterKNegations(vector& A, int K) {
sort(A.begin(), A.end(), cmp); // 第一步
for (int i = 0; i < A.size(); i++) { // 第二步
if (A[i] < 0 && K > 0) {
A[i] *= -1;
K--;
}
}
if (K % 2 == 1) A[A.size() - 1] *= -1; // 第三步
int result = 0;
for (int a : A) result += a; // 第四步
return result;
}
#134 加油站 M
我服了我自己,这道题总共花了两个多小时。几个原因吧:我非觉得我的思路没问题(是仿照前面一道题 算累加和如果为负数,就放弃前面的,从下一个当新起点开始),这个思路确实大体是对的,但是还需要再巧妙一点。另外就是我觉得确实是leetcode编译器出了点问题,但是后来又莫名其妙好了
下面的截图记录一下发生的奇怪事情:
“那你觉得我的逻辑对吗” “ 你的代码逻辑基本上是正确的。你在循环中从每个站点开始尝试,每次都尝试到下一个站点,如果油量不足,则从下一个站点重新开始”
总之,学到的是,当出现非常反常,难以理解跑出来的效果时,可以合理怀疑是编译器的问题,可以换一个编译器比如online c++ compiler 试一试,或者刷新一下页面,等一会再尝试,不要连续猛烈地死磕。
另外还想说,我觉得自己有点太固执了,每次都想证明自己的思路是行得通的,于是花非常多时间去调整修改code。做为1刷真的非常没有必要,浪费很多时间,这一点一定要改掉。
----- ------- ------ ----- ------ ----- 分割线:下面正经讲这道题 ------ ------ ------ ----- ----- ------ ----- ----- --
我的思路确实大体正确,但实现不够巧妙,而且写出来代码看一看就会发现是worst case 是O n^2 ,这和直接暴力两层for loop效率差不多( 两层这个过不了 TLE)。下面是我的没通过的代码和没通过的case:
int canCompleteCircuit(vector& gas, vector& cost) {
int sum=0;
int cnt=0;
int i=0;
bool finish=false;
while(cnt
下面是随想录思路思路自己又写了一遍code,巧妙之处是一直维持了一个totalsum,一直都可以用,比如我们走到倒数第二个发现不行,准备从倒数第一个再开始,这时不用重新计算,因为这是最后一次机会了,看total如果再<0,就根本走不完一圈了
你看这清爽的逻辑和代码,本来是30min就能ac+博客全弄完的
int canCompleteCircuit(vector& gas, vector& cost) {
int totalsum=0;
int cursum=0;
int start=0;
for(int i=0;i
随想录还有另外一种巧妙的方法,我还没太理解,先放在这:
int canCompleteCircuit(vector& gas, vector& cost) {
int curSum = 0;
int min = INT_MAX; // 从起点出发,油箱里的油量最小值
for (int i = 0; i < gas.size(); i++) {
int rest = gas[i] - cost[i];
curSum += rest;
if (curSum < min) {
min = curSum;
}
}
if (curSum < 0) return -1; // 情况1
if (min >= 0) return 0; // 情况2
// 情况3
for (int i = gas.size() - 1; i >= 0; i--) {
int rest = gas[i] - cost[i];
min += rest;
if (min >= 0) {
return i;
}
}
return -1;
}
#135 分发糖果 Hard, 关键:如果在考虑局部的时候想两边兼顾,就会顾此失彼
自己没想出来。随想录思路:
1.每个和左边的/前面的邻居比
从左向右:我比前面大吗,大就=前面+1
2.每个和右边/后面的邻居比
从右向左:我比后面大吗,大就!!!取max(后面+1,已经更新过的前面+1)
就是比左右邻居都大的话,要选择左右邻居里面数值大的那个+1
这里一定要从后往前遍历!因为既然是和后面的比,在后一个元素值基础上更新,那就要把后面的值先算出来
vector初始化要记得会写:vector
int candy(vector& ratings) {
vector 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 res = 0;
for (auto &ele:candyVec) res+=ele;
return res;
}