• 每日刷题|贪心算法初识


                                            食用指南:本文为作者刷题中认为有必要记录的题目

                                            推荐专栏每日刷题

                                           ♈️今日夜电波悬溺—葛东琪

                                                                    0:34 ━━━━━━️💟──────── 3:17
                                                                        🔄   ◀️   ⏸   ▶️    ☰ 

                                          💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


    目录

    贪心算法的理解

    一、分发饼干

     二、K次取反后最大化的数组和

    三、柠檬水找零


    贪心算法的理解

    本文参考了一位大佬的题解,详细的介绍了贪心算法:链接

    贪心算法一般分为如下四步:

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

            贪心算法并没有固定的套路

            难点在于如何通过局部最优,推出整体最优


    一、分发饼干

    455. 分发饼干icon-default.png?t=N7T8https://leetcode.cn/problems/assign-cookies/

    题目描述: 

            假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

    示例 1:

    输入: g = [1,2,3], s = [1,1]
    输出: 1
    解释: 
    你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
    虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
    所以你应该输出1。
    

    示例 2:

    输入: g = [1,2], s = [1,2,3]
    输出: 2
    解释: 
    你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
    你拥有的饼干数量和尺寸都足以让所有孩子满足。
    所以你应该输出2.
    
    

    提示:

    • 1 <= g.length <= 3 * 104
    • 0 <= s.length <= 3 * 104
    • 1 <= g[i], s[j] <= 231 - 1

    本题思路: 

            将饼干和孩子都从小到大排序一下,为了满足更多的小孩,就不要造成饼干尺寸的浪费,那按照贪心的思想:局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。那么便从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量。

    1. class Solution {
    2. public:
    3. int findContentChildren(vector<int>& g, vector<int>& s) {
    4. sort(g.begin(),g.end());//排序
    5. sort(s.begin(),s.end());
    6. int index=s.size()-1;
    7. int sum=0;
    8. for(int i=g.size()-1;i>=0;i--)//从大往小尽量给
    9. {
    10. if(index>=0&&s[index]>=g[i])
    11. {
    12. index--;
    13. sum++;
    14. }
    15. }
    16. return sum;
    17. }
    18. };


     二、K次取反后最大化的数组和

    1005. K 次取反后最大化的数组和icon-default.png?t=N7T8https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/

    题目描述: 

            给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:

            选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。

            重复这个过程恰好 k 次。可以多次选择同一个下标 i 。

            以这种方式修改数组后,返回数组 可能的最大和 。

    示例 1:

    输入:nums = [4,2,3], k = 1
    输出:5
    解释:选择下标 1 ,nums 变为 [4,-2,3] 。
    

    示例 2:

    输入:nums = [3,-1,0,2], k = 3
    输出:6
    解释:选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2] 。
    

    示例 3:

    输入:nums = [2,-3,-1,5,-4], k = 2
    输出:13
    解释:选择下标 (1, 4) ,nums 变为 [2,3,-1,5,4] 。
    

    提示:

    • 1 <= nums.length <= 104
    • -100 <= nums[i] <= 100
    • 1 <= k <= 104

    本题思路: 

    暴力思想解法:

            看到这题,啪的一下很快啊,直接就想到了先从小到大排序一次。然后,给最小的数取反,然后再排序,再取反,以此类推,统共取反K次。

    1. class Solution {
    2. public:
    3. int largestSumAfterKNegations(vector<int>& nums, int k) {
    4. for(int i=0;i
    5. {
    6. sort(nums.begin(),nums.end());
    7. nums[0]*=-1;
    8. }
    9. int result=0;
    10. for (int i=0;isize();i++)
    11. {
    12. result+=nums[i];
    13. }
    14. return result;
    15. }
    16. };

            虽然但是,这篇文章学的是贪心思想啊,我们还是要用贪心来写的!!!

    贪心思想解法:

            贪心的思路,局部最优:让绝对值大的负数变为正数,当前数值达到最大,整体最优:整个数组和达到最大。局部最优可以推出全局最优。

    • 第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
    • 第二步:从前向后遍历,遇到负数将其变为正数,同时K--
    • 第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
    • 第四步:求和
    1. class Solution {
    2. static bool cmp(int a, int b) {
    3. return abs(a) > abs(b);
    4. }
    5. public:
    6. int largestSumAfterKNegations(vector<int>& A, int K) {
    7. sort(A.begin(), A.end(), cmp); // 第一步
    8. for (int i = 0; i < A.size(); i++) { // 第二步
    9. if (A[i] < 0 && K > 0) {
    10. A[i] *= -1;
    11. K--;
    12. }
    13. }
    14. if (K % 2 == 1) A[A.size() - 1] *= -1; // 第三步
    15. int result = 0;
    16. for (int a : A) result += a; // 第四步
    17. return result;
    18. }
    19. };


    三、柠檬水找零

    860. 柠檬水找零icon-default.png?t=N7T8https://leetcode.cn/problems/lemonade-change/

     题目描述: 

            在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

            每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

            注意,一开始你手头没有任何零钱。

            给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

    示例 1:

    输入:bills = [5,5,5,10,20]
    输出:true
    解释:
    前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
    第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
    第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
    由于所有客户都得到了正确的找零,所以我们输出 true。
    

    示例 2:

    输入:bills = [5,5,10,10,20]
    输出:false
    解释:
    前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
    对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
    对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
    由于不是每位顾客都得到了正确的找零,所以答案是 false。
    
    

    提示:

    • 1 <= bills.length <= 105
    • bills[i] 不是 5 就是 10 或是 20 

    本题思路: 

    只需要维护三种金额的数量,5,10和20。

    有如下三种情况:

    • 情况一:账单是5,直接收下。
    • 情况二:账单是10,消耗一个5,增加一个10
    • 情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5

    局部最优:遇到账单20,优先消耗美元10,完成本次找零。全局最优:完成全部账单的找零。 

    1. class Solution {
    2. public:
    3. int five;
    4. int ten;
    5. int twenty;
    6. public:
    7. bool lemonadeChange(vector<int>& bills) {
    8. for(int bill:bills)
    9. {
    10. if(bill==5)//情况1
    11. {
    12. five++;
    13. }
    14. if(bill==10)//情况2
    15. {
    16. if (five <= 0) return false;
    17. ten++;
    18. five--;
    19. }
    20. if(bill==20)//情况3
    21. {
    22. if(ten>0&&five>0)
    23. {
    24. ten--;
    25. five--;
    26. }else if(five>=3)
    27. {
    28. five-=3;
    29. }else
    30. {
    31. return false;
    32. }
    33. }
    34. }
    35. return true;
    36. }
    37. };


                    感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o!  

                                     

                                                                     给个三连再走嘛~      

  • 相关阅读:
    【Spark 实战系列】Phoenix 整合 spark 进行查询分析
    如何实现应用程序的身份认证和数据加密?
    希望所有计算机学生都知道这些宝藏课程
    Python入门:A+B问题
    EBS R12.2.0升级到R12.2.6
    时间序列平滑法中边缘数据的处理技术
    给爷肝!Alibaba架构师纯手工打造神仙级“2022版Java面试手册”
    CPU核心、使用率、负荷、是否开启超线程、如何排查java程序cpu使用率过高
    vue入门
    云畅科技TMS解决方案助力华菱线缆实现智能货运管理
  • 原文地址:https://blog.csdn.net/weixin_64038246/article/details/133969385