Day31|贪心算法1

news2025/6/3 13:51:02

贪心的本质是选择每一阶段的局部最优,从而达到全局最优。

无固定套路,举不出反例,就可以试试贪心。

一般解题步骤:

1.将问题分解成若干子问题

2.找出适合的贪心策略

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

4.将局部最优解堆叠成全局最优解

分发饼干

思路:为了满足更多的小孩,就不要造成饼干尺寸的浪费,大尺寸的饼干既可以满足胃口大的孩子,也可以满足胃口小的孩子,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。可以尝试使用贪心策略,先将饼干数组和小孩数组进行排序。然后从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量。

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;
   }
};

从代码中可以看出,index用来控制饼干数组的遍历,遍历饼干没有再起一个循环,而是采用自减的方式,这是常用的技巧。

不可以先遍历比骨干再遍历胃口,因为外面for,i是固定移动的,if的index才是符合条件移动的。

 反过来,先满足胃口小的,从小到大去满足:

class Solution{
public:
   int findContentChildren(vector<int>& g,vector<int>&s){
    sort(g.begin(),g.end());
    sort(s.begin(),s.end());
    int index = 0;
    for(int i = 0; i < size(); i++){
        if(index < g.size() && g[index] <= s[i]){
            index++;
        }
    }
    return index;
   }
};
//思路一
class Solution{
  public int findContentChildren(int[] g, int[] s){
    Arrays.sort(g);
    Arrays.sort(s);
    int start = 0;
    int count = 0;
    for(int i = 0; i < s.length && start < g.length; i++){
      if(s[i] >= g[start]){
        start++;
        count++;
      }
    }
    return count;
  }
}
class Solution{
  public int findContentChildren(int[] g,int[] s){
    Arrays.sort(g);//排序胃口
    Arrays.sort(s);//排序饼干
    int count = 0;
    int start = s.length - 1;//胃口数组长度,从start开始遍历,倒着遍历,先考虑胃口大的
    //遍历胃口,从大到小
    for(int index = g.length - 1;index >= 0;index--){
      if(start >= 0 && g[index] <= s[start]){
        start--;//从大到小
        count++;//满足一个计数+1
      }
    }
    return count;//返回计数
  }
}

摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在地话),可能是正数或负数,少于两个元素的序列也是摆动序列。

给定一个整数序列,返回作为摆动序列的最长子序列的长度。通过从原始序列中删除一些元素来获得子序列,剩下的元素保持其原始顺序。

思路:

贪心

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

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

实际操作中,删除操作都不用,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)

这就是贪心所贪的地方, 让峰值尽可能地保持峰值,然后删除单一坡度上的节点。

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

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

1.上下坡有平坡

[1,2,2,2,2,1]删除左边的三个2,或者删除右边的三个2,摆动长度为3

当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) 

2.数组首尾两端

本题统计峰值的时候,数组最左面和最右面如何统计。

当有两个不同的元素时,摆动序列也是2.

例如[2,5],如果靠统计差值来计算峰值个数,就需要考虑数组最左面和最右面的特殊情况。

因为我们在计算prediff(nums[i] - nums[i - 1])和curdiff(nums[i+1] - nums[i])的时候,至少需要三个数字才能计算,而数组只有两个数字。这里如果只有两个数字,且是不同的元素,那结果为2.

3.单调坡中有平坡

之前我们在讨论 情况一 :相同数字练习的时候,prediff = 0,curdiff < 0或者>0也记为波谷

为了统一规则。针对序列[2,5],可以假设为[2,2,5],这样就有了坡度,即preDiff = 0.

[2,2,5]

针对以上情形,result初始值为1,此时curDiff > 0&&preDiff<=0,那么result++(计算了左面的峰值),最后得到结果为2(峰值个数为2即摆动序列长度为2)

class Solution{
public:
   int wiggleMaxLength(vector<int>&nums){
    if(num.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;
    }
   };
}

3.在上面解法中,忽略了第三种情况,即如果在一个单调坡度上有平坡,例如[1,2,2,2,3,4]

图中我们可以看出,应该记录2,单调中的平坡不能算作峰值(摆动)

 需要在坡度摆动变化时,更新prediff,这样prediff在单调区间有平坡的时候就不会发生变化,造成误判。

class Solution{
public:
     int wiggleMaxLength(vctor<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;
     }
};

用动态规划求解

思路:

对于我们当前考虑的这个数,要么是作为山峰(nums[i] > nums[i - 1]),要么是作为山谷(即nums[i] < nums[i-1])

设dp状态dp[i][0],表示考虑前i个数,第i个数作为山峰的摆动子序列的最长长度。

设dp状态为dp[i][1],表示考虑前i个数,第i个数作为山谷的摆动子序列的最长长度

//设dp状态dp[i][0],表示考虑前i个数,第i个数作为山峰的摆动子序列的最长长度
//设dp状态dp[i][1],表示考虑前i个数,第i个数作为山谷的摆动子序列的最长长度
class Solution{
public:
   int wiggleMaxLength(vector<int>&nums){
    memset(dp,0,sizeof dp);
    dp[0][0] = dp[0][1] = 1;
    for(int i = 1;i < nums.size(); ++i){
        dp[i][0] = dp[i][1] = 1;
        for(int j = 0;j < i;++j){
            if(nums[j] > nums[i])dp[i][1] = max(dp[i][1],dp[j][0]+1);
        }
        for(int j = 0;j < i; ++j){
            if(nums[j] < nums[i])dp[i][0] = max(dp[i][0],dp[j][1] + 1);
        }
    }
    return max(dp[nums.size() - 1][0],dp[nums.size() - 1][1]);
   }
};

最大子序和

//记录局部最优,推出全局最优,相当于暴力求解+调整子区间起始位置,用了一个result来更新和记录最大结果count
class Solution{
    public:
         int maxSubArray(vector<int>&nums){
            int count = 0;
            for(int i = 0;i < nums.size(); i++){
                count += nums[i];
                if(count > result){
                    result = count;//更新最大值
                }
                if(count <= 0)count = 0;//重置最大子序列的初始位置
            }
            return result;
         }
};

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

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

相关文章

Unity2023.1.19_ECS_DOTS

Unity2023.1.19_ECS_DOTS 盲学-盲目的学习&#xff1a; 懒着自己整理就看看别人整理的吧&#xff0c;整合一下逻辑通了不少&#xff1a; DOTS/data oriented technology stack-面向数据的技术栈 ECS/Entities-Component-System Unity-Entities包 Entities提供ECS架构面向数…

C语言操作符详解(一)

一、操作符的分类 • 算术操作符&#xff1a; 、- 、* 、/ 、% • 移位操作符:<< >> • 位操作符: & | ^ • 赋值操作符: 、 、 - 、 * 、 / 、% 、<< 、>> 、& 、| 、^ • 单⽬操作符&#xff1a; &#xff01;、、--、&、*、、…

蓝桥杯练习系统(算法训练)ALGO-987 强力党逗志芃

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 逗志芃励志要成为强力党&#xff0c;所以他将身上所以的技能点都洗掉了重新学技能。现在我们可以了解到&#xff0c;每个技…

express+mysql+vue,从零搭建一个商城管理系统9--添加商户

提示&#xff1a;学习express&#xff0c;搭建管理系统 文章目录 前言一、新建models/shop.js二、新建routes/shop.js三、修改routes下的index.js四、添加商户总结 前言 需求&#xff1a;主要学习express&#xff0c;所以先写service部分 一、新建models/shop.js models/shop.…

Python数据分析案例38——我国个人工作总收入影响因素分析

案例背景 偶然之间找到了CSFP(中国家庭追踪调查)的数据集&#xff0c;一个很全的家庭调查数据集。所以就想对大家现在最关心的工资和其影响因素做一点分析。 得到的结论还挺有价值的&#xff0c;有符合逻辑的&#xff0c;也有反直觉的。 数据来源 CFPS由北京大学中国社会科学…

element loading遮罩层添加按钮

<el-table v-loading"loadingText" element-loading-text"拼命加载中" :data"tableData" :tableColumn"tableColumn" :span-method"objectSpanMethod" border :cell-style"cellStyle" :header-cell-style"…

现代信号处理学习笔记(三)信号检测

通过观测数据判断信号是否存在&#xff0c;这一问题称为信号检测。 目录 前言 一、统计假设检验 1、信号检测的基本概念 2、信号检测理论测度 比率测度 概率测度 3、决策理论空间 二、概率密度函数与误差函数 1、概率密度函数 2、误差函数与补余误差函数 三、检测概…

第二证券|飞行汽车最大订单诞生,万亿级产业待起飞!概念股早盘大涨

开年以来&#xff0c;飞翔轿车赛道利好不断。 飞翔轿车草创公司斩获大订单 据媒体报道&#xff0c;美国飞翔轿车草创公司Alef Aeronautics表明&#xff0c;其电动笔直起降&#xff08;eVTOL&#xff09;飞翔器的预定最近创下了新纪录&#xff0c;订单量已到达2850份。埃隆马斯…

Cesium绘制带有方向的线

export const MAP_3D_BEGIN_CALC (lineStringData, geoData) > {// 画方向线map.entities.add({name: uav-tmp-line,polyline: {positions: Cesium.Cartesian3.fromDegreesArray(lineStringData),material: new Cesium.PolylineArrowMaterialProperty(Cesium.Color.RED),//…

windows下tensorflow-gpu2.5+cudn11.2+cudnn8.1环境配置

1.下载visualStidio2019&#xff08;cudn要用到&#xff09; 要下载2019版本&#xff0c;2022好像不很适配&#xff0c;cudn11.2以上的版本或许可以尝试 visualstidio官网是2022版本&#xff0c;找2019的下载Visual Studio 2019 版本 16.11 发行说明 | Microsoft Learn 勾选…

【C语言】Leetcode 206.反转链表

博主主页&#xff1a;17_Kevin-CSDN博客 收录专栏&#xff1a;《Leetcode》 题目 解决思路 思路一&#xff1a;翻转链表 struct ListNode* reverseList(struct ListNode* head) {if(head NULL){return NULL;}struct ListNode* n1 NULL,*n2 head,*n3 n2 -> next;while(…

ChatGPT Plus 如何开启插件

ChatGPT Plus 如何开启插件 购买完 ChatGPT Plus 会员之后&#xff0c;需要手动开启才能使用 GPT 的插件和 Code interpreter服务。 ​ 具体步骤如下&#xff1a; 1. 进入设置 点击左下角个人邮箱的位置&#xff0c;在弹窗中选择 Settings &Beta 2. 开启选项 在设置选…

紫光展锐T618_4G安卓核心板方案定制

紫光展锐T618核心板是一款采用纯国产化方案的高性能产品&#xff0c;搭载了开放的智能Android操作系统&#xff0c;并集成了4G网络&#xff0c;支持2.5G5G双频WIFI、蓝牙近距离无线传输技术以及GNSS无线定位技术。 展锐T618核心板应用旗舰级 DynamlQ架构 12nm 制程工艺&#x…

以线缆行业为例,工业智能网关的实际应用及其带来的变革-天拓四方

工业智能网关是一种集数据采集、传输、处理和分析于一体的智能化设备。它能够实现对工业现场各种传感器、执行器等设备的数据进行实时采集&#xff0c;并通过网络传输到云端或本地数据中心进行分析处理。同时&#xff0c;工业智能网关还具备边缘计算能力&#xff0c;能够在本地…

Domain Adaptation Vs. Prompt-Tuning:能否用域自适应解决大模型提示学习问题?

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 作者简介 李江梦&#xff0c;中国科学院软件研究所天基综合信息系统全国重点实验室助理研究员 论文简介 今天介绍的是被机器学习领域顶级学术会议ICLR 2024接收的论文&#xff1a;BayesPrompt: Prompting Large…

国创证券|AI手机PC概念拉升,福蓉科技4连板,思泉新材大涨

AI手机PC概念大幅走高&#xff0c;到发稿&#xff0c;思泉新材涨近15%&#xff0c;盘中一度涨停&#xff1b;道明光学、福蓉科技均涨停&#xff0c;诚迈科技涨近8%&#xff0c;亿道信息涨逾6%。 值得注意的是&#xff0c;福蓉科技已接连4个交易日涨停。公司4日晚间发布危险提示…

Qt 实现橡皮擦拭显示图片

1.简介 在一些游戏中看见类似解密破案的效果&#xff0c;使用手触摸去擦拭图片上的灰尘&#xff0c;然后显示最终的图片&#xff0c;所以也想试试Qt实现的效果。大家有自己想做的效果&#xff0c;都可以尝试。 以下是效果展示图。 可以控制橡皮擦的大小&#xff0c;进行擦拭…

nginx 配置404 及 nginx demo

郭永坤123/nginx-demo nginx demo&#xff1a; 包含 &#xff1a; 负载均衡 自定义conf 反向代理

基于Springboot的助农管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的助农管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

Linux系统使用宝塔面板安装MySQL服务并实现公网远程访问本地数据库【内网穿透】

文章目录 前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 宝塔面板的简易操作性,使得运维难度降低,简化了Linux命令行进行繁琐的配置,下面简单几步,通过宝塔面板cp…