代码随想录算法训练营第三十一天| 理论基础、LeetCode 455.分发饼干、376. 摆动序列、53. 最大子序和

news2024/10/6 2:17:32

一、理论基础

文章讲解:https://programmercarl.com/%E8%B4%AA%E5%BF%83%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

1.贪心的定义

        贪心的本质是选择每一阶段的局部最优解,从而达到全局最优解。例如,有一堆钞票,你可以拿走十张,如果想要拿走的金钱价值最大,那么每次都拿剩余钞票中价值最大的一张即可。而另一类问题,满足每个阶段都是局部最优解,但最后不一定是全局最优解。比如有一堆盒子,你有一个背包体积为n,如何把背包尽可能装满,如果还每次选最大的盒子,就不行了,因为可能选体积小的盒子反而能最大程度利用空间(相信大家开学装行李箱的时候都深有体会)。

2.贪心的套路

        贪心并没有固定套路,偏意识流。难点在于如何看出局部最优能够推出全局最优。现在也没有固定的方法能够说明某题就是贪心,纯靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。拿不准的时候可以举反例,如果想不到反例,那么就试一试贪心吧。当然也可以进行严格的数学推理来表明此题就适合贪心,但不是数学专业的人建议不要这么做,因为比较复杂,面试或者比赛的时候并不要求参与者能够当场证明贪心的合理性。因此,贪心说白了就是常识推导+举反例。

3.贪心一般解题步骤

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

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

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

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

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

        但这个四步其实过于理论化了,我们平时在做贪心类的题目 很难去按照这四步去思考。做题的时候,只要想清楚 局部最优 是什么,如果推导出全局最优,就够了。

二、LeetCode 455.分发饼干

题目链接/文章讲解/视频讲解:https://programmercarl.com/0455.%E5%88%86%E5%8F%91%E9%A5%BC%E5%B9%B2.html

状态:已解决

1.思路

        因为是饼干是离散数据,这意味着饼干不可切分,即使一块饼干尺寸大于孩子的胃口,也只能给孩子喂一整块饼干;那么,对于这样的问题,就用最大饼干尽量去喂最大胃口的孩子(或者小饼干喂小胃口的孩子),即贪心策略,相当于最大化利用每块饼干,如果拿大饼干喂小胃口孩子造成的浪费就会很大,因为可能还存在其他较小饼干也能喂饱小孩子,而你用大饼干去喂,其他饼干又较小,那么大胃口的孩子就无法得到满足。

        如图,是大饼干满足大胃口的情况:

如果有一个饼干不满足大饼干喂大胃口,就会出现以下情况,造成部分饼干浪费且减少了满足孩子数。

        明白原理后,思路就很清晰了。我们需要先对饼干和胃口的数组进行排序,排序后,分别从最大值开始,控制饼干和胃口进行对比,如果该饼干大于等于该胃口,饼干和胃口都向前移动一位,如果小于,则只移动胃口,找能被该饼干喂饱的最大胃口。

        注意,遍历顺序是胃口在外,饼干在内。胃口为外循环代表每次无论喂饱成功都会向前移动一位,相当于,饼干是不变量,需要滑动胃口找能被该饼干喂饱的最大胃口,饼干只有在找到能满足的胃口后才往前移。

2.代码实现

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        int index = s.size()-1;
        int result=0;
        for(int i=g.size()-1;i>=0;i--){
            if(index>=0 && s[index]>=g[i]){
                result++;
                index--;
            }
        }
        return result;
    }
};

三、376.摆动序列 

题目链接/文章讲解/视频讲解:https://programmercarl.com/0376.%E6%91%86%E5%8A%A8%E5%BA%8F%E5%88%97.html

状态:已解决

1.思路 

        这道题需要画图理解,例如,以示例二来举例:

画图图形后,很容易就看出最大摆动序列的长度是峰值的个数(包括最大和最小)。其中,

局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值

整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列

局部最优推出全局最优,并且举不出反例,因此可以试试贪心做法。因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)

在计算是否有峰值的时候,大家知道遍历的下标 i ,计算 prediff(nums[i] - nums[i-1]) 和 curdiff(nums[i+1] - nums[i]),如果prediff < 0 && curdiff > 0 或者 prediff > 0 && curdiff < 0 此时就有波动就需要统计。

这是我们思考本题的一个大题思路,但本题要考虑三种情况:

  1. 情况一:上下坡中有平坡
  2. 情况二:数组首尾两端
  3. 情况三:单调坡中有平坡
(1)情况一:上下坡中有平坡

        例如,对于数组[1,2,2,2,1],如图

那么这种上下坡包含平坡的数组摇摆序列长度为多少呢?其实为3,整个平坡可以看作一个峰值。删除左边两个或者右边两个2,构造峰值。为了tong'yi

2.代码实现 

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int curdiff = 0;
        int prediff = 0;
        int result = 1;
        for(int i=0;i<nums.size()-1;i++){
            curdiff = nums[i+1]-nums[i];
            if((prediff >=0 && curdiff < 0) || (prediff <=0 && curdiff >0)){
                prediff = curdiff;
                result++;
            }
        }
        return result;
    }
};

四、53. 最大子序和

题目链接/文章讲解/视频讲解:https://programmercarl.com/0053.%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%92%8C.html

状态:已解决

1.思路 

        这题我会做!这种求连续子序列最大值类型题的本质是:如果前面的序列和对自身有利才连接序列,否则从自身作为起点重新开始选取序列,也就是自己永远不吃亏。题目要求求具有最大和的连续子数组,我们知道,连续子数组的和=前面连续子数组的和+nums[i],那么怎么选取子序列能够使和最大呢?假如当前在nums[i]的位置,如果前面选取的连续子序列的和<0,那么就说明,nums[i]加上前面的连续子序列后只会拉低nums[i]的值,也就是得到相加结果sum<num[i],这时候单独选nums[i]的结果都比已有连续序列的和大,故我们此时不再连上前面的子序列,而是自立山头,从nums[i]开始做新的序列起点;只有在前面连续子序列的和大于0时,代表连上前面的连续子序列对nums[i]有利,得到相加结果sum>num[i],因此,选择连上前面的序列,扩大连续子序列的范围。

        注意,是连续和小于0时才不选择连接,而不是遇到负数就不连。有人可能觉得遇到负数不是会减小sum吗,但是只有sum仍然大于0,我们就可以把前面的增益效果传递到后面的正数部分,使得正数部分加上后大于自身。例如,假如nums[i]<0,但是连续子数组的和=前面连续子数组的和+nums[i]>0,这种情况仍然是可以被保存的,因为加上下一个num[i+1]后,新的sum值仍会大于nums[i+1]的值。举个示例,[4,-1,5],i此时等于1,显然,nums[-1]=-1<0,但是加上前面的序列和为3,3加到5身上为8,大于5本身,故只有连续和小于0时才不被连接。

2.代码实现

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result=-100000;
        int nowSum = 0;
        for(int i=0;i<nums.size();i++){
            if(nowSum >= 0){
                nowSum += nums[i];//如果前面的和为非负数,那么证明前面的和对我有利,故加之
            }
            else{
                nowSum = nums[i];//如果前面的和为负数,那么前面的和对我不利,不加,
//我自己就比它们的和大了,故作为新起点开始
            }
            result = (result>nowSum)?result:nowSum;
        }
        return result;
    }
};

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

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

相关文章

使用 ChatGPT 创建在线课程:一步一步指南与提示模板

原文&#xff1a;Creating Online Courses with ChatGPT 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 谢谢 作为对你支持的感谢&#xff0c;随意定制本书中列出的任何提示&#xff0c;并将其作为你自己的重新销售。是的&#xff0c;对你免费。 它们都结构良好且用…

移动开发技术历史演化简介h5,跨平台,原生的各种技术实现方案的简单介绍

移动端的开发技术是指针对移动设备如智能手机和平板电脑等便携终端进行应用程序和服务创建的过程。本文将主要介绍一下移动端的开发技术的历史进化历程。讲述h5&#xff0c;跨平台&#xff0c;原生的各种技术实现方案和他们各自的优势与不足。 移动开发&#xff0c;不仅是编程技…

自动化测试框架Robot Framework入门

什么是RF RF是一个基于 Python 的、可扩展的关键字驱动的自动化 验收测试框架、验收测试驱动开发 &#xff08;ATDD&#xff09;、 行为驱动开发 &#xff08;BDD&#xff09; 和机器人流程自动化 &#xff08;RPA&#xff09;。它 可用于分布式、异构环境&#xff0c;其中自动…

Day82:服务攻防-开发组件安全Solr搜索Shiro身份Log4j日志本地CVE环境复现

目录 J2EE-组件Solr-本地demo&CVE 命令执行&#xff08;CVE-2019-17558&#xff09; 远程命令执行漏洞(CVE-2019-0193) Apache Solr 文件读取&SSRF (CVE-2021-27905) J2EE-组件Shiro-本地demo&CVE CVE_2016_4437 Shiro-550Shiro-721(RCE) CVE-2020-11989(身…

macU盘在电脑上读不出来 u盘mac读不出来怎么办 macu盘不能写入

对于Mac用户来说&#xff0c;使用U盘是很常见的操作&#xff0c;但有时候可能会遇到Mac电脑无法读取U盘的情况&#xff0c;这时候就需要使用一些特定的工具软件来帮助我们解决问题。本文就来告诉大家macU盘在电脑上读不出来是怎么回事&#xff0c;u盘mac读不出来怎么办。 一、m…

Java 中 Spring Boot 框架下的 Email 开发

Email 开发 1. 核心依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> </dependency><dependency><groupId>org.springframework.boot</groupId><…

ubuntu安装sublime3并设置中文

安装Sublime Text 3 在Ubuntu上安装Sublime Text 3可以通过以下步骤进行&#xff1a; 打开终端。 导入Sublime Text 3的GPG密钥&#xff1a; wget -qO- https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add - 添加Sublime Text 3的存储库&#xff1a; …

Spring Boot 相关知识和工具类

写在前面 此文是对后端开发框架Spring Boot快速入门一文的知识点补充与完善&#xff0c;如果是新手小白建议两篇文章一起食用,上面那篇文章为主&#xff0c;本文为辅&#xff0c;以达到最佳效果&#xff0c;大佬随意。 http 五种与后端的交互方法 Get:主要用于请求数据。当客…

vue2+elementUi的两个el-date-picker日期组件进行联动

vue2elementUi的两个el-date-picker日期组件进行联动 <template><el-form><el-form-item label"起始日期"><el-date-picker v-model"form.startTime" change"startTimeChange" :picker-options"startTimePickerOption…

Map源码解析

基本介绍 其实HashMap底层是个什么东西我们之前也讲过, 就是一个哈希桶(差不多可以看成一个数组), 然后每一个节点又连接着链表/红黑树之类的, 下面让我们看一看具体在源码上是怎样实现的: 常量及其它 -> static final int DEFAULT_INITIAL_CAPACITY 1 << 4; //这个…

解决JavaWeb中IDEA2023新版本无法创建Servlet的问题

出现问题&#xff1a;IDEA右键创建Servlet时&#xff0c;找不到选项 原因分析&#xff1a;IDEA的2023版的已经不支持Servlet了&#xff0c;如果还要使用的话&#xff0c;需要自己创建模板使用 创建模板 右击设置&#xff0c;选择&#xff08;File and Code Templates&#x…

Oracle APEX 23.2版本 使用应用程序工作副本进行协作开发

现状描述&#xff1a; 当前APEX协作开发都是在同一应用程序下进行的&#xff0c;这样做有可能因同一时间对同一数据进行操作造成锁表或其他问题&#xff0c;Oracle APEX23.2版本迭代后新增了部分功能&#xff0c;可以创建应用程序的工作副本来修复错误、添加功能&#xff0c;然…

后端开发框架Spring Boot快速入门

写在前面 推荐将本文与Spring Boot 相关知识和工具类一文结合起来看&#xff0c;本文为主&#xff0c;上面那篇文章为辅&#xff0c;一起食用&#xff0c;以达到最佳效果&#xff0c;当然&#xff0c;大佬随意。 IDEA创建Spring Boot工程 关于Spring Boot框架项目&#xff0…

Win10 下 Vision Mamba(Vim-main)的环境配置(libcuda.so文件无法找到,windows系统运行失败)

目录 1、下载NVIDIA 驱动程序、cuda11.8、cudnn8.6.0 2、在Anaconda中创建环境并激活 3、下载gpu版本的torch 4、配置环境所需要的包 5、安装causal_conv1d和mamba-1p1p1 安装causal_conv1d 安装mamba-1p1p1 6、运行main.py失败 请直接拉到最后查看运行失败的原因&am…

虚幻UE5数字孪生蓝图开发教程

一、背景 这几年&#xff0c;智慧城市/智慧交通/智慧水利等飞速发展&#xff0c;骑士特意为大家做了一个这块的学习路线。 二、这是学习大纲 1.给虚幻UE5初学者准备的智慧城市/数字孪生蓝图开发教程 https://www.bilibili.com/video/BV1894y1u78G 2.UE5数字孪生蓝图开发教学…

【stm32】I2C通信协议

【stm32】I2C通信协议 概念及原理 如果我们想要读写寄存器来控制硬件电路&#xff0c;就至少需要定义两个字节数据 一个字节是我们要读写哪个寄存器&#xff0c;也就是指定寄存器的地址 另一个字节就是这个地址下存储寄存器的内容 写入内容就是控制电路&#xff0c;读出内容就…

Arcgis Pro地理配准

目录 一、目的 二、配准 1、找到配准工具 2、添加控制点 3、选择控制点 4、添加更多控制点 5、配准完成、保存 三、附录 1、查看控制点或删除控制点 2、效果不好怎么办 一、目的 下面我们将两张地图进行配准&#xff0c;其中一张有地理位置&#xff0c;而另外一张没…

​​​​​​​【人工智能】手写数字识别

手写数字识别 实验背景 数据集介绍 MNIST数据集包含了一系列的手写数字图像&#xff0c;包括0到9的数字。每张图像都是灰度图像&#xff0c;尺寸为28x28像素。数据集共包含60000张训练图像和10000张测试图像。 MNIST数据集的目标是通过训练一个模型&#xff0c;使其能够正确地识…

NPW(监控片的)的要点精讲

半导体的生产过程已经历经数十年的发展&#xff0c;其中主要有两个大的发展趋势&#xff0c;第一&#xff0c;晶圆尺寸越做越大&#xff0c;到目前已有超过70%的产能是12寸晶圆&#xff0c;不过18寸晶圆产业链推进缓慢&#xff1b;第二&#xff0c;电子器件的关键尺寸越做越小&…

LCD屏幕mmap显示

目录 前言 一.LCD显示 二.LCD颜色显示 2.1 直接显示 2.2 mmap映射显示 前言 mmap是一种内存映射文件的方法&#xff0c;它允许将文件或其它对象映射到进程的地址空间。 使用mmap映射函数进行映射显示&#xff0c;与屏幕普通直接显示相比有很大的优势 一.LCD显示基础 像素、分辨…