算法 贪心1 || 455.分发饼干 376. 摆动序列 53. 最大子数组和

news2025/1/18 17:04:32

基础知识

什么是贪心:贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
但是贪心没有套路,做题的时候,只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了。

455.分发饼干

很容易想到,把孩子的胃口和饼干大小都排序,都从最小值开始遍历。如果最小的饼干无法满足最小的胃口,就换到相对大一点的饼干继续测试

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

376. 摆动序列

在这里插入图片描述局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。
整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。

核心就是上面的局部最优思路。接下来就是如何实现的问题。自己写的时候使用一个index来判断上一个是高峰还是低峰。然后将后序的值push进stack。要注意!!!一个序列如果所有值都相等,那size()==1的那个子序列可以看成只有一个峰值的摆动序列。,应该返回1而不是0。

stack 和 index实现:

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if(nums.size() <= 1)return nums.size();
        if(nums.size() == 2 ){
           if(nums[0] != nums[1]) return 2;
           else return 1;
        }
        
        int index = 0;
        stack<int> st;
        int start = 1;
        st.push(nums[0]);
        for(start; start < nums.size();++start ){
            if(nums[start] == nums[0]) continue;
            if(nums[start] > nums[0]){
                index = 1;
            }
            st.push(nums[start]);
            break;
        }
        for(int i = start + 1; i < nums.size(); ++i){
            if(nums[i] > st.top() && index == 0) {
                st.push(nums[i]);
                index = 1;
            }
            else if(nums[i] < st.top() && index == 1) {
                st.push(nums[i]);
                index = 0;
            }
            else{
                st.pop();
                st.push(nums[i]);
            }
        }
        return st.size();
    }
};

卡哥的实现:
最朴素的想法,i是当前元素的下标,

prediff = nums[i] - nums[i-1],
curdiff = nums[i+1] - nums[i](prediff > 0 && curdiff < 0) || (prediff < 0 && curdiff > 0)
res加一

但是一个序列会有多种情况

  • 情况一:上下坡中有平坡
    在这里插入图片描述
    在图中,当i指向第一个2的时候,prediff > 0 && curdiff = 0 ,当 i 指向最后一个2的时候 prediff = 0 && curdiff < 0。
    如果我们采用,删左面三个2的规则,那么 当 prediff = 0 && curdiff < 0 也要记录一个峰值,因为他是把之前相同的元素都删掉留下的峰值。
    所以我们记录峰值的条件应该是: (preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0),为什么这里允许 prediff == 0 ,就是为了 上面我说的这种情况。

  • 情况二:数组首尾两端
    首先,不管这个数组的大小是多少,只要大于等于2,就至少有一个大小为1的子序列,能够成为一个摆动序列。所以一开始res就被设置为1。在遍历数组的时候,i= 0开始, 因为要计算 curdiff = nums[i+1] - nums[i]; i < nums.size()-1。这意味着数组尾元素不会被遍历,但是没关系,res设置为1就是默认数组尾端是一个峰值。

下面看两种情况处理首元素:
1、[2,5]
在这里插入图片描述针对序列[2,5],可以假设为[2,2,5],这样它就有坡度了即preDiff = 0。针对以上情形,result初始为1(默认最右面有一个峰值),此时curDiff > 0 && preDiff <= 0,那么result++(计算了左面的峰值),最后得到的result就是2(峰值个数为2即摆动序列长度为2)
2、[2,2]
这种情况其实就是平坡,index = 0 的地方 curDiff = prediff = 0不会统计。只到index = 1不会被遍历到,但是已经在最开始作为默认峰值统计到res中。

  • 情况三:单调坡度有平坡
    在这里插入图片描述上述情况会被统计三次。所以pre应当在有波动的时候才被更新。否则就保持原有的pre
    在这里插入图片描述
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if(nums.size() <= 1) return nums.size();
        int preDiff = 0;
        int curDiff = 0;
        int res = 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)){
                res++;
                preDiff = curDiff;
            }
        }
        return res;
    }
};

53. 最大子数组和

暴力解法: 两层for循环,计算每一个子数组的和,记录最大值。

贪心:如果 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方!

局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。比如有元素 abcd,如果a+b>=0,a+b+c<0,那么无论ab取多少,只要取到c整体和就是一个负数。负数加上任何一个数,不管是正负还是0,都只会更小。
-5 + (-1) = -6
-1 + (-5) = -6。
-5 + 1 = -4

全局最优:选取最大“连续和”
局部最优的情况下,并记录最大的“连续和”,可以推出全局最优。
其关键在于:不能让“连续和”为负数的时候加上下一个元素,而不是 不让“连续和”加上一个负数。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int sum = 0;
        int res = INT_MIN;
        for(int i = 0; i < nums.size(); ++i){
            sum += nums[i];
            if (sum > res) res = sum;
            if(sum < 0) sum = 0;
        }
        return res;
    }
};

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

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

相关文章

Emlog底部显示当前在线人数

第一步&#xff1a;在模板文件里面创建“visitor.php”的文件吧下面代码入进去 code <?php//首先你要有读写文件的权限&#xff0c;首次访问肯不显示&#xff0c;正常情况刷新即可$online_log "slzxrs.dat"; //保存人数的文件到根目录,$timeout 30;//30秒内没…

计算机视觉__基本图像操作(显示、读取、保存)

计算机视觉__基本图像操作&#xff08;显示、读取、保存&#xff09; 本文目录&#xff1a; ✨ 一、前言 ✨ 二、图像显示&#xff08;使用OpenCV和Matplotlib显示图像&#xff09; &#xff08;1&#xff09;、使用OpenCV显示图像 &#xff08;2&#xff09;、使用Matplotl…

密集场景下的行人跟踪替代算法,头部跟踪算法 | CVPR 2021

一个不知名大学生&#xff0c;江湖人称菜狗 original author: Jacky LiEmail : 3435673055qq.com Time of completion&#xff1a;2023.4.8 Last edited: 2023.4.8 目录 摘要 主要内容 结果 这篇文章是CVPR 2021 的最新论文&#xff0c;文章的标题&#xff1a; 文章的主要内…

C#,数值计算的进化与发展——FORTRAN 77/80/95源程序 转C# 源程序的软件F2C#

1 F2C#FORTRAN 77/80/95源程序 转C# 源程序的软件 1.1 F2C#起源 全世界科学计算领域在超过40年的时间里累积了巨大数量的FORTRAN源程序&#xff08;尤其以FORTRAN77居多&#xff09;&#xff0c;实际上目前的许多大型科学软件还是以这些代码为基础的。众所周知的原因&#xf…

【youcans的深度学习 06】PyTorch入门教程:张量的基本操作

欢迎关注『youcans的深度学习』系列&#xff0c;持续更新中… 【youcans的深度学习 01】安装环境之 miniconda 【youcans的深度学习 02】PyTorch CPU版本安装与环境配置 【youcans的深度学习 03】PyTorch CPU版本安装与环境配置 【youcans的深度学习 04】PyTorch入门教程&#…

t-SNE进行分类可视化

0、引入 我们在论文中通常可以看到下图这样的可视化效果&#xff0c;这就是使用t-SNE降维方法进行的可视化&#xff0c;当然除了t-SNE还有其他的比如PCA等降维等方法&#xff0c;关于这些算法的原理有很多文章可以借阅&#xff0c;这里不展开阐释&#xff0c;重点讲讲如何进行…

window10 更新提示 0x80073712错误

解决方法&#xff1a; 1、可以尝试重新配置一下 Windows 更新服务状态&#xff1a; 2、Win S打开搜索&#xff0c;输入 CMD 找到 “命令提示符”&#xff0c; 3、右键以管理员身份打开&#xff0c;依次输入以下代码&#xff0c;并按回车执行。注&#xff1a;是一条一条的执行…

vue基础知识

1、特点 1.采用组件化模式&#xff0c;提高代码复用率、且让代码更好维护。 2.声明式编码&#xff0c;让编码人员无需直接操作DOM&#xff0c;提高开发效率 命令式编码 3.使用虚拟DOM优秀的Diff 算法&#xff0c;尽量复用DOM节点。 2、hello vue vue的引入 就是写在引入c…

关键词词库制作-搜索词分析工具

关键词词库制作 关键词词库是一种帮助SEO和SEM优化的工具&#xff0c;它可以帮助您确定关键词的流行程度、竞争程度、搜索意图和其他相关信息等等。以下是一些关键词词库制作的方法&#xff1a; 收集关键词&#xff1a;首先需要收集相关的关键词&#xff0c;这可能涉及到您的业…

一文讲透产品经理如何用好ChatGPT

作者&#xff1a;京东零售 何雨航 “4.0版本的ChatGPT可以有效提升产品经理工作效率&#xff0c;但并无法替代产品经理的角色。” 一、引言 3月15日&#xff0c;OpenAI发布了最新的基于GPT-4的ChatGPT&#xff0c;关于其智能性的讨论热度在互联网上空前高涨。 我之前体验过3…

基于POSIX的消息队列的发送、接收demo的设计(linux)

本文介绍POSIX的消息队列的linux应用&#xff0c;新建两个进程&#xff08;一个发送进程、一个接收进程&#xff09;实现消息形式的数据传输。POSIX消息队列与SystemV消息队列存在相似的消息传输单位&#xff0c;但较SystemV消息队列更适合linux系统的使用。本文在ubuntu20.4上…

面试篇-深入理解 Java 中的 HashMap 实现原理

一、HashMap实现原理 HashMap 的实现主要包括两个部分&#xff1a;哈希函数和解决哈希冲突的方法。 1.哈希函数 当使用 put() 方法将键值对存储在 HashMap 中时&#xff0c;首先需要计算键的哈希值。HashMap 使用 hashCode() 方法获取键的哈希值&#xff0c;并将其转换为桶&…

Docker的常见命令

前言:使用Docker得学会的几个常见命令 常见命令前置学习: docker --help这个命令必须得会因为,很多命令是记不住的,得使用他们的官方help下面是一些实例 docker load --help常见命令集合: 一: docker images #查看全部镜像 docker rmi #删除某个镜像(例如:docker rmi redis…

Vue3——组件间通信的五种常用方式

Vue3组件间通信的五种常用方式 写在前面 本文采用<script setup>语法糖的编写方式&#xff0c;比options API更自由。 <script setup>语法糖详细内容看查看文档&#xff1a;setup语法糖官方文档 然后我们会讲以下五种常用的组件通信方式 propsemitv-modelrefs…

高速数字信号VS射频信号,到底哪个更难设计?

一博高速先生成员&#xff1a;黄刚熟悉高速先生的小伙伴们会知道&#xff0c;我们是以研究高速数字信号为主的团队&#xff0c;从不到1G到目前在研究的112G&#xff0c;高速先生就这样一直研究过来的&#xff0c;分享的案例也大多是以高速数字信号为主的案例。最近受到我们粉丝…

golang for range 令人抓狂的面试题

1.下面这段代码能否正常结束&#xff1f; func main() {v : []int{1, 2, 3}for i : range v {v append(v, i)} } 答案&#xff1a;正常结束。 可能我们会以为程序会陷入死循环。 但是我们要明白 for range 中的v其实就是复制了一份前面定义的v切片&#xff0c;不论前面定…

Python从入门到精通第3天(循环结构的使用)

循环结构for-in循环while循环break和continue关键字练习在写程序的时候&#xff0c;一定会遇到需要重复执行某条或某些指令的场景&#xff0c;例如用程序控制机器人踢足球&#xff0c;如果机器人持球而且还没有进射门范围&#xff0c;那么我们就要一直发出让机器人向球门方向移…

免费ChatGPT接入-国内怎么玩chatGPT

免费ChatGPT中文版 OpenAI 的 GPT 模型目前并不提供中文版的免费使用&#xff0c;但是有许多机器学习平台和第三方服务提供商也提供了基于 GPT 技术的中文版模型和 API。下面是一些常见的免费中文版 ChatGPT&#xff1a; Hugging Face&#xff1a;Hugging Face 是一个开源社区…

JAVAWeb03-JavaScript

1. JavaScript 1.1 概述 1.1.1 官方文档 地址: https://www.w3school.com.cn/js/index.asp 1.1.2 基本说明 JavaScript 能改变 HTML 内容&#xff0c;能改变 HTML 属性&#xff0c;能改变 HTML 样式 (CSS)&#xff0c;能完成页面的数据验证。 js演示1.html 需要把图片拷贝…

一个注解实现WebSocket集群方案,别提有多优雅了

WebSocket大家应该是再熟悉不过了&#xff0c;如果是单体应用确实不会有什么问题&#xff0c;但是当我们的项目使用微服务架构时&#xff0c;就可能会存在问题 比如服务A有两个实例A1和A2&#xff0c;前端的WebSocket客户端C通过网关的负载均衡连到了A1&#xff0c;这个时候当…