贪心算法~~

目录

一、理论基础

二、题目练习

(1)455. 分发饼干

(2)53. 最大子数组和 - 力扣

(3)122. 买卖股票的最佳时机 II - 力扣(LeetCode)

(4)860. 柠檬水找零 - 力扣(LeetCode)

(5)905. 区间选点 - AcWing题库

 (6)AcWing 908. 最大不相交区间数量

 (7)906. 区间分组 - AcWing题库

 (8)907. 区间覆盖 - AcWing题库

 (9)148. 合并果子 - AcWing题库

 (10)913. 排队打水 - AcWing题库

(11)104. 货仓选址 - AcWing题库

一、理论基础

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

        例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿?

指定每次拿最大的,最终结果就是拿走最大数额的钱。

每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。

        再举一个例子如果是 有一堆盒子,你有一个背包体积为n,如何把背包尽可能装满,如果还每次选最大的盒子,就不行了。这时候就需要动态规划


> 什么时候用贪心?

        hhh卡哥说没有具体场景,,手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心。贪心有时候就是常识性的推导,所以会认为本应该就这么做!

> 一般解题步骤?

  • 将问题分解为若干个子问题
  • 找出适合的贪心策略
  • 求解每一个子问题的最优解
  • 将局部最优解堆叠成全局最优解

确实过于理论化。。。。~一般都会涉及到排序 、找规律、反证其可行性

 我们直接练题!!!

二、题目练习

(1)455. 分发饼干

        局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩

最终代码:

class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {//给孩子和饼干排序sort(g.begin(),g.end());sort(s.begin(),s.end());int res=0;int index=s.size()-1;//将大饼干优先分给胃口大的孩子for(int i=g.size()-1;i>=0;i--)//遍历胃口{if(index>=0&&s[index]>=g[i]) //遍历饼干 {index--; //可以分配就指向下一个更大的饼干 res++;}}return res;}
};

 感觉还挺简单的,难在找到他的局部最优性质

(2)53. 最大子数组和 - 力扣

解法一: 可以暴力,但是时间复杂度会高

 解法二:dp,之前我们有做过~

解法三:贪心

        如果 -2 1 在一起,计算起点的时候,一定是从 1 开始计算,因为负数只会拉低总和,这就是贪心贪的地方!局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。

遍历 nums,从头开始用 count 累积,如果 count 一旦加上 nums[i]变为负数,那么就应该从 nums[i+1]开始从 0 累积 count 了,因为已经变为负数的 count,只会拖累总和。

 

class Solution {
public:int maxSubArray(vector<int>& nums) {int res=INT_MIN; //一个很小的负数int cnt=0;for(int i=0;i<nums.size();i++){cnt+=nums[i];if(cnt>res)res=cnt;if(cnt<=0) cnt=0; //加上之后非正了,cnt=0相当于重置最大子序起始位置}return res;}
};

(3)122. 买卖股票的最佳时机 II - 力扣(LeetCode)

在dp中我们也做过这道题~~,找到局部最优性质后,用贪心更简单一点 

局部最优:收集每天的正利润,全局最优:求得最大利润

是不是特别简单哈哈哈

class Solution {
public:int maxProfit(vector<int>& prices) {int result = 0;for (int i = 1; i < prices.size(); i++) {result += max(prices[i] - prices[i - 1], 0);}return result;}
};

(4)860. 柠檬水找零 - 力扣(LeetCode)

 

只需要维护三种金额的数量,5,10和20。

  • 情况一:账单是5,直接收下。
  • 情况二:账单是10,消耗一个5,增加一个10
  • 情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5

账单是20的情况,为什么要优先消耗一个10和一个5呢?

        因为美元10只能给账单20找零,而美元5可以给账单10和账单20找零,美元5更万能!

所以局部最优:遇到账单20,优先消耗美元10,完成本次找零。全局最优:完成全部账单的找零。

class Solution {
public:bool lemonadeChange(vector<int>& bills) {int five = 0, ten = 0, twenty = 0;for (int bill : bills) {// 情况一if (bill == 5) five++;// 情况二if (bill == 10) {if (five <= 0) return false; //找不了ten++;five--;}// 情况三if (bill == 20) {// 优先消耗10美元,因为5美元的找零用处更大,能多留着就多留着if (five > 0 && ten > 0) {five--;ten--;twenty++; // 其实这行代码可以删了,因为记录20已经没有意义了,不会用20来找零} else if (five >= 3) {five -= 3;twenty++; // 同理,这行代码也可以删了} else return false;}}return true;}
};

 

(5)905. 区间选点 - AcWing题库

 

 数轴上有一些区间,在数轴上选取几个点,要求每个区间上最少有一个点。

     

        

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
struct Range
{int l, r; //左右结点bool operator< (const Range &W)const{return r < W.r; //按照右端点从小到大排序}
}range[N];int main()
{scanf("%d", &n);for (int i = 0; i < n; i ++ ) cin>>range[i].l>>range[i].r;sort(range, range + n);int res = 0, ed = -2e9;for (int i = 0; i < n; i ++ )if (ed < range[i].l) //新的左端点不能覆盖右端点{res ++ ; //需要新增一个结点ed = range[i].r; //更新右端点}cout<<res;return 0;
}

 (6)AcWing 908. 最大不相交区间数量

 与上一道区间选点的题一样,一定要是对右端点从小到大排序!!!!

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
struct Range
{int l, r; //左右结点bool operator< (const Range &W)const{return r < W.r; //按照右端点从小到大排序}
}range[N];int main()
{scanf("%d", &n);for (int i = 0; i < n; i ++ ) cin>>range[i].l>>range[i].r;sort(range, range + n);int res = 0, ed = -2e9;for (int i = 0; i < n; i ++ )if (ed < range[i].l) //新的左端点不能覆盖右端点{res ++ ; //需要新增一个结点ed = range[i].r; //更新右端点}cout<<res;return 0;
}

 (7)906. 区间分组 - AcWing题库

 等效于把尽可能多的区间塞进同一组,要满足range[i].l > heap.top

  1. 把所有区间按照左端点从小到大排序
  2. 从前往后枚举每个区间,判断此区间能否将其放到现有的组中
  3. heap有多少区间,就有多少组
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
struct Range
{int l, r;bool operator< (const Range &W)const{return l < W.l; //按照左端点排序!!!!}
}range[N];int main()
{cin>>n;for (int i = 0; i < n; i ++ ){int l, r;cin>>l>>r;range[i] = {l, r};}sort(range, range + n);//小根堆(每次弹出最小的数)--每个组的右端点存储在 heap 中priority_queue<int, vector<int>, greater<int>> heap;for (int i = 0; i < n; i ++ ){//新区间的左端点大于等于堆顶的右端点if (heap.empty() || heap.top() >= range[i].l){heap.push(range[i].r); //开一个新组,记录其右端点}else { //可以合并heap.pop();//取出右端点最小的区间heap.push(range[i].r);//保留这个右端点较大的区间}}cout<<heap.size();return 0;
}

 (8)907. 区间覆盖 - AcWing题库

 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=1e9+10;
#define PII pair<int ,int>
PII a[N];
int s,t,n;
int main()
{cin>>s>>t;cin>>n;for(int i=0;i<n;i++){cin>>a[i].first>>a[i].second;}sort(a,a+n);int res=0;bool flag=false;//默认无法完全覆盖for(int i=0;i<n;i++){int j=i,r=-M;while(j<n&&a[j].first<=s){r=max(r,a[j].second);j++;}if(r<s) {res=-1;break;}res++;//最后更新的右端点大于给定区间---能覆盖if(r>=t) {flag=true;break;}s=r;//每次更新左端点为能覆盖给定区间的最大的右端点i=j-1;}if(!flag) res=-1;cout<<res;return 0;}

 (9)148. 合并果子 - AcWing题库

 

在学优先队列的时候做过这道题~~

priority_queue 优先队列-CSDN博客

#include<bits/stdc++.h>
using namespace std;
using ll =long long;
ll ans;
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int n;cin>>n;priority_queue<ll,vector<ll>,greater<ll>> pq;while(n--){ll x;cin>>x;pq.push(x);}while(pq.size()>=2){ll x=pq.top();pq.pop();ll y=pq.top();pq.pop();ans+=x+y;pq.push(x+y);}cout<<ans;return 0;
}

 (10)913. 排队打水 - AcWing题库

需要将打水时间最短的人先打水 --计算前缀和数组的和(不包含最后一个人)

 

#include<bits/stdc++.h>
using namespace std;
using LL=long long;
int main()
{int n;cin>>n;vector<LL> a(n+1);vector<LL> qz(n+1,0);//前缀和数组for(int i=1;i<=n;i++) cin>>a[i];//从小到大排序sort(a.begin(),a.end());//计算排序后的前缀和数组(不用计算最后一个)for(int i=1;i<n;i++) qz[i]=qz[i-1]+a[i];//求前缀和的sumcout<<accumulate(qz.begin()+1,qz.end(),0ll);return 0;
}

(11)104. 货仓选址 - AcWing题库

贪心策略:一开始自己也猜到了哈哈哈就是中位数

 排序 +中位数

#include <bits/stdc++.h>
using namespace std;
const int N=100100;
int a[N],n,i,ans,sum;
int main()
{cin>>n;for (i=1;i<=n;i++)cin>>a[i];sort(a+1,a+1+n);//排序int sm=a[n/2+1];//中位数for (i=1;i<=n;i++)ans=ans+abs(a[i]-sm);//统计和中位数之间的差cout<<ans;return 0;
}

 

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

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

相关文章

形象解释 HTTP 的四种常见请求方式及其中的区别联系

HTTP 的常见请求方式常见的有四种&#xff1a;GET、POST、PUT、DELETE&#xff0c;它们各自的功能不一样。 &#x1f35c; 场景比喻&#xff1a;HTTP 请求像“去餐厅点菜” 请求方式行为餐厅比喻说明GET获取数据看菜单/问服务员&#xff1a;你们有什么菜&#xff1f;不带食材、…

string的基本使用

string的模拟实现 string的基本用法string的遍历&#xff08;三种方式&#xff09;&#xff1a;关于auto&#xff08;自动推导&#xff09;:范围for: 迭代器普通迭代器(可读可改&#xff09;const迭代器&#xff08;可读不可改&#xff09; string细小知识点string的常见接口引…

kubernetes》》k8s》》证书有效期

cd /etc/kubernetes/pki openssl x509 -in apiserver.crt -text -noount通常&#xff0c;Kubernetes的证书是由kubeadm生成的&#xff0c;所以可能需要修改kubeadm的源码或者配置 登录Master节点 》》》默认延续1年 # 查看证书 检查证书有效期 # 该命令显示 /etc/kubernetes…

LangChain LCEL表达式语言简介

LangChain表达式语言&#xff08;LCEL&#xff09;是专为构建AI应用链设计的声明式编程框架&#xff0c;通过管道符|实现组件无缝衔接&#xff0c;支持流式处理、异步调用等生产级特性。其核心优势在于零代码改动实现原型到生产的过渡&#xff0c;同时保持代码简洁性和可维护性…

【计算机视觉】CV实践项目- 基于PaddleSeg的遥感建筑变化检测全解析:从U-Net 3+原理到工程实践

基于PaddleSeg的遥感建筑变化检测全解析&#xff1a;从U-Net 3原理到工程实践 技术背景与项目意义传统方法的局限性深度学习的优势 核心技术与算法原理U-Net 3架构创新全尺度跳跃连接深度监督机制 变化检测技术路线 实战指南&#xff1a;从环境搭建到模型部署环境配置数据准备与…

万字长文 | Apache SeaTunnel 分离集群模式部署 K8s 集群实践

文章作者&#xff1a;雷宝鑫 整理排版&#xff1a;白鲸开源 曾辉 Apache SeaTunnel官网链接: https://seatunnel.apache.org/ Apache SeaTunnel(以下简称SeaTunnel&#xff09;是一款新一代高性能、分布式的数据集成同步工具&#xff0c;正受到业界广泛关注和应用。SeaTunnel支…

深入解析YOLO v1:实时目标检测的开山之作

目录 YOLO v1 算法详解​ ​1. 核心思想​ ​2. 算法优势​ ​3. 网络结构&#xff08;Unified Detection&#xff09;​​ ​4. 关键创新​ ​5. 结构示意图&#xff08;Fig1&#xff09;​ Confidence Score 的计算​ 类别概率与 Bounding Box 的关系​ 后处理&…

信令与流程分析

WebRTC是h5支持的重要特征之一&#xff0c;有了它&#xff0c;不再需要借助音视频相关的客户端&#xff0c;直接通过浏览器的Web页面就可以实现音视频聊天功能。 WebRTC项目是开源的&#xff0c;我们可以借助WebRTC&#xff0c;构建自己的音视频聊缇娜功能。无论是前端JS的Web…

BIOS主板(非UEFI)安装fedora42的方法

BIOS主板(非UEFI)安装fedora42的方法 现实困难&#xff1a;将Fedora-Workstation-Live-42-1.1.x86_64.iso写入U盘制作成可启动U盘启动fedora42&#xff0c;按照向导将fedora42安装到真机的sda7分区中得到报错如下内容&#xff1a; /boot/efi 必需的 /boot/efi必须位于格式化为e…

安卓 Compose 相对传统 View 的优势

安卓 Compose 相对传统 View 的优势 文章目录 安卓 Compose 相对传统 View 的优势1. 引言2. 核心概念&#xff1a;Compose的革新性设计2.1 Jetpack Compose2.2 传统安卓View系统 3. 开发体验&#xff1a;Compose大幅提升效率3.1 使用Jetpack Compose构建UI3.2 使用传统View系统…

SIEMENS PLC 程序 GRAPH 程序解读 车型入库

1、程序载图1 2、程序截图2 3、程序解释 这是一个基于西门子 GRAPH 编程的车型 1 入库顺序控制流程图&#xff0c;通过状态机结构&#xff08;状态框 S 与转移条件 T&#xff09;描述完整工作流程&#xff0c;具体如下&#xff1a; 整体流程概述 初始化&#xff1a;从 S1&am…

VuePress可以做什么?

VuePress 可以做什么 VuePress 是一个基于 Vue.js 的静态站点生成器,专注于文档和内容展示。它结合了 Markdown 的简洁性和 Vue 的灵活性,适合多种场景的开发需求。以下是 VuePress 的主要用途和功能: 1. 技术文档网站 VuePress 最初是为编写 Vue.js 官方文档而设计的,因…

架构-系统可靠性分析与设计

一、可靠性相关基本概念 1. 可靠性与可用性 可靠性&#xff1a;软件系统在遇到错误、意外操作或系统故障时&#xff0c;仍能维持自身功能特性的能力。 举例&#xff1a;手机银行APP在用户误操作&#xff08;如快速点击多次转账&#xff09;时&#xff0c;仍能正确处理交易并避…

再谈String

1、字符串常量池 1.1 创建对象的思考 下面是两种创建字符串对象的代码 public static void main1(String[] args) {String s1 "hello";String s2 "hello";System.out.println(s1 s2);//trueString s3 new String("hello");String s4 new …

《深入浅出ProtoBuf:从环境搭建到高效数据序列化》​

ProtoBuf详解 1、初识ProtoBuf2、安装ProtoBuf2.1、ProtoBuf在Windows下的安装2.2、ProtoBuf在Linux下的安装 3、快速上手——通讯录V1.03.1、步骤1&#xff1a;创建.proto文件3.2、步骤2&#xff1a;编译contacts.proto文件&#xff0c;生成C文件3.3、步骤3&#xff1a;序列化…

基于PHP+Uniapp的互联网医院源码:电子处方功能落地方案

随着“互联网医疗”政策红利持续释放&#xff0c;互联网医院已成为推动医疗数字化转型的重要方向。在这一趋势下&#xff0c;电子处方功能模块作为核心环节&#xff0c;不仅直接关系到线上问诊闭环的实现&#xff0c;也成为系统开发中技术难度较高、业务逻辑最为复杂的一部分。…

ARM Cortex-M (STM32)如何调试HardFault

目录 步骤 1: 实现一个有效的 HardFault 处理程序 步骤 2: 复现 HardFault 并使用调试器分析 步骤 3: 解读故障信息 步骤 4: 定位并修复源代码 HardFault 是 ARM Cortex-M 处理器中的一种异常。当处理器遇到无法处理的错误&#xff0c;或者配置为处理特定类型错误&#xff…

基于归纳共形预测的大型视觉-语言模型中预测集的**数据驱动校准**

摘要 本研究通过分离共形预测&#xff08;SCP&#xff09;框架&#xff0c;解决了大型视觉语言模型&#xff08;LVLMs&#xff09;在视觉问答&#xff08;VQA&#xff09;任务中幻觉缓解的关键挑战。虽然LVLMs在多模态推理方面表现出色&#xff0c;但它们的输出常常表现出具有…

LangChain4j 搭配 Kotlin:以协程、流式交互赋能语言模型开发

Kotlin 支持 | LangChain4j Kotlin 是一种面向 JVM&#xff08;及其他平台&#xff09;的静态类型语言&#xff0c;能够实现简洁优雅的代码&#xff0c;并与 Java 库无缝互操作。 LangChain4j 利用 Kotlin 扩展和类型安全构建器来增强 Java API&#xff0c;为其增添特定于 Ko…

正大模型视角下的市场结构判断逻辑

正大模型视角下的市场结构判断逻辑 在多数交易策略中&#xff0c;结构识别往往先于方向判断。以正大的数据研判风格为例&#xff0c;其核心逻辑是&#xff1a;价格行为不能孤立解读&#xff0c;必须结合时间与成交效率来判断当前结构的有效性。 例如&#xff0c;一个上涨过程&…