贪心算法(Java)
贪心算法
文章目录

0、写在前面
顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路径问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。
1、贪心算法的基本要素
对于一个具体的问题,怎么知道是否可用贪心算法解此问题,以及能否得到问题的最优解呢?这个问题很难给予肯定的回答。
但是,从许多可以用贪心算法求解的问题中看到这类问题一般具有2个重要的性质:贪心选择性质和最优子结构性质。
1.1 贪心选择性质
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的
第一个基本要素,也是贪心算法与动态规划算法的主要区别。动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
对于一个具体问题,要确定它是否具有贪心选择性质,
必须证明每一步所作的贪心选择最终导致问题的整体最优解。
1.2 最优子结构性质
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
1.3 贪心算法与动态规划算法的差异
贪心算法和动态规划算法都要求问题具有最优子结构性质,这是2类算法的一个共同点。但是,对于具有最优子结构的问题应该选用贪心算法还是动态规划算法求解?
2、贪心算法的特点
设计要素:
贪心法适用于组合优化问题.
求解过程是多步判断过程,最终的判断序列对应于问题 的最优解.判断依据某种“短视的”贪心选择性质,性质的好坏决定了算法的成败.
贪心法必须进行正确性证明
贪心法的优势:算法简单,时间和空间复杂性低
3、贪心法的正确性证明
数学归纳法
- 叙述一个描述算法正确性的命题P(n),n为算法步数或者问题规模
- 归纳基础:P(1) 或 P(n0)为真, n0为某个自然数
- 归纳步骤:P(k) -->P(k+1) 第一数学归纳法
对于所有k(k<n)P(k)–> P(n) 第二数学归纳法

交换论证
- 分析算法的解的结构特征
- 从一个最优解逐步进行结构变换(替换成分、交换次序等)得到一个新的解(结构上与贪心算法的解更接近)
- 证明:上述变换最终得到算法的解,且变换在有限步结束,每步变换都保持解的最优性不降低.
4、活动安排问题
4.1 问题描述
设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi 。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。
4.2 贪心法的设计思想

4.3 两个反例
策略1:S={1,2,3},s1=0, f1=20, s2=2, f2=5, s3=8, f3=15
策略2:S={1,2,3},s1=0, f1=8, s2=7, f2=9, s3=8, f3=15

5、代码
活动安排
Note:各活动的起始时间和结束时间存储于数组s和f中且按结束时间的非减序排列
public static int greedySelector(int[] s,int[] f,boolean[] a) {
int n=s.length;
a[0]=true;
int j=0;
int count=1;
for(int i=1;i<n;i++){
if(s[i]>=f[j]){
a[i]=true;
j=i;
count++;
} else {
a[i]=false;
}
}
return count;
}
6、效率
由于输入的活动以其完成时间的非减序排列,所以算法greedySelector每次总是选择具有最早完成时间的相容活动加入集合A中。直观上,按这种方法选择相容活动为未安排活动留下尽可能多的时间。也就是说,该算法的贪心选择的意义是使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。
算法greedySelector的效率极高。当输入的活动已按结束时间的非减序排列,算法只需O(n)的时间安排n个活动,使最多的活动能相容地使用公共资源。如果所给出的活动未按非减序排列,可以用O(nlogn)的时间重排。
7、实例
例:设待安排的11个活动的开始时间和结束时间按结束时间的非减序排列如下:

算法greedySelector 的计算过程如左图所示。图中每行相应于算法的一次迭代。阴影长条表示的活动是已选入集合A的活动,而空白长条表示的活动是当前正在检查相容性的活动。
A = {1, 4, 8,11}

若被检查的活动i的开始时间Si小于最近选择的活动j的结束时间fi,则不选择活动i,否则选择活动i加入集合A中。
贪心算法并不总能求得问题的整体最优解。但对于活动安排问题,贪心算法greedySelector却总能求得的整体最优解,即它最终所确定的相容活动集合A的规模最大。这个结论可以用数学归纳法证明。
算法的正确性证明
定理算法Select 执行到第 k 步, 选择 k 项活动 i1= 1, i2, …,
ik, 那么存在最优解 A 包含 i1=1, i2, … , ik .
根据定理:算法至多到第 n 步得到最优解

归纳步骤:假设命题对 k 为真, 证明对 k+1 也为真.


8、参考
- 算法设计与分析(第4版)
结束!
贪心算法(Java)的更多相关文章
- Java 算法(一)贪心算法
Java 算法(一)贪心算法 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 一.贪心算法 什么是贪心算法?是指在对问题进行求 ...
- 基于贪心算法求解TSP问题(JAVA)
概述 前段时间在搞贪心算法,为了举例,故拿TSP来开刀,写了段求解算法代码以便有需之人,注意代码考虑可读性从最容易理解角度写,没有优化,有需要可以自行优化! 详细 代码下载:http://www.de ...
- Java蓝桥杯——贪心算法
贪心算法 贪心算法:只顾眼前的苟且. 即在对问题求解时,总是做出在当前看来是最好的选择 如买苹果,专挑最大的买. 最优装载问题--加勒比海盗 货物重量:Wi={4,10,7,11,3,5,14,2} ...
- 算法(Java实现)—— 贪心算法
贪心算法 应用场景-集合覆盖问题 假设在下面需要付费的广播台,以及广播台新型号可以覆盖的地区,如何选择最少的广播台,让所有地区都可以接收到信号 广播台 覆盖地区 k1 北京.上海.天津 k2 广州.北 ...
- 《Java算法》贪心算法
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解. 贪心算法的经典案例: 跳跃游戏: 给定一个非负整 ...
- 最短路径算法之Dijkstra算法(java实现)
前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是“贪心算法”的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知 ...
- HDU2037 今年暑假不AC 贪心算法
贪心算法 : 贪心算法就是只考虑眼前最优解而忽略整体的算法, 它所做出的仅是在某种意义上的局部最优解, 然后通过迭代的方法相继求出整体最优解. 但是不是所有问题都可以得到整体最优解, 所以选择贪心策略 ...
- HDOJ 1330 Deck(叠木块-物理题啊!贪心算法用到了一点)
Problem Description A single playing card can be placed on a table, carefully, so that the short edg ...
- HDU 4726 Kia's Calculation (贪心算法)
Kia's Calculation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- 剑指Offer——贪心算法
剑指Offer--贪心算法 一.基本概念 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解.虽然贪心算法不能对 ...
随机推荐
- pypi镜像-清华
临时使用 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 注意,simple 不能少, 是 https 而不是 ...
- C++future promise
A future is an object that can retrieve a value from some provider object or function, properly sync ...
- 实现分页数据请求的思路/Element UI(Plus)的分页模板(Vue3.x写法),(直接使用<script>引入vue.js)
实现分页数据请求的思路/Element UI(Plus)的分页模板(Vue3.x写法),(直接使用<script>引入vue.js) 1. 效果图: 2.实现分页数据请求的思路: 分页 ...
- yii框架中 不能正确正常使用phpredis 路径安装好后还是报 Class yii\redis\Connection does not exist!
1,成功解决方案 在yiisoft / extensions.php 中添加如下数组 指向目录 'yiisoft/yii2-redis' =>array( 'name'=>'yi ...
- react backend uploadfile
public List<string> WriteFile(List<UploadDTO> uploads) { List<string> fileNames = ...
- Zero-Shot Temporal Action Detection via Vision-Language Prompting概述
1.针对的问题 现有的方法在推断时只能识别之前见过的类别,即训练时出现过的类别,而为每个感兴趣的类收集和注释大型训练集是昂贵的. 2.主要贡献 (1)研究了如何利用大量预训练的ViL模型进行未修剪视频 ...
- el-table实现翻页选择和回看
html <el-table ... <!-- row-key的row.id是你的行唯一标识,一般用id,翻页选的关键 --> :row-key="row => ro ...
- 访问修饰符 protected(s)
protected 受保护的:可以在当前类的内部以及该类的子类中可以访问. using System; using System.Collections.Generic; using System.L ...
- kiaba启动报 FATAL ResponseError: access_control_exception,ES报:java.lang.SecurityException: access denied ("java.io.FilePermission"“文件地址”)
查了许多博客,找的头都大了还是没有发现问题的根源,之前以为是插件包文件名改了之后还是一样,当我差点放弃的时候 一位博主的瞬间把我点醒https://www.cnblogs.com/personblog ...
- C++ 手动实现单向循环链表(课后作业版)
单向循环链表,并实现增删查改等功能 首先定义节点类,类成员包含当前节点的值, 指向下一个节点的指针 循环链表的尾节点指向头节点 节点定义: //node definition template < ...