代码随想录算法训练营第34天 | 贪心算法 part03● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果

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编译器出了点问题,但是后来又莫名其妙好了

下面的截图记录一下发生的奇怪事情:

代码随想录算法训练营第34天 | 贪心算法 part03● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果_第1张图片 “那你觉得我的逻辑对吗” “ 你的代码逻辑基本上是正确的。你在循环中从每个站点开始尝试,每次都尝试到下一个站点,如果油量不足,则从下一个站点重新开始” 

代码随想录算法训练营第34天 | 贪心算法 part03● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果_第2张图片

总之,学到的是,当出现非常反常,难以理解跑出来的效果时,可以合理怀疑是编译器的问题,可以换一个编译器比如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

代码随想录算法训练营第34天 | 贪心算法 part03● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果_第3张图片代码随想录算法训练营第34天 | 贪心算法 part03● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果_第4张图片

 下面是随想录思路思路自己又写了一遍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

随想录还有另外一种巧妙的方法,我还没太理解,先放在这:

代码随想录算法训练营第34天 | 贪心算法 part03● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果_第5张图片

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

这里一定要从后往前遍历!因为既然是和后面的比,在后一个元素值基础上更新,那就要把后面的值先算出来

代码随想录算法训练营第34天 | 贪心算法 part03● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果_第6张图片

 vector初始化要记得会写:vector vec(size, value );

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;
    }

你可能感兴趣的:(代码随想录一刷,算法,贪心算法,数据结构)