当前位置: 首页 > news >正文

算法第23天|贪心算法:基础理论、分发饼干、摆动序列、最大子序和

今日总结:

        摆动序列的三种特殊情况需要着重思考,感觉是没有思考清楚

基础理论

        1、贪心的本质:

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

                例如:一堆钞票,只能拿走10张,如何拿走最多的金额?:每次拿最大的(局部最优),最后就是拿走最多的金额(全局最优)

       2、 贪心的套路:

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

                难点:如何通过局部最优推理出全局最优(也没有具体的套路)

                如何验证可不可以使用贪心算法:

                        举反例,如果想不到反例就可以尝试使用贪心算法

        3、贪心的一般解题思路(鸡肋,实际做题不能按照这个考虑):

                (1)将问题分解为若干个子问题

                (2)找出适合的贪心策略

                (3)求解每一个子问题的最优解

                (4)将局部最优解堆叠成全局最优解

                实际做题中,只需要考虑局部最优是什么,如何推导出全局最优

分发饼干

题目链接:455. 分发饼干 - 力扣(LeetCode)

总体思路:

        将每一块饼干都能够给到适合的孩子,就能达到尽可能多的孩子。

        所以,将饼干从小到大排序, 对孩子的胃口值也从小到大排序,尽量将每一块小饼干都能分给对应的小孩子。

总体代码:

class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {//对两者都进行排序sort(g.begin(),g.end());sort(s.begin(),s.end());//一个记录分配的变量int sum=0;//遍历饼干,从最小的胃口值开始分配for(int i=0,j=0;j<s.size();j++){if(i<g.size()&&s[j]>=g[i]){//满足胃口值,满足局部最合适,进行下一个孩子,同时记录i++;sum++;}}return sum;}
};

摆动序列

题目链接:376. 摆动序列 - 力扣(LeetCode)

总体思路:

        1、首先理解摆动序列的含义:连续数字之间的差严格的在正数和负数之间交替,则这个数字序列称为摆动序列,少于两个元素的序列也是摆动序列。

        2、目标:

                (1)现在给定的序列是一个未知的序列:

                (2)需要通过删除最少的元素去获得最大的摆动序列,

                (3)且不能改变元素的原本位置。

        3、方法:贪心算法:通过局部最优推导全局最优

                (1)局部最优:删除单调坡度上的节点(顶、谷不删除),那么这个坡度就有两个局部峰值。

                (2)全局最优:整个序列拥有最多的局部峰值--->达到最长的摆动序列

        4、寻找峰值情况的讨论

                (1)上下坡中有平坡

                        需要删除(不统计)平坡的前边,只保留最后一个峰或者谷[i]-[i-1]<=0&&[i+1]-[i]>0或者[i]-[i-1]>=0&&[i+1]-[i]<0才记录

                (2)数组首尾两端的记录方法

                        因为现在讨论的是通过当前的点与上一个点、下一个点的差获得当前是不是峰谷,所以对于数组首尾的特殊(首没有前一个元素,尾没有下一个元素),可以通过假设数组前还有一个与首相同的元素,即默认峰值是1开始计算。

                        相当于提前记录一个左边的端点,去记录的第二个值是左端点与右端点的峰,没有记录右端点

                (3)单调坡中有平坡

                        在第(1)种中讨论了上下坡中有平坡,处理方法是不去记录前边平的位置,但是在单调的坡中如果有平坡,可能会记录上平坡的右边位置,导致位置变多,所以需要在每次获取到当前位置的左右坡度后,需要将左边的坡度=右边的坡度,在下次计算的时候就会处理掉单调坡有平坡的现象。

                        相当于只记录峰值变化,只要没有出现峰值,就不去记录,也就是将前一个峰值的坡度记录下来,只要当前坡度不相反,就不去记录。

总体代码:

class Solution {
public://核心寻找局部最优,即不记录坡度中的值,只记录峰值//需要注意三点://(1)坡度有平坡的现象//(2)对于起始与结束的位置(因为要三个点比较)//(3)对于单调的坡中存在平坡现象int wiggleMaxLength(vector<int>& nums) {int length =1;//记录长度,从1开始,因为除去起始位置的默认坡度int pre=0;int cur=0;//定义当前的坡度for(int i=0;i<nums.size()-1;i++)//因为默认左端点前有一个与左端点一样的值,不去记录右端点的位置了{   //使用cur去更新pre,从而避免单调坡中出现平坡的问题if(nums.size()<1)return length;//记录当前的坡度cur = nums[i+1]-nums[i];if((pre<=0&&cur>0)||(pre>=0&&cur<0)){length++;//更新前一个坡度,只有在记录峰值的时候才会更新坡度,不是每次计算cur都更新前一个的坡度pre = cur;}}return length;}
};

最大子序和

题目链接:53. 最大子数组和 - 力扣(LeetCode)

总体思路:

        序列中存在正数、负数,求这个序列中的连续的子序列最大的和:所以要着重注意负数的影响,因为正数总是将和增大,负数会将和减小 

        如果从某个值开始的子序列的和为负数了:说明当前值是一个负数,且与之前子序列的和加起来都要小于0,这个数只会影响整体的和,所以直接跳过当前的这个负数,从下一个值重新记录子序列的和。

        但是如果只是加上一个小的负数,整体结果仍旧大于0,不能重新开始记录,因为后边如果有大的正数,会使整体子序列的和变得更大。

        所以,只有当前子序列的和为负数的时候,才从当前值的下一个值开始记录子序列的和,也就是贪心思想,局部的最大,推导出全局的最大。

总体代码:

class Solution {
public://最大和肯定和负值有关系,因为正值只会增加和//当目前的和小于0,就要舍弃,从新计算连续子序列的和(当前负数比之前所有的数之和都小,一定不能带这个负数,不如后边的自己相加)int maxSubArray(vector<int>& nums) {int sum = INT_MIN;//记录最大的和int cur_sum = 0;//记录当前的和for(int i=0;i<nums.size();i++){cur_sum += nums[i];//判断当前的子序列的和是不是大于sumsum = sum >cur_sum?sum : cur_sum;if(cur_sum<0) cur_sum=0;}return sum;}
};


文章转载自:
http://cankery.pzdurr.cn
http://cardioid.pzdurr.cn
http://amber.pzdurr.cn
http://ced.pzdurr.cn
http://arpnet.pzdurr.cn
http://ascribe.pzdurr.cn
http://cancellous.pzdurr.cn
http://affecting.pzdurr.cn
http://bodhran.pzdurr.cn
http://bulgar.pzdurr.cn
http://algidity.pzdurr.cn
http://acolyte.pzdurr.cn
http://certiorari.pzdurr.cn
http://amidst.pzdurr.cn
http://beekeeping.pzdurr.cn
http://catskin.pzdurr.cn
http://blushingly.pzdurr.cn
http://campaniform.pzdurr.cn
http://anticlastic.pzdurr.cn
http://caprylic.pzdurr.cn
http://boldfaced.pzdurr.cn
http://assailant.pzdurr.cn
http://acrobatism.pzdurr.cn
http://amnionic.pzdurr.cn
http://cheloid.pzdurr.cn
http://chalklike.pzdurr.cn
http://caff.pzdurr.cn
http://catbird.pzdurr.cn
http://biped.pzdurr.cn
http://cargador.pzdurr.cn
http://www.dtcms.com/a/280289.html

相关文章:

  • iOS 加固工具使用经验与 App 安全交付流程的实战分享
  • react的Fiber架构和双向链表区别
  • 小架构step系列15:白盒集成测试
  • 大型语言模型(LLM)的技术面试题
  • 如何防止直线电机模组在高湿环境下生锈?
  • 《每日AI-人工智能-编程日报》--2025年7月15日
  • Volo-HTTP 0.4.0发布:正式支持 HTTP/2,客户端易用性大幅提升!
  • AI大模型训练的云原生实践:如何用Kubernetes指挥千卡集群?
  • Node.js 中http 和 http/2 是两个不同模块对比
  • Windows 安装 nvm-windows(Node.js 版本管理器)
  • 一键部署 Prometheus + Grafana + Alertmanager 教程(使用 Docker Compose)
  • sublime如何支持换行替换换行
  • HTTP性能优化实战技术
  • 一键直达人口分布数据
  • 606. 二叉树创建字符串
  • AutoGPT vs BabyAGI:自主任务执行框架对比与选型深度分析
  • Product Hunt 每日热榜 | 2025-07-15
  • 链表算法之【回文链表】
  • 药品挂网价、药品集采价格、药品上市价格一键查询!
  • 多租户SaaS系统中设计安全便捷的跨租户流程共享
  • PubSub is not defined
  • PyCharm 高效入门指南:从安装到效率倍增
  • Spark Expression codegen
  • 用TensorFlow进行逻辑回归(六)
  • Spark 之 Join BoundCondition
  • windows内核研究(进程与线程-KPCR)
  • C++题解(37) 信息学奥赛一本通1318:【例5.3】自然数的拆分
  • 【GEOS-Chem模型第一期】模型概述及网页总结
  • 网络基础10--ACL与包过滤
  • C++11:constexpr 编译期性质