贪心算法策略实现

贪心算法

贪心算法:基于某种情况进行一个排序。 贪心算法得到的是优良解,而非全局最优解。需要证明局部最优解 == 全局最优解

经典贪心算法 —— 会议问题

对于这个问题 ,我们提出贪心策略:

策略1:按照会议的持续时间长短来排序。持续时间短的会议优先安排

我们可以举出反例:蓝色方案安排的场次比绿色方案安排的场次少

策略2:按照会议的开始时间早晚来排序。开始时间早的会议优先安排

我们可以举出反例:蓝色方案安排的场次比绿色方案安排的场次少

.......

策略n:按照会议的结束时间早晚来排序。结束时间早的会议优先安排

这个策略是正确的,先上代码

package greedyalgorithms;

import java.util.Arrays;
import java.util.Comparator;

public class ScheduleProgram {
    class Progame {//会议
        int start;
        int end;

        public Progame(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }

    public static class ProgameComparator implements Comparator<Progame> {
        //按结束时间从早到晚排序
        @Override
        public int compare(Progame o1, Progame o2) {
            return o1.end - o2.end;//o1的结束时间比o2的结束时间晚,o2排前面
            //返回-1(或负数),表示不需要交换o1和o2的位置,o1排在o2前面
            //返回1(或正数),表示需要交换o1和o2的位置,o2排在o1前面
        }
    }

    //progames:需要安排的会议,timePoint:目前的时间点
    public int bestArrange(Progame[] progames, int timePoint) {
        Arrays.sort(progames, new ProgameComparator());//按照ProgameComparator比较器定义的compare()方法来排序
        int result = 0;
        
        for (int i = 0; i < progames.length; i++) {
            if(timePoint <= progames[i].start){//此时时间 <= 会议的开始时间
                result++;//安排好的会议的个数++
                timePoint = progames[i].end;//时间来到会议的结束时间
            }
        }
        
        return result;
    }
}

对于这个策略,我们不能够轻松举出反例,但证明需要使用严格复杂的数学证明

贪心算法在笔试时的解题套路

1、准备暴力枚举、全排列的模板,贪心算法的最优解一定在全排列之中

2、贪心策略类题目,是一句某个标准排序或是放在堆里各自排序,举出n多个比较策略。此时容易举出反例的比较策略可以直接pass

3、用策略X结合随机大样本跑对数器。如果某个策略几千万次的随机样本都相同,那么这个比较策略就是正确的

什么是对数器?对数器的作用是什么?-CSDN博客

贪心策略实现

切分金条的最小分割代价

哈夫曼编码问题

从反方向考虑,已经切好的数组如何合并使得花费最小,花费的金额为合并的数值

贪心策略:每次挑代价最小的2个数来结合

如果有一组数组:arr = {2, 3, 4, 7, 9, 2}

将数组放入小根堆中arr = {2, 2, 3, 4, 7, 9}
前两个数相加arr = {4, 3, 4, 7, 9}
排序arr = {3, 4, 4, 7, 9}
前两个数相加arr = {7, 4, 7, 9}
排序arr = {4, 7, 7, 9}
前两个数相加arr = {11, 7, 9}
排序arr = {7, 9, 11}
前两个数相加arr = {16, 11}
排序arr = {16, 11}
两个数相加arr = {27}
package greedyalgorithms;

import java.util.PriorityQueue;

public class LessMoneySplitGold {
    public static int lessMoney(int[] arr) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();//默认小根堆
        for (int i = 0; i < arr.length; i++) {
            priorityQueue.add(arr[i]);//将数组全部放入小根堆
        }

        int temp = 0;
        while (priorityQueue.size() > 1) {
            temp = priorityQueue.poll() + priorityQueue.poll();//弹出两个相加
            priorityQueue.add(temp);//加回去,排序
        }

        return priorityQueue.poll();//最后小根堆中只有一个数即为结果
    }
}

做项目获得的最大收益

costs[]:花费数组,profits[]: 利润数组

这里的花费仅仅表示做项目的门槛,因为在实际题目的计算中并没有减去项目花费的数

实现解析

一组项目:<花费,利润>

<2,3>,  <1,4>,  <1,1>,  <2,7>.,  <3,2>,  <4,10>

将项目放入一个以花费为依据的小根堆中,其中,利润的大小不考虑

小根堆中的项目表示都是锁住(不可做)的状态

小根堆中:<1,4>,  <1,1>,   <2,3>,  <2,7>.,  <3,2>,  <4,10>

依据初始资金m,解锁所有花费小于等于m的项目放到一个以利润为依据的大根堆中,其中,花费的大小不考虑

大根堆中的项目表示解锁(可做)的状态

m = 1; 大根堆中:<1,4>,  <1,1>

大根堆抛出第一个项目,初始资金更新为m+该项目的利润

依据新的初始资金m,在小根堆中解锁项目,在大根堆中抛出,更新利润 .......

直到到达指定的项目数k停止

此外,还有另一种情况。当没有达到指定的项目数k,但某一时刻的初始资金比较少,不能够解锁小根堆中剩下的所有项目,此时只能提前返回当前的资金m

package greedyalgorithms;

import java.util.*;

public class FindMaxmizedCapital {
    int M = 0;//初始资金
    int K = 0;//表示最多做k个项目

    class Program {
        public int cost;//花费
        public int profit;//利润

        public Program(int cost, int profit) {
            this.cost = cost;
            this.profit = profit;
        }
    }

    public int findMaxmizedCapital(List<Program> programs, int M, int K) {
        PriorityQueue<Program> minCostPQ = new PriorityQueue(new MinCostComparator());
        PriorityQueue<Program> maxProfitPQ = new PriorityQueue(new MaxProfitComparator());
        //全部放入小根堆中锁定
        for (Program pr : programs) {
            minCostPQ.add(pr);
        }

        for (int i = 0; i < K; i++) {
            //peek(): 获取元素但不删除队列首元素
            while (!minCostPQ.isEmpty() && minCostPQ.peek().cost <= M) {
                maxProfitPQ.add(minCostPQ.poll());//放入大根堆中,解锁
            }
            //更新初始资金
            M += maxProfitPQ.poll().profit;
            //当没有达到指定的项目数k,但某一时刻的初始资金比较少,不能够解锁小根堆中剩下的所有项目,此时只能提前返回当前的资金m
            if (maxProfitPQ.isEmpty()) {
                break;
            }
        }
        return M;
    }


    class MinCostComparator implements Comparator<Program> {
        @Override
        public int compare(Program o1, Program o2) {
            return o1.cost - o2.cost;
            //compare()方法比较o1,o2的大小
            //正序:当o1<o2时return -1,o1=o2时return 0,o1>o2时return 1

        }
    }

    class MaxProfitComparator implements Comparator<Program> {
        @Override
        public int compare(Program o1, Program o2) {
            return o2.profit - o1.profit;
        }
    }


}

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

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

相关文章

函数声明与函数表达式

函数声明 一个标准的函数声明&#xff0c;由关键字function 、函数名、形参和代码块组成。 有名字的函数又叫具名函数。 举个例子&#xff1a; function quack(num) { for (var i 0; i < num; i) {console.log("Quack!")} } quack(3)函数表达式 函数没有名称…

前端代码提交gitlab出现语法错误无法提交

错误 找到项目里面的.git文件夹 下面有一个hooks 删除pre-commit文件&#xff08;git语法校验代码&#xff09;

人工智能即将彻底改变你使用计算机的方式

文章目录 每个人的私人助理“Clippy 是一个机器人&#xff0c;而不是特工。”卫生保健“一半需要心理健康护理的美国退伍军人没有得到治疗。”教育生产率娱乐和购物科技行业的冲击波技术挑战隐私和其他重大问题 今天我仍然像保罗艾伦和我创办微软时一样热爱软件。但是&#xff…

Nodejs+Vue校园餐厅外卖订餐点餐系统 PHP高校食堂 微信小程序_0u4hl 多商家

对于校园订餐小程序将是又一个传统管理到智能化信息管理的改革&#xff0c;对于传统的校园订餐管理&#xff0c;所包括的信息内容比较多&#xff0c;对于用户想要对这些数据进行管理维护需要花费很大的时间信息&#xff0c;而且对于数据的存储比较麻烦&#xff0c;想要查找某一…

Elasticsearch:向量搜索 (kNN) 实施指南 - API 版

作者&#xff1a;Jeff Vestal 本指南重点介绍通过 HTTP 或 Python 使用 Elasticsearch API 设置 Elasticsearch 以进行近似 k 最近邻 (kNN) 搜索。 对于主要使用 Kibana 或希望通过 UI 进行测试的用户&#xff0c;请访问使用 Elastic 爬虫的语义搜索入门指南。你也可以参考文章…

【嵌入式】开源shell命令行的移植和使用(2)——letter-shell

目录 一 背景说明 二 移植准备 三 移植过程 四 自定义命令 五 实际使用 一 背景说明 之前使用过一款开源shell工具 nr_micro_shell &#xff08;【嵌入式】开源shell命令行的移植和使用&#xff08;1&#xff09;——nr_micro_shell-CSDN博客&#xff09;&#xff0c;感觉…

【Linux】了解进程的基础知识

进程 1. 进程的概念1.1 进程的理解1.2 Linux下的进程1.3 查看进程属性1.4 getpid和getppid 2. 创建进程3. 进程状态4. 进程优先级5. 进程切换6. 环境变量7. 本地变量与内建命令 1. 进程的概念 一个已经加载到内存中的程序&#xff0c;叫做进程&#xff08;也叫任务&#xff09…

echarts点击事件

有这么个需求要点击叶片的时候跳转页面 代码&#xff1a;点击之后 报错了 解决办法 1、使用箭头函数&#xff08;箭头函数没有自己的 this&#xff0c;所以在箭头函数中使用 this 时&#xff0c;其指向与外层作用域相同。&#xff09;或者使用闭包来解决上下文的问题。 2、使…

QT基础实践之QQ登录界面

文章目录 QQ登录界面源码分享演示图代码分析 QQ登录界面 源码分享 链接&#xff1a;https://pan.baidu.com/s/1v_J4WQjZoSAoMrIpx88PbA 提取码&#xff1a;qwer 记得把图片放入Debug文件 演示图 代码分析 已注释 较为详细 widget.h #ifndef WIDGET_H #define WIDGET_H#inc…

Leetcode98 验证二叉搜索树

题意理解&#xff1a; 首先明确二叉树的定义&#xff0c;对于所有节点&#xff0c;根节点的值大于左子树所有节点的值&#xff0c;小于右子树所有节点的值。 注意一个误区&#xff1a; 根节点简单和左孩子&#xff0c;右孩子比大小是不够的&#xff0c;要和子树比&#xff0c;…

Django项目部署本地windows IIS(详细版)和static文件设置(页面样式正常显示)

目录 必要条件&#xff1a; 一、下载并启用wfastcgi 二、window安装 IIS功能 三、IIS管理器中添加网站 1、复制项目 2、复制wfastcgi.py文件 3、创建文件web.config 4、添加网站&#xff0c;填写信息 5、启动fastcgi程序 6、修改进程标识 四、static文件设置和正确显…

凝聚数字经济发展新力量,四象科技受邀出席2023全球数商大会

11月25日&#xff0c;2023全球数商大会在上海开幕。本届大会以“数联全球、商通未来”为主题&#xff0c;上海市委副书记、市长龚正出席大会并宣布大会开幕&#xff0c;国家发展改革委党组成员&#xff0c;国家数据局党组书记、局长刘烈宏&#xff0c;上海市副市长陈杰致辞。四…

智能学习台灯_AI摄像头学习机基于MTk8175方案

智能学习台灯是一款专为中小学生设计的学习辅助工具&#xff0c;具有多项突出的参数和功能。首先&#xff0c;它采用了基于联发科MTK平台的解决方案&#xff0c;内置了12纳米四核Cortex-A53处理器&#xff0c;提供了稳定而高效的性能。操作系统方面&#xff0c;智能学习台灯运行…

山西临县“5·7”火灾事故调查报告公布,揭秘富维烟火报警系统

近日&#xff0c;山西临县“57”火灾事故调查报告震惊全国&#xff0c;提醒我们火灾防控的重要性。在这起悲剧中&#xff0c;我们深刻认识到&#xff0c;及时发现火灾并迅速应对至关重要。这不仅是对生命安全的保护&#xff0c;也是对财产损失的有效减少。而在这方面&#xff0…

SQL注入-报错注入

目录 一&#xff0c;sql报错注入概述&#xff1a; 二&#xff0c;报错注入函数&#xff1a; extractvalue() updatexml() floor()、rand()、count()、group by联用 其它函数 三&#xff0c;SQL报错注入实例&#xff1a; extractvalue() floor()、rand()、count()、grou…

统计学中两组数据如何进行差异性(相关性)分析?

变量说明&#xff1a; 在确定分析方法前&#xff0c;我们需要了解手中的数据类型&#xff0c;这是最基础也是有必要的&#xff0c;在所有的数据类型中&#xff0c;我们将数据类型分为分类变量也为定类变量和连续变量也称为定量变量&#xff0c;那么什么是定类变量&#xff1f;…

通达信抛物线SAR指标原理详解、参数设置及选股公式

抛物线指标(SAR)是由技术分析大师威尔斯威尔德(Welles Wilder)发明的&#xff0c;在其1978 年出版的《技术交易系统新概念》一书中介绍了该指标。SAR指标通过跟踪股票价格的动态变化&#xff0c;在走势图上以一系列点的形式显示&#xff0c;提供了一种判断趋势反转的方法&#…

E云管家开发自动转发朋友圈

简要描述&#xff1a; 转发朋友圈&#xff0c;直接xml数据。(对谁不可见) 请求URL&#xff1a; http://域名地址/forwardSns 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参…

9.增删改操作

目录 一、插入操作 1、为表的所有字段插入数据 2、为表的指定字段插入数据 3、同时插入多条记录 4、将查询结果插入表中&#xff1a; 二、更新操作 三、删除操作 四、练习题 一、插入操作 在使用数据库之前&#xff0c;数据库中必须要有数据&#xff0c;MYSQL中使INSE…

SimpleDateFormat在多线程下的安全问题

目录 情景重现 SimpleDateFormat解析 解决方案 局部变量 加锁 使用线程变量 使用DateTimeFormatter 情景重现 SimpleDateFormat类是Java开发中的一个日期时间的转化类。它可以满足绝大多数的开发场景&#xff0c;但是在高并发下会出现并发问题。接下来查看下文中的案例。…