Day31|贪心算法1

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

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

一般解题步骤:

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言第三十五弹---文件操作(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 文件操作 1、为什么使用文件&#xff1f; 2、什么是文件&#xff1f; 2.1、程序文件 2.2、数据文件 2.3、文件名 3、二进制文件和文本文件 4、文件的打开和…

YOLO v9训练自己数据集

原以为RT-DETR可以真的干翻YOLO家族&#xff0c;结果&#xff0c;&#xff01;&#xff01;&#xff01;&#xff01; 究竟能否让卷积神经网络重获新生&#xff1f; 1.数据准备 代码地址&#xff1a;https://github.com/WongKinYiu/yolov9 不能科学上网的评论区留言 数据集…

【Python】新手入门(2):避免将关键字作为标识符

Python新手入门&#xff08;2&#xff09;&#xff1a;避免将关键字作为标识符 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1…

蓝桥杯-单片机组基础7-存储器映射扩展与PWM脉冲调制(附小蜜蜂课程代码)

蓝桥杯单片机组备赛指南请查看这篇文章&#xff1a;戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写&#xff0c;代码可直接在比赛开发板上使用。 型号&#xff1a;国信天长4T开发板&#xff08;绿板&#xff09;&#xff0c;芯片&#xff1a;IAP15F2K6…

【Python】matplotlib绘制图像时增加颜色条

一、需求 plt.imshow()是matplotlib中的一个函数&#xff0c;用于显示图像。它可以传递一个二维或三维数组作为image参数&#xff0c; 并将图像数据显示为图形&#xff0c;并对图像进行不同的可视化设置。 在显示的过程中&#xff0c;我们如果需要增加一个图例显示颜色条&…

Word转Excel怎么操作?4个实用技巧别忘了!

“我在处理一个Word文件时&#xff0c;需要将里面的一些表格内容转化为Excel。有什么比较好用的Word转Excel方法可以推荐吗&#xff1f;” 在互联网时代&#xff0c;数据处理和信息整合是工作中不可或缺的一部分。有时&#xff0c;我们可能会遇到需要将Word文档中的数据或内容转…

高性能深度学习库luminal

一、概述 Luminal是一个深度学习库&#xff0c;它使用可组合的编译器来实现高性能。 当前的机器学习库往往很庞大复杂&#xff0c;因为它们试图直接将高级操作映射到底层手工编写的内核上&#xff0c;并且专注于立刻执行&#xff08;eager模式&#xff09;。像PyTorch这样的库…

Java Web开发---复试Tips复习

&#xff08;自用&#xff0c;摘录自各种文章和自己总结&#xff09; 小知识点理解 Web Web应用开发主要是基于浏览器的应用程序开发。一个Web应用由多部分组成 Web应用程序编写完后&#xff0c;若想提供给外界访问&#xff0c;需要服务器来统一管理 常用的动态网页语言——…

react native中如何使用webView调用腾讯地图选点组件

react native中如何使用webView调用腾讯地图选点组件 效果示例图代码示例备注 效果示例图 代码示例 import React, {useEffect, useRef, useState} from react; import {Modal, StyleSheet} from react-native; import {pxToPd} from ../../common/js/device; import {WebView…

私有化部署自己的ChatGPT,免费开源的chatgpt-next-web搭建

随着AI的应用变广&#xff0c;各类AI程序已逐渐普及&#xff0c;尤其是在一些日常办公、学习等与撰写/翻译文稿密切相关的场景&#xff0c;大家都希望找到一个适合自己的稳定可靠的ChatGPT软件来使用。 ChatGPT-Next-Web就是一个很好的选择。它是一个Github上超人气的免费开源…

产品介绍二维码怎么做?多种内容组合二维码的方法

现在扫描二维码来获取内容的方式越来越常见&#xff0c;比如很多的产品介绍都会做成二维码图片后&#xff0c;在产品包装、传单、展板等印刷展示。而一般展示的内容类型多为文本、图片、视频等内容&#xff0c;那么这些类型的内容放入一个二维码中展示如何实现呢&#xff1f; …

白酒:制曲工艺的环境因素与微生物生态关系

在豪迈白酒的酿造过程中&#xff0c;制曲工艺是非常关键的一环。而环境因素与微生物生态关系对于制曲工艺的成功与否起着决定性的作用。云仓酒庄深谙此道&#xff0c;在制曲过程中注重环境因素的调控&#xff0c;并深入研究微生物生态关系&#xff0c;以提升豪迈白酒的品质和风…

Jmeter 命令启动 —— 动态参数化!

Jmeter命令行参数 1、在Linux中&#xff0c;使用非GUI的方式执行Jmeter。若需更改参数&#xff0c;必须先编辑jmx文件&#xff0c;找到对应变量进行修改&#xff0c;比较麻烦。 因此&#xff0c;可以参数化一些常用的变量&#xff0c;直接在Jmeter命令行进行设置 2、参数 -J…

draw.io设置矩形四个边的有无

第一步创建一个矩形 选中矩形&#xff0c;并编辑样式 然后在编辑框中输入 verticalLabelPositionbottom;verticalAligntop;html1;shapemxgraph.basic.rect;right1;将原来的内容覆盖掉 然后点击应用 然后发现 点击那四个设置就可以了

MyCAT集群——MyCAT2如何配置读写分离

先搭载MySQL一主两从 192.168.20.110MyCAT192.168.20.111Master192.168.20.112slave1192.168.20.113slave2 配置就不写了&#xff0c;比较基础&#xff0c;写一下步骤 1.进入mysql配置文件或者其子配置文件&#xff0c;添加server_id,开启gtidgtid_modeON,enforce-gtid-cons…

智慧公厕:改变城市公共卫生管理的未来

现代城市发展快速&#xff0c;人口不断增加&#xff0c;公共卫生管理面临着严峻的挑战。传统公厕的建设、管理和使用模式已经无法满足日益提高的卫生与环保需求。然而&#xff0c;随着科技的进步与智能化的发展&#xff0c;智慧公厕正成为一种全新的解决方案&#xff0c;为城市…

(十六)【Jmeter】取样器(Sampler)之测试活动(Test Action)

简述 操作路径如下: JMeter中的测试活动取样器实际上并不是一个具体的取样器类型,而是一种对测试计划中的多个取样器进行组合和执行的活动。常常被用作定时器,在某个请求之后等待多长时间。 参数说明 Logical Action on Thread(在线程上的逻辑操作) Pause Duration(mil…

Python知识汇总

重要链接&#xff1a; matplotlib库&#xff1a;matplotlib — Matplotlib 3.5.1 documentation DataFrame库&#xff1a;DataFrame — pandas 2.2.1 documentation (pydata.org) Python Matplotlib 实现散点图、曲线图、箱状图、柱状图示例&#xff1a;Python Matplotlib 实…

计算机网络-网络安全(二)

1.应用层安全协议&#xff1a; S-HTTP或SHTTP&#xff08;Sec HTTP&#xff09;&#xff0c;安全超文本传输协议&#xff0c;是HTTP扩展&#xff0c;使用TCP的80端口。HTTPS&#xff1a;HTTPSSL&#xff0c;使用TCP的443端口。和TLS&#xff08;传输层安全标准&#xff09;是双…

Linux conntrack和iptables技术解析

Linux虚拟文件系统管理技术 1. netfilter解析1.1 netfilter的基础原理1.2 netfilter的相关hook 2. conntrack解析2.1 conntrack的基础原理2.2 conntrack的表记录解析 3. iptables解析3.1 iptables基础原理3.2 融合conntrack表的iptables规则 4. 疑问和思考4.1 conntrack和iptab…