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

news2024/11/25 11:55:29

今日内容

  • 贪心理论基础
  • Leetcode. 455 分发饼干
  • Leetcode. 376 摆动序列
  • Leetcode. 53 最大子序和

贪心理论基础

贪心算法的本质就是选择每一阶段的最优,达到全局上的最优

贪心算法和之前学到的所有方法相比,它没有固定的使用套路,也没有固定的验证法来确认本题是否适用贪心算法。

对于何时应该使用贪心,那就只能手动模拟推导一下。如果模拟推导感觉可以根据局部最优推出全局最优,并且也找不出反例的话,就用贪心吧

Leetcode. 455 分发饼干

文章链接:代码随想录 (programmercarl.com)

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

本题的局部最优就是拿目前最大的饼干来满足胃口最大的孩子,从而达到全局最优:尽可能多的孩子被喂饱。而且似乎也找不出反例,那么就可以使用贪心算法解决。

因此,可以写出如下代码:

class Solution {
    // 从大到小进行贪心
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int index = s.length - 1;
        int result = 0;
        for (int i = g.length - 1; i >= 0; i--){ // 注意这里遍历的是 胃口
            if (index >= 0 && s[index] >= g[i]){
                index--;
                result++;
            }
        }
        return result;
    }
}
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(1)

注意代码中,for 循环是在表示小孩胃口的数组中进行遍历的,这样是必须的。因为假如对饼干尺寸数组进行遍历,则可能遇到如下图所示情况:

即 饼干尺寸数组遍历完也找不到一个匹配当前孩子胃口的结果,进而影响结果。如果我们的贪心思想是先用尺寸小的饼干满足小胃口的孩子优先的话,此时遍历饼干尺寸数组是正确的。

Leetcode. 376 摆动序列

文章链接:代码随想录 (programmercarl.com)

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

本题的局部思想就是获取单调坡上的两端节点,不理会单调坡中间的节点,获取两个局部峰值。使整个序列的局部峰值最多,就可以获得全局最优:得到最长摆动序列。

要想知道当前节点是否为单调坡的两端,就需要知晓该节点的前坡值 pre 和 后坡值 next。其中 pre = nums[i] - nums[i - 1],next = nums[i + 1] - nums[i]。当 pre > 0, next < 0 或 pre < 0, next > 0时就说明当前节点是坡的两端。

知晓了两端的判断方式,就需要列出单调坡中可能出现的情况:

  1. 上下坡中有平坡如图所示,此时要么去除前三个重复元素,要么去除后三个重复元素。所以考虑这种情况后,上面的条件就变为了 当 pre >= 0, next < 0 或 pre <= 0, next > 0 时就说明当前节点是坡的两端。
  2. 数组首位两端。假如整个数组只有两个元素,根据上述的前后坡值是无法计算出来的,因为这样需要三个元素得出。因此可以假设最左边的元素前有个平坡,然后最右边的元素自动视作是一个峰值。

根据上述两种情况可以写出如下代码:

// 版本一
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if (nums.size() <= 1) return nums.size();
        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)) {
                result++;
            }
            preDiff = curDiff;
        }
        return result;
    }
};

但这个代码依然完成不了,原因就在于 preDiff = curDiff 这一行。

实际上,除了上述两个情况以外还有一个情况:单调坡上有个平坡。

面对这种情况,如果根据 版本一 的代码所示,遍历每个元素时都更新一次前坡值,那么它会把第三个 2 认为是一次摆动,但实际上这只是单调坡上的平坡的一个转折点,并没有摆动。

要想解决该情况,则需要在摆动真正发生时更新前坡值。因此,改良后的代码如下:

class Solution {
    public int wiggleMaxLength(int[] nums) {
        int pre = 0;
        int cur = 0;
        int result = 1; // 默认最右边的元素算一个摆动序列
        for (int i = 0; i < nums.length - 1; i++){ // 注意条件表达式已经将最后一个元素排除
            cur = nums[i + 1] - nums[i];
            if (pre >= 0 && cur < 0 || pre <= 0 && cur > 0){
                result++;
                pre = cur; // 摆动发生时才更新前坡值
            }
        }
        return result;
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

Leetcode. 53 最大子序和

文章链接:代码随想录 (programmercarl.com)

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

本题的局部最优就是当前元素若加入进来后导致总和为负数后,则重新求和。因为本题要求最大的连续子序,所以当总和为负数后,总是会拉低得到的结果,因此碰到使总和为负数的元素时就重置总和。

本题思路如下图所示:

写出如下代码:

class Solution {
    public int maxSubArray(int[] nums) {
        int result = Integer.MIN_VALUE;
        int count = 0;
        for (int i = 0; i < nums.length; i++){
            count += nums[i];
            if (count > result){ // 记录当前最大总和
                result = count;
            }
            if (count < 0){count = 0;} // 当总和为负数时,重置
        }
        return result;
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

总结

贪心算法真是给了个下马威,一下子难以彻底消化贪心算法的使用。

目前看来,贪心算法最重要的还是找到题目中什么是局部最优,这样才好进行下一步。

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

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

相关文章

IEEE 802.11a OFDM系统的仿真

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第九章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; ​ ​ ​ clear all %%%%%%%参数设计部分%%%%%%%Nsp52;%系统子载波数&#xff08;不包括直流载波&#xff09; Nfft64;%FF…

【QT】自制一个简单的小闹钟,能够实现语音播报功能

做了一个自制的小闹钟&#xff0c;能够自己输入时间&#xff0c;以及对应的闹铃&#xff0c;时间到了自动播放设定的闹铃&#xff0c;可以随时取消重新设定&#xff0c;采用分文件编译 注意&#xff1a;需要在.pro文件中加入&#xff1a;QT core gui texttospeech 代码…

使用C++编写一个语音播报时钟(Qt)

要求&#xff1a;当系统时间达到输入的时间时&#xff0c;语音播报对话框中的内容。定时可以取消。qt界面如上图所示。组件如下&#xff1a; countdownEdit作为书写目标时间的line_edit start_btn作为开始和停止的按钮 stop_btn作为取消的按钮 systimelab显示系统时间的lab tex…

绿色医院建的中央空调无线集中控制系统

在医疗服务水平不断提高的今天&#xff0c;空调能耗已成为医院建筑能耗的主要组成部分&#xff0c;达到总建筑能耗的50%至60%。如何提高医院中央空调系统的能效&#xff0c;成为绿色医院建设中亟待解决的问题。而中央空调无线集中控制系统的出现&#xff0c;为医院节能运行提供…

Etsy店铺又被封了?教你申诉和防封技巧!

熟悉美国Etsy平台的用户都知道&#xff0c;该平台对店铺的监管非常严格&#xff0c;店铺被封的情况时有发生。 无论是新开的店铺&#xff0c;还是已经有一定订单量的店铺&#xff0c;都可能面临被封的风险&#xff0c;突如其来的封号&#xff0c;会让很多卖家束手无策。 那么&a…

国内AI论文写作推荐工具有哪些?试试这7款

在当前信息爆炸的时代&#xff0c;AI写作工具已经成为学术研究和写作的重要助手。这些工具不仅能够提高写作效率&#xff0c;还能帮助用户生成高质量的文稿。以下是七款值得推荐的国内AI论文写作工具&#xff1a; 一、千笔-AIPassPaper 千笔-AIPassPaper是一款功能强大且全面…

MDK keil STM32 局部变量不能查看值,显示为not in scope

用MDK调试程序&#xff0c;查看变量时watch窗口总是和 一、方法1&#xff1a;优化级别改为Level 0 1 编译器把这个局部变量给优化掉了&#xff0c;并没有在内存中生成&#xff0c;把优化级别改为Level 0&#xff0c;重新编译。 Keil默认优化是等级3&#xff0c;最高优化&…

MMO 地图传送,UI系统框架设计

地图传送 创建传送点 建碰撞器触发 //位置归零 建一个传送门cube放到要传送的位置&#xff08;这个teleporter1是传出的区域 这是从另一张地图传入时的传送门 创建一个脚本TeleporterObject给每个传送cube都绑上脚本 通过脚本&#xff0c;让传送门在编辑器下面还能绘制出来 …

第三部分:6---进程程序替换

目录 进程替换&#xff1a; execl函数解析&#xff1a; 多进程替换的本质&#xff1a; exec系列函数解析&#xff1a; 进程替换不会替换原进程的环境变量&#xff1a; 进程替换&#xff1a; 通过 fork 创建的进程&#xff0c;在最初会执行父进程代码的一部分&#xff0c;这…

动态规划-最长回文子序列

题目描述 给你一个字符串 s &#xff0c;找出其中最长的回文子序列&#xff0c;并返回该序列的长度。 子序列定义为&#xff1a;不改变剩余字符顺序的情况下&#xff0c;删除某些字符或者不删除任何字符形成的一个序列。 示例 1&#xff1a; 输入&#xff1a;s "bcbbab…

图书馆上新了!新华书店×度小满推出“开学季悦读计划”公益活动

2024年9月&#xff0c;新学期伊始&#xff0c;度小满携手新华书店启动“开学季悦读计划”公益行动。本次活动以“开学季&#xff0c;图书馆上新书”为主题&#xff0c;向度小满“小满助力计划”公益项目落地过的五个地区共六所小学和初中捐赠3300余本图书&#xff0c;让孩子们开…

李飞飞团队 ReKep:空间智能机器人可整合 GPT-4o;苹果首款 AI 手机 iPhone 16 发布丨RTE 开发者日报

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

一款专业编曲软件Guitar Pro 8中文版安装激活图文教程

Guitar Pro 8中文版是一款专业编曲软件&#xff0c;帮助所有的吉他爱好者学习、创作、设计、绘谱&#xff0c;指法、音色&#xff0c;了解各种吉他方面的内容&#xff0c;除了吉他还有其他十种乐器可以使用&#xff0c;节省时间&#xff0c;提高效率&#xff0c;有助于学习如何…

LLM大模型学习:AI Agent综述

AI Agent是什么 将LLM思想链接到一起&#xff0c;自主实现用户设定的任何目标。只需要告诉AutoGPT一个目标&#xff0c;能自主生成执行计划。 吴恩达&#xff1a;“与其争论哪些工作才算是真正的 Agent&#xff0c;不如承认系统可以具有不同程度的 Agentic 特性。” 核心在于…

TCP 为什么是三次握手,而不是两次或四次?(通俗易懂)

TCP 三次握手是为了保证&#xff1a;让客户端和服务器都知道自己和对方的发送和接收都没问题。 换句话说&#xff0c;可以 假设客户端和服务端都维护了四个布尔变量&#xff1a;自己发送&#xff0c;自己接收&#xff0c;对方发送&#xff0c;对方接收。 初始值为 false&#…

ROS第三梯:ROS+C++实现速腾Bag包的解析

解决问题&#xff1a;速腾Bag包利用bag_to_pcd生成的pcd文件字段名称存在问题&#xff0c;多了几个异常的"_"&#xff0c;导致强度属性无法在Intensity中显示。 解决方案&#xff1a;利用sensor_msgs库进行数据读取和转换成sensor_msgs::PointCloud格式&#xff0c;再…

避免17个最常见的电子邮件营销错误

我们都曾在电子邮件营销中犯过错。你点击发送&#xff0c;随后那种沉重的感觉袭来。你搞砸了&#xff0c;现在所有人都能看到。就像把信息放入瓶子丢进互联网的浩瀚海洋中&#xff0c;无法收回。 有些电子邮件营销错误显而易见&#xff0c;可能会破坏你投入了大量心血的营销活…

多窗口联系

使用信号和槽实现多个界面的跳转 准备好两个界面 一个界面准备好信号 一个界面准备好槽 连接两个界面的信号和槽 主界面的头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Wi…

俄罗斯电商没有技巧,OZON换季相关爆品

Top1 加热器 Обогреватель кварцевый напольный ИЖЭКО М 800 вт СВ01 энергосберегающий электрообогреватель 商品id&#xff1a;1352359815 月销量&#xff1a;781 OZON选品分析工具&#…

Xilinx系FPGA学习笔记(六)RAM的IP核学习

系列文章目录 文章目录 系列文章目录块RAM生成 块RAM生成 对于RAM来说&#xff0c;也有两种: 在 Memories & Storage Elements 下&#xff0c;一个是 Distributed Memory Generator&#xff0c;另一个是 BlockMemory Generator&#xff0c;这与ROM是类似的 这里的常规接口…