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

Java 贪心算法经典问题解决

文章目录

    • 分金条
      • 题目
      • 思路
      • 代码实现
      • 测试用例以及结果输出
    • 花费资金做项目最大收益
      • 题目
      • 思路
      • 代码实现
      • 测试用例以及结果输出
    • 预定会议室
      • 题目
      • 思路
      • 代码实现
      • 测试用例以及结果输出
    • 取中位数
      • 题目
      • 思路
      • 代码实现
      • 测试用例以及结果输出
    • 最低字典序
      • 题目
      • 思路
      • 代码实现
      • 测试用例以及结果输出
    • 结语

分金条

题目

一块金条切成两半,是需要花费和长度数值一样的铜板的。比如 长度为20的 金条,不管切成长度多大的两半,都要花费20个铜 板。一群人想整分整块金 条,怎么分最省铜板?

例如,给定数组{10,20,30},代表一共三个人,整块金条长度为 10+20+30=60. 金条要分成10,20,30三个部分。 如果, 先把长 度60的金条分成10和50,花费60 再把长度50的金条分成20和30, 花费50 一共花费110铜板。 但是如果, 先把长度60的金条分成30和30,花费60 再把长度30 金条分成10和20,花费30 一共花费90铜板。

输入一个数组,返回分割的最小代价。

思路

哈夫曼树带权路径计算问题,更多了解可参考:哈夫曼树及其应用

  1. 先将给定数组进行排序,这里可以使用优先级队列处理【优先级堆结构】,将数组依次丢入优先级队列中;
  2. 每次从优先级队列中取出较小的值相加,记录计算结果,同时将结果重新丢入到队列中,直到队列中没有元素;
  3. 将过程中的所有计算结果相加,结果即为分割最小代价;

代码实现

   private static int lessMoney(int[] aar) {PriorityQueue<Integer> pQ = new PriorityQueue<>();for (int i = 0; i < aar.length; i++) {pQ.add(aar[i]);}int result = 0;int cur = 0;while (pQ.size() > 1) {cur = pQ.poll() + pQ.poll();result += cur;pQ.add(result);}return result;}

测试用例以及结果输出

  public static void main(String[] args) {int[] aar = new int[]{30, 10, 20};System.out.println(lessMoney(aar));}

输出结果:

90

花费资金做项目最大收益

题目

输入:
参数1,正数数组costs
参数2,正数数组profits
参数3, 正数k
参数4,正数m

其中,costs[i]表示i号项目的花费;profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润);
k表示你不能并行、只能串行的最多做k个项目;
m表示你初始的资金;
说明:你每做完一个项目,马上获得的收益,可以支持你去做下一个 项目。
输出:你最后获得的最大钱数。

思路

基本原则:结合生活中的实际生产,每次选花费最小收益最高的项目去做,最终得到的收益肯定是最大的;

  1. 新定义Node类,包含每个项目对应的花费以及收益;
  2. 分别定义两个优先级队列,按照最小花费和最大收益优先级取元素;
  3. 将根据花费以及收益数组生成的Node数组丢入到最小花费优先级队列中;
  4. 进行K次遍历【最多可以做K个项目】,不断从最小花费优先级队列中取出项目,丢入到最大收益优先级队列中【注意资金问题】,在根据最大收益去做项目【即从最大收益队列中取项目做】,计算过程中获取的收益之和;

代码实现

/*** 计算最大收益** @param k       表示能做K个项目* @param m       表示启动资金* @param profits 表示做每个项目去除花费后的利润* @param costs   表示做每个项目对应的花费* @return*/private static int getMaxProfit(int k, int m, int[] profits, int[] costs) {//将项目对应花费以及收益包装成Node类,添加到Node[]数组中Node[] nodes = new Node[costs.length];for (int i = 0; i < costs.length; i++) {nodes[i] = new Node(costs[i], profits[i]);}// 最小花费优先级队列PriorityQueue<Node> minConstQ = new PriorityQueue<>(new MinComparator());// 最大收益优先级队列PriorityQueue<Node> maxProfitQ = new PriorityQueue<>(new MaxComparator());//添加到最小花费优先级队列中for (int i = 0; i < nodes.length; i++) {minConstQ.add(nodes[i]);}// k表示最多可以做k个项目for (int i = 0; i < k; i++) {//只要花费不超过启动资金,按照最小花费不断从队列中取,丢入到收益队列中while (!minConstQ.isEmpty() && minConstQ.peek().cost <= m) {maxProfitQ.add(minConstQ.poll());}//如果收益队列为空,就返回最终资金,否则每次从收益队列中取最大收益的项目去做;if (maxProfitQ.isEmpty()) {return m;}m = m + maxProfitQ.poll().profit;}return m;}private static class Node {/*** 花费*/public int cost;/*** 利润*/public int profit;public Node(int cost, int profit) {this.cost = cost;this.profit = profit;}}/*** 花费最小排序*/private static class MinComparator implements Comparator<Node> {@Overridepublic int compare(Node o1, Node o2) {return o1.cost - o2.cost; //>0表示o1>o2}}/*** 利润最大排序*/private static class MaxComparator implements Comparator<Node> {@Overridepublic int compare(Node o1, Node o2) {return o2.profit - o1.profit; // >0 表示o2>o1}}

测试用例以及结果输出

   public static void main(String[] args) {int k = 3;int m = 5;int[] profits = new int[]{1, 3, 4, 6, 8};int[] costs = new int[]{3, 6, 4, 2, 6};System.out.println(getMaxProfit(k, m, profits, costs));}

输出结果:

23

预定会议室

题目

一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。

给你每一个项目开始的时间和结束的时间(给你一个数组,里面是一个个具体的项目),你来安排宣讲的日程,

要求会议室进行的宣讲的场次最多,返回这个最多的宣讲场次。

思路

优先做最早结束的项目,保证开始时间小于或等于要做项目的开始时间即可;

代码实现

 private static int getMaxProgram(Program[] program, int start) {Arrays.sort(program, new ProgramComparator());int result = 0;for (int i = 0; i < program.length; i++) {if (start <= program[i].start) {result++;start = program[i].end;}}return result;}/*** 定义项目会议  包含开始和结束时间*/private static class Program {public int start;public int end;public Program(int start, int end) {this.start = start;this.end = end;}}/*** 按哪个项目先结束排序*/private static class ProgramComparator implements Comparator<Program> {@Overridepublic int compare(Program o1, Program o2) {return o1.end - o2.end;}}

测试用例以及结果输出

    public static void main(String[] args) {Program p1 = new Program(6, 10);Program p2 = new Program(7, 8);Program p3 = new Program(11, 13);Program p4 = new Program(13, 15);Program[] programs = new Program[]{p1, p2, p3, p4};System.out.println(getMaxProgram(programs, 6));}

输出结果:

3

取中位数

题目

一个数据流中,随时可以取得中位数;

思路

分别定义大根堆和小根堆,以下述逻辑进行存放和调整;

  1. 当大根堆为空时,元素直接添加到大根堆中;
  2. 当大根堆不为空时,如果元素小于或等于大根堆堆顶元素,则添加到大根堆中,否则添加到小根堆中;
  3. 当大根堆和小根堆元素个数相差为2时,需要进行堆调整,将元素个数多的堆堆顶元素放入元素个数少的堆中;
  4. 计算中位数,当大根堆和小根堆元素个数相等,则中位数为取两个堆的堆顶元素之和除以2,如果元素个数不相等,则中位数为元素个数多的堆的堆顶元素;

下面以以图进行举例说明,这里简单以队列表示大小根堆:

中位数计算
可以理解成通过堆对元素进行排序,只不过利用大小根队的性质,保证中位数可以通过堆顶数据进行计算得出,也避免了每次添加元素时进行排序问题,时间复杂度更低;

代码实现

    private static class MedianHelper {private PriorityQueue<Integer> minQ = new PriorityQueue<>(new MinComparator());private PriorityQueue<Integer> maxQ = new PriorityQueue<>(new MaxComparator());public int getMedian() {int maxQSize = maxQ.size();int minQSize = minQ.size();if (maxQSize == 0) {return 0;}//元素个数相等,取两者堆顶元素/2if (maxQSize == minQSize) {return (maxQ.peek() + minQ.peek()) / 2;}//元素个数不相等,取元素多的堆顶元素return maxQSize > minQSize ? maxQ.peek() : minQ.peek();}//插入元素public void addNum(int num) {if (maxQ.isEmpty()) {maxQ.add(num);} else {if (maxQ.peek() >= num) {maxQ.add(num);} else {minQ.add(num);}}modifyQSize();}/*** 调整两个堆的大小 一旦发现两个堆数据个数相差为2,则取多的丢到少的里面*/private void modifyQSize() {int minQSize = minQ.size();int maxQSize = maxQ.size();if (minQSize - maxQSize == 2) {maxQ.add(minQ.poll());}if (maxQSize - minQSize == 2) {minQ.add(maxQ.poll());}}}

测试用例以及结果输出

    public static void main(String[] args) {int[] aar = new int[]{8, 6, 13, 10, 11, 19};MedianHelper helper = new MedianHelper();for (int i : aar) {helper.addNum(i);}System.out.println(helper.getMedian());}

输出结果:

10

最低字典序

题目

给定一个字符串类型的数组strs,找到一种拼接方式,使得把所有字符串拼起来之后形成的字符串具有最低的字典序。

思路

保证每次拼接后的字符串都是最低字典序的即可;

代码实现

 private static String lowestString(String[] strs) {if (strs == null || strs.length == 0) {return "";}Arrays.sort(strs, new LowestComparator());StringBuilder result = new StringBuilder();for (int i = 0; i < strs.length; i++) {result.append(strs[i]);}return result.toString();}/*** 定义两个字符拼接最小字典序比较器*/private static class LowestComparator implements Comparator<String> {@Overridepublic int compare(String o1, String o2) {return (o1 + o2).compareTo(o2 + o1);}}

测试用例以及结果输出

    public static void main(String[] args) {String[] strs2 = {"b", "ab", "ac"};System.out.println(lowestString(strs2));}

结果输出:

abacb

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

相关文章:

Java 贪心算法经典问题解决

文章目录 分金条题目思路代码实现测试用例以及结果输出 花费资金做项目最大收益题目思路代码实现测试用例以及结果输出 预定会议室题目思路代码实现测试用例以及结果输出 取中位数题目思路代码实现测试用例以及结果输出 最低字典序题目思路代码实现测试用例以及结果输出 结语 分…...

所有docker命令无效,解决办法

目录 ■前言 今天使用docker时&#xff0c;所有命令无效 ■解决办法如下 1.停止docker服务 2.查看状态 3.删除之前的docker相关的文件 4.再次查看状态 5.使用相关命令 &#xff08;好用了&#xff09; 6.重新下载镜像 ■前言 今天使用docker时&#xff0c;所有命令无…...

系列一、创建者模式

一、概述 创建者模式的主要关注点是"怎样创建对象?"&#xff0c;它的主要特点是"将对象的创建与使用分离"。这样可以降低系统的耦合度&#xff0c;使用者不需要关注对象的创建细节。 二、分类 单例模式工厂方法模式抽象工厂模式原型模式建造者模式...

数据库系列:覆盖索引和规避回表

1 介绍 在MySQL数据库查询过程中&#xff0c;索引覆盖和避免不必要的回表&#xff0c;是减少检索步骤&#xff0c;提高执行效率的有效手段。下面从这两个角度分析如何进行MySQL检索提效。 2 数据准备 模拟一个500w数据容量的部门表 emp&#xff0c;表结构如下&#xff0c;并…...

java Spring Boot上线运维 启动jar时控制台调整零时变量

前面的文章 java 打包Spring Boot项目&#xff0c;并运行在windows系统中和将Spring Boot项目打包部署到阿里云linux服务器讲述了Spring Boot项目打包部署的过程 但是 这里 我们可能会遇到一种情况 此时 我们服务器 java项目占用了 80端口 但我们需要放上去一个更重要的东西&am…...

java后端校验

Java 后端数据校验 一、概述 当我们想提供可靠的 API 接口&#xff0c;对参数的校验&#xff0c;以保证最终数据入库的正确性&#xff0c;是 必不可少 的活。比如下图就是 我们一个项目里 新增一个菜单校验 参数的函数&#xff0c;写了一大堆的 if else 进行校验&#xff0c;…...

PowerPoint如何修改“默认保存路径”?

很多时候&#xff0c;我们做好PPT后都要保存&#xff0c;一般会保存在创建PPT的文件夹里&#xff0c;或者另外设置保存的路径。 如果经常需要制作PPT&#xff0c;又不想每次都要重新选择保存位置&#xff0c;我们可以创建或修改“默认保存路径”&#xff0c;这样每次关闭PPT后…...

【PMP】有没有项目经理能看得懂这九张图?求挑战

这九张图&#xff0c;全是圈圈我的肺腑之言啊&#xff01;谁痛谁知道&#xff01; 做技术时&#xff0c;就想着30岁就转管理&#xff0c;管理岗位赚得多&#xff0c;结果发现全是烟雾弹。 做技术和代码打交道&#xff0c;做管理跟人打交道。天天开不完的会、说不完的话&#xf…...

ES6学习记录—自己记录一直更新版

1. 什么是ECMA 全称&#xff1a;European computer manufacturers association欧洲计算机制造联合会; 2、它的标准名单中的&#xff1a;ECMA — 262脚本语言的规范&#xff1a;规范化脚本语言&#xff0c;叫ECMAScript ( 一定要记住)&#xff1b;像ES5 ES6就是这样来的&#xf…...

linux操作gpio的一些记录

在linux里面使用GPIO的一些知识点记录如下&#xff1a; 一、驱动里面操作GPIO 在linux内核里面如果 pinctrl 子系统将一个 PIN 复用为 GPIO 的话&#xff0c;那么就可以用gpio 子系统提供的 API 函数操做gpio&#xff0c;比如设置 GPIO为输入输出&#xff0c;读取 GPIO 的值等…...

目前新能源汽车充电桩的发展受到哪些不利因素的影响?

目前新能源汽车充电桩的发展受到哪些不利因素的影响? 一是安装难&#xff0c;很多老旧小区没有充电桩配套施工规范&#xff0c;充电桩建设比较难&#xff0c;受到充电容量不足电表箱供电等局限性的制约&#xff0c;同时缺乏充电桩配套设施的统一规划&#xff0c;小区内只能安装…...

jenkins

Gitlab添加钩子 测试钩子 添加完成后&#xff0c;下面会出现钩子选择。点击test中的&#xff0c;push event。 出现successful&#xff0c;既添加成功。 如果添加失败&#xff0c;报错&#xff0c;更改Network...

基于深度学习的图像分割技术探究

导言&#xff1a; 图像分割是计算机视觉领域的重要任务&#xff0c;旨在将图像划分为不同的语义区域&#xff0c;实现对图像中感兴趣物体的定位和提取。深度学习作为图像分割的新兴技术&#xff0c;通过卷积神经网络&#xff08;CNN&#xff09;等模型&#xff0c;取得了显著的…...

【c++】vector的使用与模拟实现

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;初阶数据结构 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对…...

记录安装stable diffusion webui时,出现的gfpgan安装卡住的问题

参考链接&#xff1a;(145条消息) 使用stable diffusion webui时&#xff0c;安装gfpgan失败的解决方案&#xff08;windows下的操作&#xff09;_新时代原始人的博客-CSDN博客...

【开发环境】Windows下搭建TVM编译器

关于搭建TVM编译器的官方文档&#xff1a;Install from Source — tvm 0.14.dev0 documentation (apache.org) 1. 安装Anaconda 首先我们需要安装Anaconda&#xff0c;因为其中包含着我们所需要的各类依赖&#xff1a; 进入Anaconda官网https://www.anaconda.com/products/d…...

了解Unity编辑器之组件篇Video(二)

Video Player组件&#xff1a;用于在游戏中播放视频的组件。它提供了一系列属性来控制视频的播放、显示和交互。 1.Source&#xff08;视频源&#xff09;&#xff1a;用于指定视频的来源。可以选择两种不同的视频源类型&#xff1a; &#xff08;1&#xff09;Vieo Clip&#…...

安全杂记 - 状态码,DNS,编码

目录 1.状态码2.DNS解析过程3.URL编码4.HTML实体编码5.FORM表单 1.状态码 200 - 请求成功 301 - 资源&#xff08;网页等&#xff09;被永久转移到其它URL 302 - 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI 304 - 未修改。所请求的资源未修改&#…...

微信小程序 Page页面

新建页面只需要在app.json配置好路径&#xff0c;编译器自动新增了页面 项目首页&#xff0c;在app.json哪个页面是第一位&#xff0c;哪个页面就是小程序首页...

C语言实现基于Linux,epoll和多线程的WebServer服务器

代码结构&#xff1a; Server.h 头文件&#xff0c;对函数进行了声明 #pragma once #include<stdio.h> // 新建一个用于TCP监听的socket文件描述符&#xff0c;并返回 int initListenFd(unsigned short port);// 启动epoll int epollRun(int lfd);// accept建立连接 vo…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...