贪心算法--区间调度问题

贪心算法

引言

贪心算法是一种简单而有效的算法设计技巧,在解决一些优化问题时具有广泛的应用。其基本思想是通过每一步的局部最优选择,最终达到全局最优解。贪心算法通常不会回溯之前的决策,而是根据当前状态作出最优决策,因此其执行效率较高。

贪心算法的应用十分广泛,涵盖了诸多领域,如图论、计算机网络、调度问题等。在某些情况下,贪心算法能够给出最优解,但也存在一些问题并不适合贪心策略的情况。因此,了解贪心算法的原理、应用场景以及适用性是十分重要的。

原理

贪心算法(Greedy Algorithm)是一种解决问题的算法范式,其基本思想是通过每一步的局部最优选择,最终达到全局最优解。在贪心算法中,每一步都选择当前情况下的最优解,并希望通过这种局部最优的选择,最终得到全局最优解。

贪心算法的核心思想可以概括为以下两点:

  1. 贪心选择性质:贪心算法每一步都做出一个局部最优的选择,即当前情况下看起来最好的选择。
  2. 最优子结构性质:当一个问题的最优解包含其子问题的最优解时,称该问题具有最优子结构性质。贪心算法通过递归地求解子问题,并利用最优子结构性质,可以保证每一步的选择都是最优的。

贪心算法通常不会回溯之前的决策,而是根据当前状态作出最优决策。这使得贪心算法执行效率较高,但也限制了其能够解决的问题范围。贪心算法通常适用于满足贪心选择性质和最优子结构性质的问题,例如最小生成树、最短路径、任务调度等。

需要注意的是,并非所有问题都适合使用贪心算法求解,因为贪心算法可能会得到局部最优解而不是全局最优解。因此,在应用贪心算法时,需要仔细分析问题的特点,确保问题满足贪心选择性质和最优子结构性质,以及贪心算法能够得到正确的解。

应用场景

贪心算法在许多领域都有广泛的应用,特别是在以下几个方面:

  1. 最小生成树: 在图论中,贪心算法经常用于构建最小生成树,例如 Prim 算法和 Kruskal 算法。这些算法通过每次选择权值最小的边来构建最小生成树,从而实现图的最优连通。
  2. 最短路径问题: 在图论中,Dijkstra 算法和 A* 算法等都是基于贪心策略的最短路径算法。它们通过每次选择当前距离最短的顶点来逐步确定起点到其他顶点的最短路径。
  3. 任务调度问题: 在任务调度问题中,贪心算法可以用于优化任务的执行顺序,以使得总执行时间最小化。例如,按照任务的截止时间或处理时间进行排序,然后依次执行。
  4. 背包问题: 在背包问题中,贪心算法可以用于近似求解,例如分数背包问题中的分数贪心算法。这种算法每次选择单位价值最高的物品放入背包中,以尽可能达到背包的容量限制并使总价值最大化。
  5. 区间调度问题: 在区间调度问题中,贪心算法可以用于确定最大数量的互不重叠的区间。例如,会议安排问题中,每次选择结束时间最早的会议安排,以尽可能安排更多的会议。
  6. Huffman 编码: Huffman 编码是一种用于数据压缩的贪心算法。它通过构建一棵最优前缀树来实现对字符的编码,使得出现频率较高的字符拥有较短的编码,从而实现数据的高效压缩。

实现贪心算法

本篇我们主要分享的是区间调度问题相关例题。

452. 用最少数量的箭引爆气球

image-20240524180422090

我们以**[[10,16],[2,8],[1,6],[7,12]]**为例:

原气球的排列为:

image-20240524190910742

题目要求求出引爆所有气球所必须射出的 最小 弓箭数

如果按照原来顺序去判断的话,很难找出有重复的气球,所以我们可以对气球先进行排序(按照左边界或者右边界排序都可以,本题我按照左边界排序来进行讲解)

排序后为:

image-20240524191023959

排序了之后我们就可以从上往下遍历去判断是否重合了。

当下面的气球的左边界小于等于上面气球的右边界时,证明两个气球重合,可以用一支箭引爆。

当然下面一个气球有可能和上面两个气球都重合,如果只和上面一个气球重合而不和上上面气球重合的话,那么还需要额外的一支箭去引爆。为了实现判断,当两支气球重合时,我们可以把右边界缩小为两个气球右边界较小的一个值(因为此时新气球的左边界一定大于等于上面两个气球的左边界,所以不用判断),如果新气球左边界小于上面气球的右边界,那么就不需要额外的箭就能引爆。

遍历完所有的气球,我们便可以统计出需要的箭的数量。

下面为代码实现:

class Solution {public int findMinArrowShots(int[][] points) {if (points.length == 0)return 0;Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));//不使用a[0] - b[0]而使用Integer.compare(a, b)是为了防止整数溢出int ans = 1;for (int i = 1; i < points.length; i++) {if (points[i][0] <= points[i - 1][1]) {points[i][1] = Math.min(points[i][1], points[i - 1][1]);//把上一个气球右边界修改为较小值} else {ans++;}}return ans;}
}

435. 无重叠区间

image-20240524184413408

本题相比于上一题增加了一点难度,下面我是按照我的思路来讲解。

首先我们依然是要先进行排序(用**[[1,2],[2,3],[3,4],[1,3]]**举例):

在这里插入图片描述

排序后为:
在这里插入图片描述

我们可以直观地看出只要删除1,3便可以实现剩下的区间没有重叠。

那么具体代码上怎么去实现呢?

整体思路和上一道题有些类似,当本区间左边界比上一个区间右边界小的时候我们就需要去删除了。删除在代码上只需要将此区间右边界设置为此区间与上一个区间中的较小值就可以了。如果此区间左边界大于等于上一个区间右边界,那么就证明两个区间没有重合,不需要进行操作。

下面是代码实现:

class Solution {public int eraseOverlapIntervals(int[][] intervals) {if (intervals.length == 0)return 0;Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));int ans = 0;for (int i = 1; i < intervals.length; i++) {if (intervals[i][0] < intervals[i - 1][1]) {intervals[i][1] = Math.min(intervals[i][1], intervals[i - 1][1]);ans++;} }return ans;}
}

56. 合并区间

image-20240524192004312

本题和上面两道题也比较类似,大致讲一下思路。

先进行排序,然后用此区间左边界与上一个区间右边界进行比较,如果满足重叠,则进行记录。

下面用代码来具体看一下:

class Solution {public int[][] merge(int[][] intervals) {Arrays.sort(intervals, (a, b) -> a[0] - b[0]);List<int[]> list = new LinkedList<>();for (int i = 0; i < intervals.length; i++) {if (list.isEmpty() || list.get(list.size() - 1)[1] < intervals[i][0]) {//如果集合为空或者此区间左边界大于最后录入集合的区间右边界,则直接记录答案就可以了,反之就证明有重叠list.add(intervals[i]);} else {list.get(list.size() - 1)[1] = Math.max(list.get(list.size() - 1)[1], intervals[i][1]);//重叠的区间左边界是不用变的,右边界需要修改成两个区间右边界的较大值,就可以了}}return list.toArray(new int[list.size()][]);}
}

结语

在本文中,我们深入探讨了贪心算法的原理、应用场景以及实现方法。贪心算法作为一种简单而强大的算法设计技巧,已经在许多领域得到了广泛的应用,如图论、任务调度、最优化问题等。通过每一步的局部最优选择,贪心算法能够快速地找到问题的最优解,具有较高的执行效率。

在实际应用中,贪心算法的灵活运用能够为我们带来更多的便利和效益。通过深入理解贪心算法的原理和特点,我们可以更好地利用这一算法工具,为解决实际问题提供有效的解决方案。

希望本文能够帮助读者更好地理解贪心算法,并在实际应用中取得更好的效果。

贪心算法能够快速地找到问题的最优解,具有较高的执行效率。

在实际应用中,贪心算法的灵活运用能够为我们带来更多的便利和效益。通过深入理解贪心算法的原理和特点,我们可以更好地利用这一算法工具,为解决实际问题提供有效的解决方案。

希望本文能够帮助读者更好地理解贪心算法,并在实际应用中取得更好的效果。

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

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

相关文章

面试准备-八股【面试准备】

面试准备-八股【面试准备】 Java基础解决hash冲突的方法try catch finallyException与Error的包结构OOM你遇到过哪些情况&#xff0c;SOF你遇到过哪些情况线程有哪些基本状态?Java IO与 NIO的区别堆和栈的区别对象分配规则notify()和notifyAll()有什么区别&#xff1f;sleep()…

Docker(四)容器相关操作及问题处理

目录 一、进入、退出容器操作 二、查看Docker 容器的配置文件 方法一&#xff1a;进入docker容器内进行查看 方法二&#xff1a;通过数据卷挂载方式查看配置文件 方法三&#xff1a;使用Docker可视化工具查看配置文件 三、容器与宿主机时间同步 方法一&#xff1a;创建启…

3D模型旋转显示不全怎么办---模大狮模型网

在3D建模和渲染过程中&#xff0c;我们有时会遇到旋转模型时显示不全的问题。这种情况可能由多种原因造成&#xff0c;包括模型本身的问题、软件设置不当、硬件配置不足等。本文将为您详细介绍几种可能的解决方法&#xff0c;帮助您解决3D模型旋转显示不全的问题。 一、检查模型…

Mask R-CNN实战

一、源码和数据集的准备 获取git开源项目代码 https://github.com/matterport/Mask_RCNN 一下载2.1的前三个文件&#xff0c;和2.0的第一个h5文件&#xff0c;coco.h5是预训练权重&#xff0c;也放入源码 项目文件结构如下&#xff1a; samples/logs:训练模型保存的位置 配置…

LINUX系统编程:命名管道

匿名管道的通信只能在&#xff0c;有血缘关系的进程中&#xff0c;本质就是&#xff0c;子进程会拷贝一份父进程的文件描述符表&#xff0c;父子进程就可以看到操作系统的同一块资源&#xff08;文件&#xff09;&#xff0c;以这块资源为媒介进行通信。 命名管道&#xff0c;…

STM32——DAC篇(基于f103)

技术笔记&#xff01; 一、DAC简介&#xff08;了解&#xff09; 1.1 DAC概念 传感器信号采集改变电信号&#xff0c;通过ADC转换成单片机可以处理的数字信号&#xff0c;处理后&#xff0c;通过DAC转换成电信号&#xff0c;进而实现对系统的控制。 1.2 DAC的特性参数 1.3…

Vue3实战笔记(41)—自己封装一个计时器Hooks

文章目录 前言计时器钩子总结 前言 在Vue项目中&#xff0c;封装一个计时器挂钩&#xff08;Hook&#xff09;是一种实用的技术&#xff0c;它允许你在组件中方便地管理定时任务&#xff0c;如倒计时、计时器等&#xff0c;而无需在每个使用场景重复编写相同的逻辑代码。 计时…

大语言模型的工程技巧(一)——GPU计算

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 本文涉及到的代码链接如下&#xff1a;regression2chatgpt/ch07_autograd/gpu.ipynb 本文将讨论如何利用PyTorch实现GPU计算。本…

常见的几种数据库通过SQL对表信息进行查询

一、前言 我们查询数据库表的信息&#xff0c;一般都使用界面化的连接工具查看&#xff0c;很少使用SQL语句去查&#xff0c;而且不同的数据库SQL语句又各自有差异。但如果通过代码去获取数据库表的信息&#xff0c;这时就需要通过SQL语句去查了&#xff0c;这个在逆向代码生成…

翻转列表-力扣

题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示例 3&#xff1a; …

CGAN|生成手势图像|可控制生成

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;TensorFlow入门实战&#xff5c;第3周&#xff1a;天气识别&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 CGAN&#xff08;条件生成对抗网络&#xf…

pytorch-13_2 模型结构选择策略:层数、激活函数、神经元个数

一、拟合度概念 在所有的模型优化问题中&#xff0c;最基础的也是最核心的问题&#xff0c;就是关于模型拟合程度的探讨与优化。根据此前的讨论&#xff0c;模型如果能很好的捕捉总体规律&#xff0c;就能够有较好的未知数据的预测效果。但限制模型捕捉总体规律的原因主要有两点…

C++:vector基础讲解

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《C&#xff1a;vector基础讲解》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞&#xff01;&#…

day15|各种遍历的应用

相关题目&#xff1a; 层次遍历会一打十 反转二叉树 对称二叉树 层次遍历会一打十 自底向上的层序遍历 实现思路&#xff1a;层次遍历二叉树&#xff0c;将遍历后的结果revers即可 public List<List<Integer>> levelOrderBottom(TreeNode root) {List<List&l…

框架学习之SpringMVC学习笔记(一)

一、SpringMVC简介 1-介绍 Spring Web MVC是基于Servlet API构建的原始Web框架&#xff0c;从一开始就包含在Spring Framework中。正式名称“Spring Web MVC”来自其源模块的名称&#xff08; spring-webmvc &#xff09;&#xff0c;但它通常被称为“Spring MVC”。 在控制层…

一文深度剖析 ColBERT

近年来&#xff0c;向量搜索领域经历了爆炸性增长&#xff0c;尤其是在大型语言模型&#xff08;LLMs&#xff09;问世后。学术界开始重点关注如何通过扩展训练数据、采用先进的训练方法和新的架构等方法来增强 embedding 向量模型。 在之前的文章中&#xff0c;我们已经深入探…

记录踩坑事件 分页查询order by出现重复数据bug

MySQL排序小坑_mysql order by name相同导致排序混乱-CSDN博客 1、问题描述 列表页分页查询出现重复数据。 2、问题排查 排查最终执行sql日志。 select * from tableA where (start_time>2024-04-17 00:00:00) AND (start_time<2024-05-18 00:00:00) ORDER BY sta…

AIGC基础教学:AI+建筑设计,一场划时代变革的序幕已经拉开

2015年9月&#xff0c;美的集团本着把艺术融入民间的理念&#xff0c;邀请了安藤忠雄设计正在筹建中的美术馆。 在历经长达近120天的设计工作之后&#xff0c;美术馆于同年12月动工。这座具有岭南建筑文化意境的美术馆&#xff0c;后来荣获2020年美国建筑大师奖(Architecture …

【ArcGIS微课1000例】0112:沿线(面)按距离或百分比生成点

文章目录 一、沿线生成点工具介绍二、线状案例三、面状案例一、沿线生成点工具介绍 位置:工具箱→数据管理工具→采样→沿线生成点 摘要:沿线或面以固定间隔或百分比创建点要素。 用法:输入要素的属性将保留在输出要素类中。向输出要素类添加新字段 ORIG_FID,并设置为输…

Java.lang.InterruptedException被中止异常解决方案

大家好&#xff01;我是咕噜铁蛋&#xff01;在Java编程的世界里&#xff0c;java.lang.InterruptedException是一个常见的异常&#xff0c;尤其是在处理多线程和并发任务时。这个异常通常表示一个线程在等待、休眠或其他占用时间不长的操作时被中断。作为一个资深的Java开发者…