当前位置: 首页 > news >正文

数据结构算法之贪心算法,贪心算法之区间调度问题

什么是贪⼼算法呢? 贪⼼算法可以认为是动态规划算法的⼀个特例, 相⽐动态规划, 使⽤贪⼼算法需要满⾜更多的条件(贪⼼选择性质) , 但是效率⽐动态规划要⾼。

⽐如说⼀个算法问题使⽤暴⼒解法需要指数级时间, 如果能使⽤动态规划消除重叠⼦问题, 就可以降到多项式级别的时间, 如果满⾜贪⼼选择性质, 那么可以进⼀步降低时间复杂度, 达到线性级别的。

什么是贪⼼选择性质呢, 简单说就是: 每⼀步都做出⼀个局部最优的选择,最终的结果就是全局最优。 注意哦, 这是⼀种特殊性质, 其实只有⼀部分问题拥有这个性质。

⽐如你⾯前放着 100 张⼈⺠币, 你只能拿⼗张, 怎么才能拿最多的⾯额? 显然每次选择剩下钞票中⾯值最⼤的⼀张, 最后你的选择⼀定是最优的。

然⽽, ⼤部分问题明显不具有贪⼼选择性质。 ⽐如打⽃地主, 对⼿出对⼉三, 按照贪⼼策略, 你应该出尽可能⼩的牌刚好压制住对⽅, 但现实情况我们甚⾄可能会出王炸。 这种情况就不能⽤贪⼼算法, ⽽得使⽤动态规划解决, 参⻅前⽂「动态规划解决博弈问题」 。

⼀、 问题概述

⾔归正传, 本⽂解决⼀个很经典的贪⼼算法问题 Interval Scheduling(区间调度问题) 。 给你很多形如 [start, end] 的闭区间, 请你设计⼀个算法,算出这些区间中最多有⼏个互不相交的区间。

int intervalSchedule(int[][] intvs) {}

举个例⼦, intvs = [[1,3], [2,4], [3,6]] , 这些区间最多有 2 个区间互不相交, 即 [[1,3], [3,6]] , 你的算法应该返回 2。 注意边界相同并不算相交。

这个问题在⽣活中的应⽤⼴泛, ⽐如你今天有好⼏个活动, 每个活动都可以⽤区间 [start, end] 表⽰开始和结束的时间, 请问你今天最多能参加⼏个活动呢? 显然你⼀个⼈不能同时参加两个活动, 所以说这个问题就是求这些时间区间的最⼤不相交⼦集。

⼆、 贪⼼解法

这个问题有许多看起来不错的贪⼼思路, 却都不能得到正确答案。 ⽐如说:也许我们可以每次选择可选区间中开始最早的那个? 但是可能存在某些区间开始很早, 但是很⻓, 使得我们错误地错过了⼀些短的区间。 或者我们每次选择可选区间中最短的那个? 或者选择出现冲突最少的那个区间? 这些⽅案都能很容易举出反例, 不是正确的⽅案。

正确的思路其实很简单, 可以分为以下三步:

  1. 从区间集合 intvs 中选择⼀个区间 x, 这个 x 是在当前所有区间中结束最早的(end 最⼩) 。

  2. 把所有与 x 区间相交的区间从区间集合 intvs 中删除。

  3. 重复步骤 1 和 2, 直到 intvs 为空为⽌。 之前选出的那些 x 就是最⼤不相交⼦集。

把这个思路实现成算法的话, 可以按每个区间的 end 数值升序排序, 因为这样处理之后实现步骤 1 和步骤 2 都⽅便很多:

【PDF格式⽆法显⽰GIF⽂件 interval/1.gif, 可移步点击数据结构算法 访问学习】

现在来实现算法, 对于步骤 1, 由于我们预先按照 end 排了序, 所以选择x 是很容易的。 关键在于, 如何去除与 x 相交的区间, 选择下⼀轮循环的 x呢?

由于我们事先排了序, 不难发现所有与 x 相交的区间必然会与 x 的 end 相交; 如果⼀个区间不想与 x 的 end 相交, 它的 start 必须要⼤于(或等于) x 的 end :
在这里插入图片描述

三、代码实现

public int intervalSchedule(int[][] intvs) {
if (intvs.length == 0) return 0;
// 按 end 升序排序
Arrays.sort(intvs, new Comparator<int[]>() {
public int compare(int[] a, int[] b) {
return a[1] - b[1];
}
});
// ⾄少有⼀个区间不相交
int count = 1;
// 排序后, 第⼀个区间就是 x
int x_end = intvs[0][1];
for (int[] interval : intvs) {
int start = interval[0];
if (start >= x_end) {
// 找到下⼀个选择的区间了
count++;
x_end = interval[1];
}
}
returncount;
}

四、应⽤举例

下⾯举例⼏道LeetCode题⽬应⽤⼀下区间调度算法。第435题,⽆重叠区间:
在这里插入图片描述

我们已经会求最多有⼏个区间不会重叠了,那么剩下的不就是⾄少需要去除的区间吗?

interaseOverlapIntervals(int[][]intervals){
intn=intervals.length;
returnn-intervalSchedule(intervals);
}

第452题,⽤最少的箭头射爆⽓球:

查看:数据结构与算法 ,查看完整技术文档和完整的数据结构算法视频教程资料,包含左神算法全部系列。

相关文章:

  • Spark Rdd之mapToPair,flatMapToPair
  • nodejs项目实例知识信息分享平台
  • Python类和对象怎么使用
  • 【我不熟悉的css 】02. 手动画一个svg图片
  • 一、特征工程
  • 超详细Redis入门教程三
  • 【Go】slice
  • 低码筑梦,扬帆起航|湘潭大学万应低代码实训营圆满结营!
  • 盲盒app系统开发功能介绍
  • Linux中磁盘管理
  • Android Studio无障碍功能
  • 计算机毕业设计 SSM+Vue美容院管理系统 美容护理管理系统 美容店系统管理Java Vue MySQL数据库 远程调试 代码讲解
  • 2022年全球及中国手术感控行业头部企业市场占有率及排名调研报告
  • 我的世界Minecraft基岩版开服服务器教程(Windows)开服器开服包下载开服网站服务器要多少钱开服核心开服端下载
  • 2022年全球及中国叔十二烷基硫醇行业头部企业市场占有率及排名调研报告
  • [译]前端离线指南(上)
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • Effective Java 笔记(一)
  • LeetCode算法系列_0891_子序列宽度之和
  • Next.js之基础概念(二)
  • python学习笔记 - ThreadLocal
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • Transformer-XL: Unleashing the Potential of Attention Models
  • Vue 2.3、2.4 知识点小结
  • 产品三维模型在线预览
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • - 概述 - 《设计模式(极简c++版)》
  • 关于springcloud Gateway中的限流
  • 浏览器缓存机制分析
  • 我的业余项目总结
  • 主流的CSS水平和垂直居中技术大全
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • #LLM入门|Prompt#3.3_存储_Memory
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (ZT)一个美国文科博士的YardLife
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (六)Hibernate的二级缓存
  • (算法)Game
  • (一)RocketMQ初步认识
  • (转载)hibernate缓存
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • ..回顾17,展望18
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .net访问oracle数据库性能问题
  • @angular/cli项目构建--http(2)
  • [23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
  • [Android]如何调试Native memory crash issue
  • [Angular] 笔记 18:Angular Router
  • [Angularjs]asp.net mvc+angularjs+web api单页应用
  • [Assignment] C++1
  • [AutoSar]工程中的cpuload陷阱(三)测试