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

news2024/12/23 23:15:48

理论基础 

  • 什么是贪心算法?
    • 贪心的本质是选择每一阶段的局部最优,从而达到全局最优
  • 什么时候用贪心算法?
    • 贪心算法并没有固定的套路。唯一的难点就是如何通过局部最优,推出整体最优。
  • 如何验证可不可以用贪心算法?
    • 最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧
  • 贪心算法一般解题步骤(比较理论化,实用性不强)
    • 将问题分解为若干个子问题
    • 找出适合的贪心策略
    • 求解每一个子问题的最优解
    • 将局部最优解堆叠成全局最优解


455.分发饼干

  • 思路:
    • 如果用最大的饼干来喂胃口最小的孩子,势必会造成饼干尺寸的浪费。所以为了满足更多的小孩,思路应该是尽量用大的饼干来满足胃口大的孩子从后向前遍历小孩数组,尺寸大的饼干优先满足胃口大的孩子,并统计满足小孩数量(或小饼干先喂饱小胃口)。
    • 局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(1)
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int count = 0;
        int index = s.size() - 1;//遍历饼干时的下标
        for(int i = g.size() - 1; i >= 0; i--) {//遍历孩子的胃口
            if(index >= 0 && s[index] >= g[i]) {//遍历饼干
                count++;
                index--;
            }
        }
        return count;
    }
};


376. 摆动序列

  • 思路:
    • 大体思路:让峰值尽可能的保持峰值,然后删除单一坡度上的节点
      • 局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值
      • 整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列
    • 考虑三种情况(prediff:与前一个数的差,curdiff:与后一个数的差):
      • 情况一:上下坡中有平坡
        • 数组[1,2,2,2,2,1]的摇摆序列长度为3,也就是[1,2,1],那么应该取哪一个2呢?不妨统一规则,保留最后一个
        • 当遍历到第一个2时,prediff > 0 && curdiff = 0;当遍历到最后一个2时,prediff = 0 && curdiff < 0,此时要记录一个峰值。
      • 情况二:数组首尾两端
        • ​​​​​​​数组[2,5],在计算 prediff(nums[i] - nums[i-1]) 和 curdiff(nums[i+1] - nums[i])的时候,至少需要三个数字才能计算,而只有两个不同数字的无法这样计算,但显然摇摆序列长度为2。
        • 如果不只有两个元素,我们在判断首尾元素时依旧无法使用上述方法。不妨假设数组最前面还有一个数字,与第一个数字相同,此时prediff = 0,就可以用情况一来判断。而默认最后有一个峰值(统计变量初始化为1)。
      • 情况三:单调坡中有平坡
        • ​​​​​​​数组[1,2,2,2,3,4],根据情况一,遍历到最后一个2时,prediff = 0,curdiff > 0,会记录一个峰值,这样计算出结果会是3,但实际上摇摆序列长度应该为2。
        • 出错的原因是因为实时更新了 prediff,只需要在 这个坡度 摆动变化的时候,更新 prediff 就行,这样 prediff 在 单调区间有平坡的时候 就不会发生变化,造成我们的误判。

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if(nums.size() <= 1) return nums.size();
        int res = 1;//默认最后一个元素为一个峰值,记录峰值个数
        int prediff = 0;//与前一元素的差
        int curdiff = 0;//与后一元素的差
        for(int i = 0; i < nums.size() - 1; i++) {//因为默认最后一个为峰值,所以i < nums.size() - 1
            curdiff = nums[i + 1] - nums[i];
            //出现峰值
            if((prediff <= 0 && curdiff > 0) || (prediff >= 0 && curdiff < 0)) {
                res++;
                prediff = curdiff;//只在统计到峰值的时候更新prediff
            }
        }
        return res;
    }
};


53. 最大子序和 

  • 思路:
    • 如果前面的和为负数,不管什么数加上负数,总和肯定会变小,因此使用贪心算法时,会直接舍弃前面和为负数的这段,直接从下一个元素开始重新计算连续子序列和
    • 全局最优:选取最大“连续和”
    • 局部最优的情况下,并记录最大的“连续和”,可以推出全局最优
    • 本质上就是不断调整子序列区间求和,区间的终止位置,就是如果当前总和取到最大值时,及时用result变量记录下来。
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int res = INT_MIN;
        int sum = 0;
        for(int i = 0; i < nums.size(); i++) {
            sum += nums[i];
            //取区间累计的最大值(相当于不断确定最大子序终止位置)
            res = sum > res ? sum : res;
            if(sum <= 0) sum = 0;//重置最大子序起始位置,因为遇到负数一定是拉低总和
        }
        return res;
    }
};


总结

最好举反例,举不出反例时就可以考虑使用贪心算法

参考链接

代码随想录:理论基础  分发饼干  摆动序列  最大子序和

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1303787.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

恢复出厂设置后在 Android 上恢复照片的 6 种常用方法

恢复出厂设置可帮助您删除电子设备的所有信息并将其恢复到原始系统状态。但是&#xff0c;如果您不小心按下了恢复出厂设置按钮并从 Android 设备中删除了所有难忘的照片&#xff0c;该怎么办&#xff1f;好吧&#xff0c;您无需担心&#xff0c;因为可以通过以下一些方法来恢复…

ArkUI List组件

我们在column中使用foreach循环渲染数据的时候&#xff0c;如果数据过多&#xff0c;超出屏幕高度&#xff0c;会出现隐藏的情况。 class Item {name: stringimage: ResourceStrprice: numberdiscount: numberconstructor(name: string, image: ResourceStr, price: number,dis…

人人都能用的AI编程助手 CodeGeeX

视频版&#xff1a;人人都能用的Ai编程助手——CodeGeeX 大家好&#xff0c;我是凌览。 现在距离 AI 大火已经快有一年啦&#xff0c;作为程序员可不得准备一款AI帮咱们干点活。本文分享一款 AI 工具 CodeGeeX&#xff0c;帮助大家提高一波学习和工作效率。 CodeGeeX 是什么…

springcloud微服务篇--1.认识微服务

一、服务架构演变。 单体架构&#xff1a; 将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 优点&#xff1a;架构简单 &#xff0c;部署成本低。 缺点&#xff1a;耦合度高 分布式架构 根据业务功能对系统进行拆分&#xff0c;每个业务模块作为独立项…

spring国际化 - i18n

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

Excel——TEXTJOIN函数实现某一列值相等时合并其他列

一、TEXTJOIN函数介绍 公式TEXTJOIN(分隔符, 忽略空白单元格, 字符串1…) 分隔符&#xff1a;文本字符串&#xff0c;或者为空&#xff0c;或用双引号引起来的一个或多个字符&#xff0c;或对有效文本字符串的引用。如果提供一个数字&#xff0c;则将被视为文本。 忽略空白单…

选用SLMi331CG-DG芯片作为隔离驱动驱动器有什么优势?

国内首款单通道带DESAT保护功能的/SiC隔离SLMi331CG-DG&#xff0c;内置快速去饱和&#xff08;DESAT&#xff09; 故障检测功能、米勒钳位功能、漏极开路故障反馈、软关断功能以及可选择的自恢复模式&#xff0c;兼容隔离驱动器&#xff0c;为客户工程师提供高质量、高性能的替…

东芝携手罗姆共同投资191亿元,共同生产功率芯片 | 百能云芯

日本东芝&#xff08;Toshiba&#xff09;集团与芯片制造商罗姆半导体集团&#xff08;Rohm&#xff09;近日宣布将共同生产功率芯片&#xff0c;总投资额达3883亿日元&#xff08;约人民币191亿元&#xff09;&#xff0c;这一举措旨在通过扩大生产规模&#xff0c;提高成本竞…

awt中文乱码-Intellij IDEA

乱码的根本原因在于秦始皇嘎太早了&#xff08;bushi 解决方法&#xff1a;肉眼可见的编码设置统一为GBK 1.打开设置找到文件编码 2.肉眼可见的编码统统改成GBK 有人该问了&#xff0c;为什么不改成utf-8&#xff0c;因为awt的编码由操作系统决定&#xff0c;我的是win家庭中…

鸿蒙开发之状态管理@Prop和@Link

一、用法 在父子组件需要进行数据同步的时候&#xff0c;可以通过Prop和Link装饰器来做到。在父组件中用State装饰&#xff0c;在自组件中用Prop或Link装饰。 结论&#xff1a;Prop用于子组件只监听父组件的数据改变而改变&#xff0c;自己不对数据改变 Link用于子组件与父组…

C语言三种循环输出9*9乘法表

解题思路&#xff1a; 1、外层循环控制1~9循环 2、内层控制循环的次数 比如&#xff1a; 1 * 1 1 循环一次 1 * 1 1 1 * 2 循环两次 依此类推 int i, j;printf("for 打印9*9乘法表\r\n");for(i 1; i <10; i) {for(j 1; j < i;j) {printf("%d * %d %d…

快速排序(2)

一、快速排序有三种方法&#xff1a;hoare版本、挖坑法、前后指针版本 但是三种方法的核心思想都是一样的&#xff0c;都是将该数组分为左右两半递归式的排序。 1.hoare版本 该方法是先保存a[keyi]位置的值&#xff0c;然后右边先开动找小&#xff0c;找到小后&#xff0c;左…

Sci Transl Med | 新生儿重症监护室肠道病原体定植先于血流感染

今天给同学们分享一篇生信文章“Gut pathogen colonization precedes bloodstream infection in the neonatal intensive care unit”&#xff0c;这篇文章发表在Sci Transl Med期刊上&#xff0c;影响因子为17.1。 结果解读&#xff1a; 最近使用抗生素会导致肠道微生物群中潜…

Jemeter,提取响应体中的数据:正则表达式、Json提取器

一、正则表达式 1、线程组--创建线程组&#xff1b; 2、线程组--添加--取样器--HTTP请求&#xff1b; 3、Http请求--添加--后置处理器--正则表达式提取器&#xff1b; 4、线程组--添加--监听器--查看结果树&#xff1b; 5、线程组--添加--取样器--调试取样器。 响应体数据…

【Java SE】带你识别什么叫做异常!!!

&#x1f339;&#x1f339;&#x1f339;个人主页&#x1f339;&#x1f339;&#x1f339; 【&#x1f339;&#x1f339;&#x1f339;Java SE 专栏&#x1f339;&#x1f339;&#x1f339;】 &#x1f339;&#x1f339;&#x1f339;上一篇文章&#xff1a;【Java SE】带…

Axure的使用

1.Axure是什么&#xff1f;&#xff1f;&#xff1f; Axure是一款功能强大的原型设计工具&#xff0c;它可以让用户快速地创建交互式原型&#xff0c;并针对原型进行测试和改进。Axure的主要特点包括可定制的界面元素库、交互动画效果、条件逻辑、团队协作等功能&#xff0c;适…

nginx 网页匹配跳转

常用的Nginx 正则表达式 常用的Nginx 正则表达式 ^ &#xff1a;匹配输入字符串的起始位置 $ &#xff1a;匹配输入字符串的结束位置 * &#xff1a;匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll”&#xff1a;匹配前面的字符一次或多次。如“ol”能匹配“o…

《虹》国家级月刊维普收录期刊投稿

《虹》杂志由中华人民共和国国家新闻出版署正式批准&#xff0c;国内外公开发行的优秀期刊。虹杂志由团中央主管、中国青年出版总社主办&#xff0c;发行周期为月刊。为各行各业广大朋友提供一个学术交流的平台。 刊名&#xff1a;虹 主管单位&#xff1a;共青团中央 主办单…

ONLYOFFICE协作空间2.0:文档协作更便捷

〇、前言 大家好我是陈橘又青&#xff0c;在之前的文章中&#xff0c;我向大家介绍了ONLYOFFICE&#xff1a;免费、开源、跨平台的办公神器&#xff0c;想必大家都已经了解到了ONLYOFFICE在企业办公、文档处理工作中的方便快捷。ONLYOFFICE 2.0版本也已于近日更新。 今天就来跟…

ubuntu-c++-可执行模块-动态链接库-链接库搜索-基础知识

文章目录 1.动态链接库简介2.动态库搜索路径3.运行时链接及搜索顺序4.查看可运行模块的链接库5.总结 1.动态链接库简介 动态库又叫动态链接库&#xff0c;是程序运行的时候加载的库&#xff0c;当动态链接库正确安装后&#xff0c;所有的程序都可以使用动态库来运行程序。动态…