当前位置: 首页 > 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…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...