贪心算法合集

感觉贪心算法很奇怪,完全没有模版套,,,,真是苦了鼠鼠我😭只能把做到的每一题都记下来,有空来看看

455.分发饼干

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        int count = 0;
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        int index = s.size() - 1;//饼干or胃口都行
        for (int i = g.size() - 1; i >= 0; i--){ //先胃口
            if (index >= 0 && g[i] <= s[index]){ //后饼干
                index--;
                count++;
            }
        }
        return count;
    }
};

很简单的一题,有思路就不难写,主要是语法,,,刚学c++好多都不会,知道要干嘛,但是就写不出来,,,,,,代码不能停

376.摆动序列

看到题目的思路:遍历一遍原数组,然后得到差值组成的列表,然后再逐个判断是否一正一负or一负一正(不知道如何实现)
得,题目看错了😅还要删除原数组

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        // 如果数组长度小于2,直接返回长度
        if(nums.size() < 2) return nums.size(); 

        // 定义常量表示三种状态
        const int begin = 0; // 初始状态
        const int up = 1;    // 上升状态
        const int down = 2;  // 下降状态

        // 初始化当前状态为初始状态
        int state = begin;
        
        // 摆动序列的初始长度为1,因为至少包含第一个元素
        int length = 1;

        // 从第二个元素开始遍历数组
        for(int i = 1; i < nums.size(); i++) {
            switch(state) {
                case begin:
                    // 初始状态时,如果当前元素大于前一个元素,状态转为上升,序列长度+1
                    if(nums[i - 1] < nums[i]) {
                        state = up;
                        length++;
                    }
                    // 初始状态时,如果当前元素小于前一个元素,状态转为下降,序列长度+1
                    else if(nums[i - 1] > nums[i]) {
                        state = down;
                        length++;
                    }
                    break;
                case up:
                    // 上升状态时,如果当前元素小于前一个元素,状态转为下降,序列长度+1
                    if(nums[i - 1] > nums[i]) {
                        state = down;
                        length++;
                    }
                    break;
                case down:
                    // 下降状态时,如果当前元素大于前一个元素,状态转为上升,序列长度+1
                    if(nums[i - 1] < nums[i]) {
                        state = up;
                        length++;
                    }
                    break;
            }
        }
        // 返回最长摆动序列的长度
        return length;
    }
};

53.最大子数组和

毫无头绪ing感觉像动规,不像贪心
每个都加一下然后储存起来?然后比较?

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int len = nums.size();
        //dp[i]表示的是以nums[i]为结尾的连续子数组的最大和
        vector<int> dp(len);//初始化一个大小为 len 的 vector叫dp
        int ret;
        dp[0] = nums[0];
        ret = dp[0];
        for (int i = 1; i < len; i++){
            dp[i] = max(dp[i - 1] + nums[i], nums[i]);
            if (dp[i] > ret) ret = dp[i];
        }
        return ret;
    }
};

膜拜大佬,找dp的能力太重要了,可惜我没有,,,,,看了大佬的逻辑以后茅塞顿开。

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

找到前一个最小的,然后用后面的大的减去小的,后面以此类推?感觉有点奇怪,,,

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

k神yyds!想法太精妙了太秀了我哭了😭我怎么就想不到
k:所有上涨交易日都买卖(赚到所有利润),所有下降交易日都不买卖(永不亏钱)。等价于每天都买卖!等价于每天都买卖!等价于每天都买卖!tql!

55.跳跃游戏

原先的思路是检查从后往前能否到达每一个位置,如果遇到0则返回false。,然后一直有样例过不了,硬着头皮改只能从130多到一百五十多,,,后来看了别人题解的思路,自己琢磨着写了这个

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int maxreach = 0;
        for (int i = 0; i < nums.size(); i++){
            if (maxreach < i) return false;
            maxreach = max(maxreach, i + nums[i]);
        }
        if (maxreach >= nums.size() - 1) return true;
        else return false;
    }
};

45.跳跃游戏ll

上一题是判断是否可以到达终点,这一题是要找到跳跃次数最少的是几。

class Solution {
public:
    int jump(vector<int>& nums) {
        int ans = 0;
        int start = 0;
        int end = 1;
        while(end < nums.size()){
            int maxPos = 0;
            for (int i =start; i < end; i++){
                maxPos = max(maxPos, i + nums[i]);
            }
            start = end;
            end = maxPos + 1;
            ans ++;
        }
        return ans;
    }
};

喵啊喵啊!直接上图(来自Ikaruga大佬画的图,简直一目了然)
在这里插入图片描述
马克一下思路

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

想了半天,觉得很多情况很复杂,然后被编程熊大佬秒了,一句话就解释完了所有事情:
情况1,若负数数量大于等于k,则将最小的k个负数变为正数。
情况2,若负数数量小于k,则将所有负数变为正数,之后根据 k 减去负数的数量的剩余值的奇偶性,进一步判断。
若剩余值为偶数,则不用管。
若剩余值为奇数,减去绝对值最小的值。

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        
        int sum = 0, absmin = 10000;
        for(int i = 0; i < nums.size(); i++){
            absmin = min(abs(nums[i]), absmin);
            sum += nums[i];
        }
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size() && k; i++, k--){
            if (nums[i] >= 0) break;
            sum += 2 * abs(nums[i]);
        }
        if (k > 0 && (k & 1)) sum -= 2 * absmin;
        return sum;
    }
};

关于求sum,我自己写的代码是先把数组排序了一下,然后后面发现乱了。编程熊大佬是先求了sum和整个数组中绝对值最小的然后再排序,然后在原sum的基础上进行加减。最后一句更是神,一句话概括了我脑子里乱七八糟分的情况,,,,,

134.加油站

第一反应,遍历,从0开始挨个试,反正结果唯一,但是暴力好像很难写的样子,,,然后看了代码随想录的暴力解法,for和while用的好巧,我不会,,,,

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        for (int i = 0; i < cost.size(); i++) {
            int rest = gas[i] - cost[i]; // 记录剩余油量
            int index = (i + 1) % cost.size();
            while (rest > 0 && index != i) { // 模拟以i为起点行驶一圈(如果有rest==0,那么答案就不唯一了)
                rest += gas[index] - cost[index];
                index = (index + 1) % cost.size();
            }
            // 如果以i为起点跑一圈,剩余油量>=0,返回该起始位置
            if (rest >= 0 && index == i) return i;
        }
        return -1;
    }
};

然后看到一个使用了贪心的,就是在该点油量-消耗若<0,则一定不能从该点开始出发,所以一搜索到<0的(为i)就从i+1开始往后继续找<0的,是为贪心。

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.分发糖果

这题我写过一遍了,但是现在又忘记了。。。大致思路是,先设一个新数组,里面元素都是1,然后从右到左贪心一遍,从左到右贪心一遍,第一遍好像是看大小,逐个+1,第二遍好像是取max啥的,,,

class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> candyVec(ratings.size(), 1);//所有元素初始化为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 < candyVec.size(); i++) result+= candyVec[i];
        return result;
    }
};

记错了,是先从左到右,再从右到左


转行了,不刷题了!神清气爽啊啊啊啊啊
力扣,江湖路远,有缘再会。

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值