贪心算法 Greedy Algroithm

贪心算法简介

贪心算法是一种在每一步选择中都采取在当前看来最好选择的算法。它的基本思想是从问题的某个初始解出发,通过一步步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度做最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下的方法,以迭代的方式做出相继贪心的选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解不一定是最优的,所以贪心算法不要回溯。

贪心算法的应用场景

贪心算法的应用非常广泛,包括但不限于最短路径问题、单位密度问题。这些问题的共同特点是可以通过贪婪选择属性与最优子结构属性,利用贪心算法解决。贪婪选择属性指的是通过在每个步骤中选择最优选择,可以得到一个全局(总体)最优解。

贪心算法的经典例子

1.找零钱问题(Greedy Chang-Making Problem)

假设有一定面值的纸币和硬币,当要找零钱时,贪心算法会选择最大面值的纸币和硬币,当要找零钱时,贪心算法会选择最大面值的纸币或硬币,直到零钱找完。

import java.util.Arrays;public class GreedyAlgorithm {public static void main(String[] args) {int totalAmount = 16;int[] coins = {1, 2, 5, 10};int[] change = getChange(totalAmount, coins);System.out.println("Change: " + Arrays.toString(change));}public static int[] getChange(int totalAmount, int[] coins) {int[] change = new int[coins.length];int remainingAmount = totalAmount;for (int i = coins.length - 1; i >= 0; i--) {int numCoins = remainingAmount / coins[i];change[i] = numCoins;remainingAmount -= numCoins * coins[i];}return change;}
}

2.区间调度问题(Interval Scheduling Problem)

假设有一系列的任务需要在特定时间完成,每个任务都有一个开始时间和结束时间,贪心算法会优先选择结束时间最早的任务,然后选择下一个结束时间最早的任务,一次类推。

区间调度问题是指给定一组区间,找到能够完全覆盖这些区间的最少的区间数。这个问题可以使用贪心算法来解决。

贪心算法的思路是,先按照区间的结束时间进行排序,然后从第一个区间开始遍历,依次选取结束时间最早的区间,并且这个区间的开始时间要晚于前一个区间的结束时间。这样就可以保证选取的区间数最少。

下面是用Java实现的代码:

import java.util.Arrays;
import java.util.Comparator;public class IntervalSchedule {public static int intervalSchedule(int[][] intervals) {//按结束时间对区间进行排序Arrays.sort(intervals, Comparator.comparingInt(a -> a[1]));int count = 1;  //选取的区间数int end = intervals[0][1];  //当前选择的区间的结束时间for (int i = 1; i < intervals.length; i++) {if (intervals[i][0] >= end) {//如果当前区间的开始时间晚于前一个区间的结束时间,可以选择这个区间count++;end = intervals[i][1];}}return count;}public static void main(String[] args) {int[][] intervals = {{1, 3}, {2, 4}, {3, 6}, {4, 7}, {5, 8}};int result = intervalSchedule(intervals);System.out.println("最少的区间数为:" + result);}
}

运行结果为:

最少的区间数为:3

注意,这里假设输入的区间数组是已经合法的,即每个区间的开始时间都小于结束时间。如果区间数组未按照开始时间进行排序,可以先进行排序再使用贪心算法。

3.分数背包问题(Fractional Knapsack Problem)

假设有一系列物品和一个背包,每个物品有自己的重量和价值,贪心算法会先选择性价比最高的物品放入背包,直到背包装满或者物品用完。

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;class Item {int weight;int value;public Item(int weight, int value) {this.weight = weight;this.value = value;}
}class FractionalKnapsack {public static double getMaxValue(List<Item> items, int capacity) {// 排序,按照单位价值从高到低排序items.sort(Comparator.comparingDouble(o -> (double) o.value / o.weight));double totalValue = 0;for (Item item : items) {if (capacity >= item.weight) {// 如果背包容量可以装下当前物品,则装入整个物品totalValue += item.value;capacity -= item.weight;} else {// 否则,计算当前物品的单位价值,装入剩余容量的物品totalValue += item.value * ((double) capacity / item.weight);break;}}return totalValue;}public static void main(String[] args) {List<Item> items = new ArrayList<>();items.add(new Item(10, 60));items.add(new Item(20, 100));items.add(new Item(30, 120));int capacity = 50;double maxValue = getMaxValue(items, capacity);System.out.println("最大价值为:" + maxValue);}
}

4.最小生成树问题(Minimum Spanning Tree Problem)

假设有一张图,贪心算法会先选择连接两个点之间最短的边,然后选择下一个最短的边,直到所有的点都被连接。
贪心算法解决最小生成树问题的一种实现方式是使用Prim算法。以下是一个使用Java语言实现的Prim算法示例代码:

import java.util.*;class PrimMST {private int V; // 图的顶点数private int[][] graph; // 图的邻接矩阵表示public PrimMST(int v, int[][] graph) {V = v;this.graph = graph;}// 寻找最小生成树public void findMST() {boolean[] visited = new boolean[V]; // 记录顶点是否访问过int[] parent = new int[V]; // 记录最小生成树的父节点int[] key = new int[V]; // 记录顶点到最小生成树的最小权值// 初始化key数组Arrays.fill(key, Integer.MAX_VALUE);// 第一个顶点作为最小生成树的根节点key[0] = 0;parent[0] = -1;for (int i = 0; i < V-1; i++) {int u = findMinKey(key, visited); // 选择key值最小的顶点visited[u] = true; // 将选择的顶点标记为已访问// 更新与顶点u相邻的顶点的key值和parent值for (int v = 0; v < V; v++) {if (graph[u][v] != 0 && !visited[v] && graph[u][v] < key[v]) {key[v] = graph[u][v];parent[v] = u;}}}// 输出最小生成树System.out.println("边    权值");for (int i = 1; i < V; i++) {System.out.println(parent[i] + " - " + i + "   " + graph[i][parent[i]]);}}// 找到key值最小的顶点private int findMinKey(int[] key, boolean[] visited) {int minKey = Integer.MAX_VALUE;int minIndex = -1;for (int i = 0; i < V; i++) {if (!visited[i] && key[i] < minKey) {minKey = key[i];minIndex = i;}}return minIndex;}public static void main(String args[]) {int graph[][] = new int[][] {{ 0, 2, 0, 6, 0 },{ 2, 0, 3, 8, 5 },{ 0, 3, 0, 0, 7 },{ 6, 8, 0, 0, 9 },{ 0, 5, 7, 9, 0 }};PrimMST mst = new PrimMST(5, graph);mst.findMST();}
}

这是一个简单的Prim算法实现,假设图的顶点数为5,使用邻接矩阵表示图的连接关系。在findMST()方法中,我们使用一个visited数组来记录顶点是否已经访问过,使用parent数组来记录最小生成树的父节点,使用key数组来记录顶点到最小生成树的最小权值。在每次循环找到key值最小的顶点后,我们将其标记为已访问,并更新其相邻顶点的key值和parent值。最后,输出最小生成树的边和权值。

main()方法中,我们使用一个邻接矩阵来表示图,并创建一个PrimMST对象来求解最小生成树。运行代码后,将输出最小生成树的边和权值。

5.哈夫曼编码问题(Huffman Coding Problem)

假设有一系列的字符和它们对应的频率,在使用最少的比特数来编码字符的同时,贪心算法会优先选择频率最高的字符编码长度最短。
下面是用Java实现贪心算法哈夫曼编码的示例代码:

import java.util.PriorityQueue;class HuffmanTreeNode implements Comparable<HuffmanTreeNode> {int frequency;char data;HuffmanTreeNode left, right;public HuffmanTreeNode(char data, int frequency) {this.data = data;this.frequency = frequency;}@Overridepublic int compareTo(HuffmanTreeNode node) {return this.frequency - node.frequency;}
}public class HuffmanEncoding {public static void main(String[] args) {String input = "Hello, world!";HuffmanTreeNode root = buildHuffmanTree(input);String encodedString = encode(input, root);String decodedString = decode(encodedString, root);System.out.println("Input: " + input);System.out.println("Encoded String: " + encodedString);System.out.println("Decoded String: " + decodedString);}public static HuffmanTreeNode buildHuffmanTree(String input) {int[] frequencyTable = new int[256];for (char c : input.toCharArray()) {frequencyTable[c]++;}PriorityQueue<HuffmanTreeNode> priorityQueue = new PriorityQueue<>();for (int i = 0; i < frequencyTable.length; i++) {if (frequencyTable[i] > 0) {priorityQueue.add(new HuffmanTreeNode((char) i, frequencyTable[i]));}}while (priorityQueue.size() > 1) {HuffmanTreeNode leftNode = priorityQueue.poll();HuffmanTreeNode rightNode = priorityQueue.poll();HuffmanTreeNode newNode = new HuffmanTreeNode('\0', leftNode.frequency + rightNode.frequency);newNode.left = leftNode;newNode.right = rightNode;priorityQueue.add(newNode);}return priorityQueue.poll();}public static String encode(String input, HuffmanTreeNode root) {StringBuilder sb = new StringBuilder();for (char c : input.toCharArray()) {sb.append(getEncodedString(c, root));}return sb.toString();}private static String getEncodedString(char c, HuffmanTreeNode root) {if (root == null) {return "";}if (root.data == c) {return "";}String left = getEncodedString(c, root.left);if (left != null) {return "0" + left;}String right = getEncodedString(c, root.right);if (right != null) {return "1" + right;}return null;}public static String decode(String encodedString, HuffmanTreeNode root) {StringBuilder sb = new StringBuilder();HuffmanTreeNode currentNode = root;for (char c : encodedString.toCharArray()) {if (c == '0') {currentNode = currentNode.left;} else if (c == '1') {currentNode = currentNode.right;}if (currentNode.data != '\0') {sb.append(currentNode.data);currentNode = root;}}return sb.toString();}
}

此代码实现了一个HuffmanEncoding类,其中buildHuffmanTree方法用于构建Huffman树,encode方法用于将字符串编码为Huffman编码,decode方法用于将Huffman编码解码为原始字符串。

main方法中,我们首先创建一个HuffmanEncoding对象,并将要编码的字符串作为输入进行编码。然后,我们将编码后的字符串进行解码,并将结果打印出来。

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

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

相关文章

基于SpringBoot+Vue教材订购系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

文件上传漏洞-下篇

一、白名单绕过 目录路径检测绕过 00截断 简介&#xff1a; 0x00是字符串的结束标识符&#xff0c;攻击者可以利用手动添加字符串标识符的方式来将后面的内容进行截断&#xff0c;而后面的内容又可以帮助我们绕过检测。 饶过条件 利用操作&#xff1a;Pass-12 要求&#xff…

高考志愿填报,二个准备三个重点四个原则

对于高考生而言&#xff0c;高考完毕并不是可以轻松地开始&#xff0c;接下来需要研究怎么报考的问题。如何在理想和现实中取得平衡&#xff1f;如何根据就业和专业的前景做合适的安排&#xff0c;对于还处于青少年阶段的高考生们来说不是容易的事情&#xff0c;要掌握哪些技巧…

HuggingFace CLI 命令全面指南

文章目录 安装与认证1.1 安装 HuggingFace Hub 库使用 pip 安装使用 conda 安装验证安装 1.2 认证与登录生成访问令牌使用访问令牌登录环境变量认证验证认证 下载文件2.1 下载单个文件安装 huggingface_hub 库认证与登录下载单个文件 2.2 下载特定版本的文件下载特定版本的文件…

tcp 客户端进行拆包

心跳机制服务器 Server TcpListener listen;public Server(IPAddress ip,int port) {listen new TcpListener(ip, port);} public void Start(){listen.Start(100);StartConnect(); }Dictionary<string,TcpClient> clientDic new Dictionary<string,TcpClient>…

CANoe CAPL如何模拟发送CAN错误帧?

目录 canOutputErrorFrame介绍代码output(errorframe)代码总结canOutputErrorFrame 介绍 代码 canOutputErrorFrame(errorFrame, 12, 0); //output Error Frame with 12 dominant bits on CAN1 canOutputErrorFrame(CAN2.errorFrame, 6,

快手可灵大模型开放视频续写功能,可生成最长约3分钟视频

6月21日&#xff0c;可灵再度进化&#xff0c;正式推出图生视频功能&#xff0c;支持用任意静态图像生成5s视频&#xff0c;并且可搭配不同的文本内容&#xff0c;实现丰富的视觉叙事 。 同时&#xff0c;可灵还发布了业内领先的视频续写功能&#xff0c;可为已生成的视频&…

【乐吾乐2D可视化组态编辑器】弹框

很多同学问道&#xff1a;如何弹框。Meta2d.js只通知弹框&#xff0c;不直接弹框。 原因很简单&#xff0c;我们不知道用户需要什么样的弹框&#xff0c;弹框通常涉及具体业务数据&#xff0c;只有业务自己知道。 External Player - 哔哩哔哩嵌入式外链播放器 乐吾乐2D可视化…

Chromium 开发指南2024 Mac篇-开始编译Chromium(五)

1.引言 在之前的指南中&#xff0c;我们已经详细介绍了在 macOS 上编译和开发 Chromium 的准备工作。您学会了如何安装和配置 Xcode&#xff0c;如何下载和配置 depot_tools&#xff0c;以及如何获取 Chromium 的源代码。通过这些步骤&#xff0c;您的开发环境已经搭建完毕&am…

在没有安装 Qt 的 Linux 上启动 Qt5 应用时出现 “Failed to load platform plugin ‘xcb‘“ 错误的解决方法

在Linux系统上开发和部署Qt5应用时&#xff0c;有时会遇到一个令人头痛的问题——当你在没有安装Qt SDK的系统上运行应用程序时&#xff0c;控制台出现如下错误信息&#xff1a; Failed to load platform plugin "xcb". Available platforms are:原因分析 这个问题…

如何级联移位寄存器(74HC595)

在这个项目中&#xff0c;我们将使用 74HC595 移位寄存器将 2 个移位寄存器级联在一起。这样级联移位寄存器现在可以控制 16 个输出。 当然您可以级联任意数量的移位寄存器。如果您要级联第三个移位寄存器&#xff0c;它可以控制 24 个输出。如果您级联第四个移位寄存器&#x…

任务3.8.4 利用RDD实现分组排行榜

文章目录 1. 任务说明2. 解决思路3. 准备成绩文件4. 采用交互式实现5. 采用Spark项目实战概述&#xff1a;使用Spark RDD实现分组排行榜任务背景任务目标技术选型实现步骤1. 准备数据2. 数据上传至HDFS3. 启动Spark Shell4. 读取数据生成RDD5. 数据处理6. 计算TopN7. 输出结果8…

学习es6

1、let变量 2、const常量 3、解构赋值 4、模板字符串 5、简化对象写法 6、参数默认值 7、rest参数 8、扩展运算符 9、扩展对象方法 10、扩展数组方法 11、Set 12&#xff0c;Promise 13、Module模块

Leetcode - 周赛402

目录 一&#xff0c;3185. 构成整天的下标对数目 II 二&#xff0c;3186. 施咒的最大总伤害 三&#xff0c;3187. 数组中的峰值 一&#xff0c;3185. 构成整天的下标对数目 II 这里的T1&#xff0c;T2是一个题&#xff0c;这里直接一起讲了&#xff0c; 当我们已知 x%24 的值…

Postman接口测试工具

Postman接口测试工具是一款专为API测试设计的工具&#xff0c;其强大的功能和易用性使得它在现代Web开发流程中占据了重要地位。以下是对Postman接口测试工具的详细解析&#xff1a; 一、Postman简介 Postman是一个流行的API开发工具&#xff0c;它允许开发者快速创建、共享、…

深入理解Java虚拟机(JVM)中的垃圾回收器

垃圾回收&#xff08;Garbage Collection, GC&#xff09;是现代编程语言中用于管理内存的重要机制&#xff0c;特别是在Java虚拟机&#xff08;JVM&#xff09;中。 它的基本原理是自动检测和释放不再被程序使用的内存&#xff0c;以避免内存泄漏和提高程序执行效率。 1.GC的基…

MobileNetV3轻量化YOLOv8

1 轻量化模型 一般而言,模型轻量化有三个途径: 知识蒸馏:大模型引导小模型训练,让其逼近大模型效果 轻量化模块替换:利用一些轻量化模块进行替换,减少模型参数 剪枝:通过优化算法引导模型裁剪无用的参数 MobileNetV3论文如下,自行搜索 2 修改步骤 在nn/modules的文…

Cyberdog GPTS建立过程笔记

标题&#xff1a; Xiaomi Cyberdog 简介&#xff1a; Knowledge from Cyberdogs GitBook & part of GitHub source & lqxuezhang.cn. Knowledge captured on June 21st, 2024. Editor链接&#xff08;PlusAI的GPTS专用账号&#xff09;: https://cc01.plusai.io/gpts/e…

qt+halcon实战

注意建QT工程项目用的是MSVC&#xff0c;如果选成MinGW,则会报错 INCLUDEPATH $$PWD/include INCLUDEPATH $$PWD/include/halconcppLIBS $$PWD/lib/x64-win64/halconcpp.lib LIBS $$PWD/lib/x64-win64/halcon.lib#include "halconcpp/HalconCpp.h" #include &quo…

Kubernetes Ingress 简介

前言 Ingress 是 Kubernetes 中的一种资源对象&#xff0c;用于管理从集群外部到内部服务的 HTTP 和 HTTPS 路由。它提供了灵活的路由功能、SSL/TLS 终止、负载均衡和虚拟主机支持。Ingress 需要一个 Ingress 控制器来实际处理路由&#xff0c;并且可以通过配置不同的控制器来…