LeetCode刷题笔记【23】:贪心算法专题-1(分发饼干、摆动序列、最大子序和)

文章目录

前置知识

贪心算法的本质

贪心的本质是选择每一阶段的局部最优,从而达到全局最优。

例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿?

指定每次拿最大的,最终结果就是拿走最大数额的钱。

每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。

什么时候用贪心算法?

  1. 感觉像是可以用贪心
  2. 用题中的案例试一下, 发现没问题
  3. 尝试举一下反例, 发现没问题
  4. 那就可以用了

所以贪心算法并没有固定的规律和套路, 也不会要求你论证背后算法的合理性和有效性, 只要能解决问题, 通过测试案例即可.

ps:个人认为贪心非常虚无缥缈呀, 还是动态规划更加有迹可循;

并且在实践过程中, 可以用贪心算法的, 基本都可以用动态规划.

什么时候不能用贪心?

当局部最优, 不一定可以达到全局最优的时候, 如:

有一堆盒子,你有一个背包体积为n,如何把背包尽可能装;

如果还每次选最大的盒子,就不行了。

这时候就需要动态规划。

贪心算法的解题步骤

  1. 将问题分解为若干个子问题
  2. 找出适合的贪心策略
  3. 求解每一个子问题的最优解
  4. 将局部最优解堆叠成全局最优解

这样的叙述非常抽象, 实践过程中还是要把握思想: 选择每一阶段的局部最优,从而达到全局最优

参考文章:关于贪心算法, 你该了解这些

455.分发饼干

题目描述

LeetCode链接:https://leetcode.cn/problems/assign-cookies/description/

解题思路

思路: 先将两个数组都srot

遍历g数组, 优先满足胃口最小的孩子

遍历g数组中的元素gg的时候, 依次遍历s数组, 选择能满足gg的最小尺寸饼干

代码

cpp 复制代码
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        int ans=0;
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int ss=0;
        for(int gg : g){
            for(; ss<s.size(); ++ss){
                if(s[ss] >= gg){
                    s[ss] = 0;
                    ans++;
                    break;
                }
            }
        }
        return ans;
    }
};

376. 摆动序列

题目描述

LeetCode链接:https://leetcode.cn/problems/wiggle-subsequence/description/

解题思路

<代>: 其实过程中不需要对数组进行操作, 只需要看有多少个点是符合要求的即可;

具体过程比较复杂, 建议参考其原文.

代码

cpp 复制代码
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n=nums.size();
        if(n==0 || n==1 || (n==2 && nums[0]!=nums[1]))
            return n;
        int curDiff = 0;
        int preDiff = 0;
        int ans=1;
        for(int i=0; i<n-1; ++i){
            curDiff = nums[i+1] - nums[i];
            if((preDiff<=0 && curDiff>0) || (preDiff>=0 && curDiff<0)){
                ans++;
                preDiff = curDiff;
            }
        }
        return ans;
    }
};

53. 最大子序和

题目描述

LeetCode链接:https://leetcode.cn/problems/maximum-subarray/description/

暴力解法

思路: 暴力解法

对数组中每个数, 都依次向后遍历所有子数组, 求和, 和ansmax

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int ans=INT_MIN;
        for(int i=0; i<nums.size(); ++i){
            int sum=0;
            for(int j=i; j<nums.size(); ++j){
                sum += nums[j];
                ans = max(ans, sum);
            }
        }
        return ans;
    }
};

动态规划

不出所料的, 超出时间限制;

用动态规划, 创建数组maxSum
nums[0]maxSum[0]就是自己本身

之后的nums[i]maxSum[i]=max(nums[i], maxSum[i-1]+nums[i])

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if(nums.size()==1)
            return nums[0];
        vector<int> maxSum(nums.size());
        maxSum[0] = nums[0];
        int ans=nums[0];
        for(int i=1; i<nums.size(); ++i){
            maxSum[i] = max(nums[i], maxSum[i-1]+nums[i]);
            ans = max(ans, maxSum[i]);
        }
        return ans;
    }
};

优化: 不用数组用pre

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int ans = nums[0];
        int pre = nums[0];
        for(int i=1; i<nums.size(); ++i){
            pre = max(pre+nums[i], nums[i]);
            ans = max(ans, pre);
        }
        return ans;
    }
};

贪心算法

选取一个个"区间 ", 过程中用count记录区间内的和;

count<0时, 将其清空(=0)

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int ans = INT_MIN;
        int count=0;
        for(int i=0; i<nums.size(); ++i){
            count += nums[i];
            ans = max(ans, count);
            if(count<0)
                count = 0;
        }
        return ans;
    }
};

总结

相比于动态规划, 贪心算法的思路难把握的多, 也很难以揣摩;

所以过程中如果想不出来, 第一反应应该是尝试动态规划, 或者直接看题解;

一方面不要在做题过程中硬磕贪心算法;

另一方面在学习的时候, 不要过于较真, 对于贪心这一部分的内容, 可以适当抱着"了解"和:"探索学习"的心态.

把精力多花在可以比较快比较好地掌握和把握的部分和方法上.

本文参考:
分发饼干
摆动序列
最大子序和

相关推荐
Indigo_code1 小时前
【数据结构】【顺序表算法】 删除特定值
数据结构·算法
麻辣韭菜2 小时前
网络基础 【HTTP】
网络·c++·http
__AtYou__2 小时前
Golang | Leetcode Golang题解之第448题找到所有数组中消失的数字
leetcode·golang·题解
阿史大杯茶2 小时前
Codeforces Round 976 (Div. 2 ABCDE题)视频讲解
数据结构·c++·算法
LluckyYH2 小时前
代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会
算法·深度优先·动态规划·软件构建·图论·dfs
转调2 小时前
每日一练:地下城游戏
开发语言·c++·算法·leetcode
不穿格子衬衫3 小时前
常用排序算法(下)
c语言·开发语言·数据结构·算法·排序算法·八大排序
wdxylb3 小时前
使用C++的OpenSSL 库实现 AES 加密和解密文件
开发语言·c++·算法
aqua35357423583 小时前
蓝桥杯-财务管理
java·c语言·数据结构·算法
CV金科3 小时前
蓝桥杯—STM32G431RBT6(IIC通信--EEPROM(AT24C02)存储器进行通信)
stm32·单片机·嵌入式硬件·算法·蓝桥杯