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

一、理论基础

文章讲解: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.mzph.cn/news/794836.shtml

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

相关文章

基于SpringBoot Vue汽车租赁系统

一、&#x1f4dd;功能介绍 基于SpringBoot Vue汽车租赁系统 角色&#xff1a;管理员、普通管理员、用户 管理员&#xff1a;管理员进入主页面&#xff0c;主要功能包括对系统首页、个人中心、用户管理、普通管理员管理、汽车类别管理、汽车信息管理、租车订单管理、取消订单管…

网络安全 | 什么是威胁情报?

关注WX&#xff1a;CodingTechWork 威胁情报 威胁情报-介绍 威胁情报也称为“网络威胁情报”(CTI)&#xff0c;是详细描述针对组织的网络安全威胁的数据。威胁情报可帮助安全团队更加积极主动地采取由数据驱动的有效措施&#xff0c;在网络攻击发生之前就将其消弭于无形。威…

09 flink-sql 中基于 mysql-cdc 的 select * from test_user 的具体实现

前言 这也是最近帮一个朋友看问题 遇到的一个问题 然后 引发了一下 对于 flink-sql 里面的一些 常规处理的思考, 理解 原始问题主要是 在测试库可以使用 flink-sql 可以正常同步, 但是 在生产环境 无法正常同步数据 这个问题 我们后面单独 记录一篇文章 测试用例 下载…

网络抓包专题

导航目录 HTTP 原理HTTPS 原理TLS 原理网络抓包原理一. 什么是抓包&#xff1f;二. 抓包的原理对HTTP请求进行抓包对HTTPS请求进行抓包 三. Android设备抓包问题Android6.0 及以下系统Android7.0 及以上系统方式一&#xff1a;方式二 HTTP 原理 HTTP 详解 点击跳转 HTTPS 原理…

【QT入门】 Qt代码创建布局综合运用:仿写腾讯会议登陆界面

往期回顾&#xff1a; 【QT入门】 Qt代码创建布局之水平布局、竖直布局详解-CSDN博客 【QT入门】 Qt代码创建布局之栅格布局详解-CSDN博客 【QT入门】 Qt代码创建布局之分裂器布局详解-CSDN博客 【QT入门】 Qt代码创建布局综合运用&#xff1a;仿写腾讯会议登陆界面 一、界面分…

Linux基础篇:文件系统介绍——根目录下文件夹含义与作用介绍

Linux文件系统介绍——文件夹含义与作用 Linux文件系统是一个组织和管理文件的层次结构。它包括了目录、子目录和文件&#xff0c;这些都是按照一定的规则和标准进行组织的。以下是Linux文件系统的一些关键组成部分&#xff1a; 1./bin&#xff1a; 该目录包含了系统启动和运…

Rust线程间通信通讯channel的理解和使用

Channel允许在Rust中创建一个消息传递渠道&#xff0c;它返回一个元组结构体&#xff0c;其中包含发送和接收端。发送端用于向通道发送数据&#xff0c;而接收端则用于从通道接收数据。不能使用可变变量的方式&#xff0c;线程外面修改了可变变量的值&#xff0c;线程里面是拿不…

C++设计模式:策略模式(二)

1、定义与动机 定义一系列算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可互相替换&#xff08;变化&#xff09;&#xff0c;该模式使得算法可独立于使用它的客户程序&#xff08;稳定&#xff09;而变化&#xff08;扩展&#xff0c;子类化&#xff09; 在软…

Hadoop-MapReduce

一、MapReduce 概述 1.1 MapReduce 定义 MapReduce 是一个分布式运算程序的编程框架&#xff0c;是用户开发“基于 Hadoop 的数据分析应用”的核心框架。 MapReduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并发运行在…

Linux:Centos9:配置固定ip

centos9的网卡位置移动到了 /etc/NetworkManager/system-connections/ 下面 查看网卡 ifconfig 当前有两块网卡&#xff0c;我要去配置ens160的一个固定的ip&#xff0c;让其ip为192.168.6.20/24&#xff0c;网关为192.168.6.254.dns为&#xff1a;1.1.1.1 vim /etc/Netwo…

CSS-概述

&#x1f4da;详见 W3scholl&#xff0c;本篇只做快速思维索引。 概述 CSS 是一种描述 HTML 文档样式的语言。 有三种插入样式表的方法&#xff1a; 外部 CSS内部 CSS行内 CSS &#x1f4c5; 外部 CSS 外部样式表存储在.css文件中。HTML 页面必须在 head 部分的<link&g…

基于JavaWeb实现的漫画网站前后台系统

一、项目简介 本项目是一套基于JavaWeb实现的漫画网站前后台系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#x…

云服务器ECS租用价格表报价——阿里云

阿里云服务器租用价格表2024年最新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核…

SRS 实时视频服务器搭建及使用

一、SRS 介绍 SRS是一个开源的&#xff08;MIT协议&#xff09;简单高效的实时视频服务器&#xff0c;支持RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DASH和GB28181等协议。 SRS媒体服务器和FFmpeg、OBS、VLC、 WebRTC等客户端配合使用&#xff0c;提供流的接收和分发的能力&am…

DNS和HTTP

DNS应用层协议 域名解析系统 使用IP地址&#xff0c;来描述设备在网络上的位置 IP地址并不适合来进行传播网站&#xff0c;就采用了域名的方式来解决网站传播的问题。如www.baidu.com这样类似的就很容易让人记住。其域名就直接代表了这个网站。而且有一套自动的系统会将域名解…

YOLO火灾烟雾检测数据集:20000多张,yolo标注完整

YOLO火灾烟雾检测数据集&#xff1a;一共20859张图像&#xff0c;yolo标注完整&#xff0c;部分图像应用增强 适用于CV项目&#xff0c;毕设&#xff0c;科研&#xff0c;实验等 需要此数据集或其他任何数据集请私信

C++11多线程库重点接口

目录 一.thread构造函数 二.移动构造&#xff0c;移动赋值 小结 三.获取线程id的方法 四.thread与lambda表达式联用 五.Mutexs的总览 六.互斥锁 七.Locks的总览 八. 条件变量总览 九.条件变量的wait和notify 十.典型例题 十一.原子类 十二.智能指针和单例模式的线…

详解 Redis 在 Ubuntu 系统上的安装

在 Ubuntu 20.04 安装 Redis 1. 先切换到 root 用户 在 Ubuntu 20.04 中&#xff0c;可以通过以下步骤切换到 root 用户&#xff1a; 输入以下命令&#xff0c;以 root 用户身份登录&#xff1a; sudo su -按回车键&#xff0c;并输入当前用户的密码&#xff08;即具有 sudo…

【论文精读】Detecting Out-of-Distribution Examples with Gram Matrices 使用Gram矩阵检测分布外实例

文章目录 一、文章概览&#xff08;一&#xff09;Gram矩阵1、Gram&#xff08;格朗姆&#xff09;矩阵的定义2、Gram矩阵计算特征表示3、风格迁移中的Gram矩阵 &#xff08;二&#xff09;ood检测&#xff08;三&#xff09;核心思路&#xff1a;扩展 Gram 矩阵以进行分布外检…

2024最新在线工具箱/ 站长IT工具箱/网站系统源码下载

2024最新在线工具箱/ 站长IT工具箱/网站系统源码下载- 更多详情及下载地址请访问https://a5.org.cn/a5_ziyuan/39525.html 转载请注明出处!