代码随想录一刷打卡——贪心(上篇)

文章目录

  • 前言
  • 一、455. 分发饼干
  • 二、376. 摆动序列
  • 三、53. 最大子数组和
  • 四、122. 买卖股票的最佳时机 II
  • 五、55. 跳跃游戏
  • 六、45. 跳跃游戏 II
  • 七、1005. K 次取反后最大化的数组和
  • 八、1402. 做菜顺序
  • 九、134. 加油站
  • 十、135. 分发糖果
  • 总结


前言

一个本硕双非的小菜鸡,备战24年秋招,计划刷完卡子哥的刷题计划,加油!
推荐一手卡子哥的刷题网站,感谢卡子哥。代码随想录

贪心:通过局部最优,推出整体最优。

一、455. 分发饼干

455. 分发饼干

Note:贪心第一题,思路很简单。但是要注意if循环先判断sSize >= 0,要不然会内存泄漏。


class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());

        int gSize = g.size() - 1;
        int sSize = s.size() - 1;
        int result = 0;

        for (int i = gSize; i >= 0; i--) {
            if (sSize >= 0 && g[i] <= s[sSize]) {
                result++;
                sSize--;
            }
        }
        return result;
    }
};

二、376. 摆动序列

376. 摆动序列

Note:这道题跟我之前周赛的题目有点像,可惜当时没做出来

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if (nums.size() <= 1) return nums.size();

        int curDiff = 0; //当前差值
        int preDiff = 0; //前一对差值
        int result = 1;

        for (int i = 0; i < nums.size() - 1; i++) {
            curDiff = nums[i + 1] - nums[i];

            if ((preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)) {
                result++;
                preDiff = curDiff;
            }
        }
        return result;
    }
};

三、53. 最大子数组和

53. 最大子数组和

Note:不难,我感觉我好像做过类似的


class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int res = INT32_MIN;
        int count = 0;

        for (int i = 0; i < nums.size(); i++) {
            count += nums[i];
            if (count > res)
                res = count;
            if (count <= 0)
                count = 0;
        }
        return res;
    }
};

四、122. 买卖股票的最佳时机 II

122. 买卖股票的最佳时机 II

Note:…原来做过类似的是这道题


class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int res = 0;
        for (int i = 1; i < prices.size(); i++) {
            if (prices[i] - prices[i - 1] > 0)
                res += prices[i] - prices[i - 1];
        }
        return res;
    }
};

五、55. 跳跃游戏

55. 跳跃游戏

Note:贪心想法很简单,是我想麻烦了


class Solution {
public:
    bool canJump(vector<int>& nums) {
        int cover = 0;

        if (nums.size() == 1) return true;

        for (int i = 0; i <= cover; i++) {
            cover = max(cover, i + nums[i]);
            if (cover >= nums.size() - 1) return true;
        }
        return false;
    }
};

六、45. 跳跃游戏 II

45. 跳跃游戏 II

Note:我真想到强化就是找最短路径


class Solution {
public:
    int jump(vector<int>& nums) {
        if (nums.size() == 1) return 0;
        int curDistance = 0; //当前最远可到达的位置
        int res = 0;
        int nextDistance = 0; //下一步最远可到达的位置

        for (int i = 0; i < nums.size(); i++) {
            nextDistance = max(nums[i] + i, nextDistance);
            if (i == curDistance) {
                res++;
                curDistance = nextDistance;
                if (nextDistance >= nums.size() - 1) break;
            }
        }
        return res;
    }
};

七、1005. K 次取反后最大化的数组和

1005. K 次取反后最大化的数组和

Note:思路很好想,先排序再顺序翻转的负数


class Solution {
static bool cmp(int a, int b) {
    return abs(a) > abs(b);
}
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        int res = 0;
        sort(nums.begin(), nums.end(), cmp);

        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] < 0 && k > 0) {
                nums[i] = abs(nums[i]);
                k--;
            }
        }
        if (k % 2 == 1) nums[nums.size() - 1] *= -1;
        for (int a : nums) res += a;
        return res;
    }
};

八、1402. 做菜顺序

78. 子集

Note:并不是代码随想录中的一题,是每日一题遇到的。贪心算法帮助我搞定了第一道困难。
此处采用了题解中Ikaruga大佬的优化解答
思路
1.贪心
2.越往后乘积越大,越大的数应该放在最后,所以先排个序
3.从后面一个一个加入,每新加一个数,之前加过的所有数都会多加一遍(点睛之笔!)

class Solution {
public:
    int maxSatisfaction(vector<int>& satisfaction) {
        sort(satisfaction.rbegin(), satisfaction.rend());
        int ans = 0;
        int res = 0;

        for (int i = 0; i < satisfaction.size(); i++) {
            ans += satisfaction[i];
            if (ans < 0) break;
            res += ans;
        }
        return res;
    }
};

九、134. 加油站

134. 加油站

Note:总油量减去总消耗大于等于零那么一定可以跑完一圈


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) {
                start = i + 1;
                curSum = 0;
            }
        }
        if (totalSum < 0) return -1;
        return start;
    }
};

十、135. 分发糖果

135. 分发糖果

Note:很有意思的题,掌握贪心思想这题不难


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 res = 0;
        for (int i = 0; i < candyVec.size(); i++)
            res += candyVec[i];
        return res;
    }
};

总结

因为贪心题比较多,就分上下两篇记录了。
贪心没有固定的套路,只要能通过局部最优推导出全局最优就可以尝试贪心了。
贪心更多的是思想与解题技巧。

你可能感兴趣的:(代码随想录刷刷刷,学习,leetcode,c++,程序人生)