【数据结构和算法】-贪心算法
贪心算法(又称贪婪算法)是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。贪心算法在有最优子结构的问题中尤为有效,它通过将问题分解为一系列更小的子问题,并依次解决这些子问题,从而得到原问题的解。
贪心算法的基本思路是从问题的某一个初始解出发,逐步逼近给定的目标,以尽可能快地求得更好的解。当某个步骤不能再继续前进时,算法就停止执行。贪心算法并不是对所有问题都能得到整体最优解,关键是贪心策略的选择。选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。
贪心算法的主要特点包括:
- 局部最优选择:在每一步,算法都根据某种局部最优的准则进行选择,以期望通过这种方式得到全局最优解。
- 简化问题:每做一次贪心选择,就将所求问题简化为一个规模更小的子问题。
- 迭代进行:贪心算法通常以自顶向下的方式进行,通过迭代的方法逐步得到问题的解。
贪心算法可以解决的问题通常具有一些特殊的性质,如贪心选择性质和最优子结构性质。贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择来达到。最优子结构性质是指问题的最优解包含其子问题的最优解。这些性质是贪心算法能够成功解决问题的关键。
接下来我们看几个例子:
找零问题
一个贪心算法的实际例子是找零问题,即给定一些面值的硬币,如何用最少数量的硬币来凑齐一个给定的金额。这个问题可以使用贪心算法来解决,基本思路是从面值最大的硬币开始,尽可能多地使用这种硬币,直到剩余的金额无法再使用这种硬币为止,然后转而使用面值次大的硬币,依此类推。
例如,假设我们有面值为1元、50分、25分、10分、5分和1分的硬币,我们需要凑齐93分。按照贪心算法的思想,我们可以按照硬币面值从大到小的顺序进行考虑:
- 首先考虑面值最大的1元硬币,但93分不足以使用1元硬币,所以我们跳过1元硬币。
- 接着考虑50分硬币,因为93分大于50分,所以我们可以使用一枚50分硬币,此时剩余金额为43分。
- 然后考虑25分硬币,因为43分大于25分,所以我们可以使用一枚25分硬币,此时剩余金额为18分。
- 接下来考虑10分硬币,因为18分大于10分,所以我们可以使用一枚10分硬币,此时剩余金额为8分。
- 再考虑5分硬币,因为8分大于5分,所以我们可以使用一枚5分硬币,此时剩余金额为3分。
- 最后,我们使用三枚1分硬币来凑齐剩余的3分。
通过贪心算法,我们使用了6枚硬币来凑齐93分,这是使用最少数量硬币的方法。
需要注意的是,贪心算法并不总是能得到最优解,但在某些情况下,如硬币找零问题中硬币面值设计合理时,贪心算法可以得到最优解。因此,在选择使用贪心算法时,需要确保问题满足贪心算法的前提条件和特性。
以下是使用贪心算法解决找零问题的 Python 代码示例:
def make_change(amount, coins):# coins 列表应按照面值从大到小的顺序排列coins.sort(reverse=True)change = [] # 用于存储找零的硬币列表remaining = amount # 剩余需要凑齐的金额for coin in coins:# 当剩余金额大于等于当前硬币的面值时,就使用该硬币while remaining >= coin:change.append(coin)remaining -= coin# 如果剩余金额已经为0,则无需继续考虑后面的硬币if remaining == 0:break# 如果最终剩余金额不为0,说明无法用给定的硬币凑齐if remaining != 0:return None # 或者可以抛出异常或返回其他错误标识return change# 示例:假设有面值为 [1, 5, 10, 25] 的硬币,需要凑齐93分
coins = [1, 5, 10, 25]
amount = 93
change_list = make_change(amount, coins)if change_list is not None:print("找零的硬币列表为:", change_list)print("所需硬币总数为:", len(change_list))
else:print("无法用给定的硬币凑齐金额")
在这段代码中,我们首先定义了一个函数 make_change,它接受两个参数:amount(需要凑齐的金额)和 coins(可用的硬币面值列表)。然后,我们按照硬币面值从大到小的顺序对硬币进行排序。接着,我们遍历排序后的硬币列表,尽可能多地使用当前硬币来凑齐剩余金额,直到剩余金额为0或者无法再使用当前硬币为止。最后,我们检查是否还有剩余的金额无法凑齐,如果有则返回 None 或抛出异常,否则返回找零的硬币列表。
注意,这段代码假设硬币面值列表已经按照从大到小的顺序排列。如果硬币面值列表未排序,你需要在调用 make_change 函数之前先对 coins 进行排序。此外,这段代码只考虑了找零硬币的数量,没有考虑找零硬币的总面值是否等于原始金额,这在实际情况中通常是隐含的,因为每一步都是根据剩余金额来选取硬币的。
网络路由流量分配
实际生产中,贪心算法常用于各种优化问题,其中一个常见的例子是在网络路由中使用贪心算法进行流量分配。下面我将给出一个简化的例子,即使用贪心算法解决带权重的网络流量分配问题。
假设我们有一个网络,其中节点代表路由器或交换机,边代表它们之间的连接,边的权重代表连接的带宽。我们的目标是分配流量,使得每条连接的带宽都得到充分利用,同时避免过载。
为了简化问题,我们假设每个节点都有一个固定的流量需求,流量只能从源节点流向目标节点,且每条边的带宽都是固定的。贪心策略可以是每次选择剩余带宽最大的边来分配流量。
以下是一个简单的 Python 代码示例,用于解决这个问题:
import heapq
from collections import defaultdictclass Network:def __init__(self, edges, demands):# edges: [(source, target, capacity), ...]# demands: {source: target_demand, ...}self.graph = defaultdict(list)self.capacities = {}self.demands = demandsself.allocated = defaultdict(int)for source, target, capacity in edges:self.graph[source].append(target)self.graph[target].append(source)self.capacities[(source, target)] = capacityself.capacities[(target, source)] = capacity# 初始化最大堆,按照剩余带宽从大到小排序self.max_heap = [(capacity, source, target) for source, target, capacity in edges]heapq.heapify(self.max_heap)def allocate_flow(self):while self.max_heap:capacity, source, target = heapq.heappop(self.max_heap)# 如果源节点的需求已经被满足,则跳过if self.allocated[source] >= self.demands[source]:continue# 计算可以分配的流量allocatable = min(capacity - self.allocated[(source, target)], self.demands[source] - self.allocated[source])# 分配流量self.allocated[(source, target)] += allocatableself.allocated[source] += allocatable# 更新剩余带宽到最大堆中remaining_capacity = capacity - self.allocated[(source, target)]if remaining_capacity > 0:heapq.heappush(self.max_heap, (remaining_capacity, source, target))# 检查是否所有需求都已满足if self.allocated[source] == self.demands[source]:break# 检查是否所有需求都得到满足return all(allocated == demand for source, demand in self.demands.items() for allocated in [self.allocated[source], self.allocated.get((source, target), 0][::2])# 示例使用
edges = [('A', 'B', 10),('A', 'C', 5),('B', 'C', 8),('B', 'D', 7),('C', 'D', 6)
]
demands = {'A': 8, 'B': 4, 'C': 2}network = Network(edges, demands)
if network.allocate_flow():print("流量分配成功!")for source, target in network.capacities:print(f"从 {source} 到 {target} 分配了 {network.allocated[(source, target)]} 单位流量")
else:print("流量分配失败,无法满足所有需求!")
在这个示例中,Network 类表示网络,它维护了一个图结构(通过邻接表表示)以及每条边的带宽。allocate_flow 方法使用贪心策略来分配流量,每次都从剩余带宽最大的边开始分配。如果成功分配了所有流量,它会打印出每条边分配的流量;否则,它会报告分配失败。
注意,这个简化示例没有考虑许多实际网络流量分配问题中的复杂因素,比如流量的动态变化、多路径路由、故障恢复等。在实际生产环境中,网络流量分配通常更加复杂,并且会结合其他算法和技术来实现高效和可靠的流量管理。
贪心算法的前提条件和特性
贪心算法需要满足的前提条件和特性主要包括以下几点:
-
最优子结构:问题的最优解可以通过子问题的最优解来推导得到。这意味着,如果我们将问题分解为若干个子问题,并且每个子问题都使用了贪心策略得到最优解,那么由这些子问题的最优解组合起来就能得到原问题的全局最优解。
-
贪心选择性质:每一步的最优选择都可以导致最终的全局最优解。也就是说,贪心算法在每一步都做出在当前看来最好的选择,并希望这样的局部最优选择能够导致全局最优解。这种性质要求我们在设计贪心算法时,能够确定每一步的局部最优选择策略。
-
无后效性:即某个状态以后的过程不会影响以前的状态,只与当前状态有关。这意味着贪心算法在做出选择后,不会因为后面的选择而改变之前的选择。
-
可行性:贪心算法所做出的选择必须是可行的,即必须满足问题的约束条件。
贪心是解决局部最优,大家一定要注意,并不一定是全局最优,全局最优需要用到其他的比如动态规划等算法。后续我们会逐步介绍。
相关文章:
【数据结构和算法】-贪心算法
贪心算法(又称贪婪算法)是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。贪心算法在有最优子结构的问题中尤为有效,它通过将问题分解为一系列…...
路由器里如何设置端口映射?
在互联网时代,我们经常需要将内部网络的服务暴露到公网以便其他人访问。直接将内部网络暴露在公网上存在一定的安全风险。为了解决这个问题,我们可以利用路由器里设置端口映射来实现将特定端口的访问请求转发到内部网络的特定设备上。 端口映射的原理 端…...
M3C芯片——支持工业级HMI应用,集成2D加速、4路串口及2路CAN
M3C芯片是一款基于 RISC-V 的高性能、国产自主、工业级高清显示与智能控制 MCU,配备强大的 2D 图形加速处理器、PNG/JPEG 解码引擎、丰富的接口,支持工业宽温,具有高可靠性、高开放性,可广泛应用于工业自动化控制、HMI人机交互、 …...
如何做时间管理?
前言 本篇是最近学习工作提效系列课程的第一篇,如何做时间管理?关于时间管理的内容老生常谈了,我自己之前也分享过针对时间管理的一些思考,比如 近期对「时间管理」的一些思考, 还有高效能人士的七个习惯的分享【读书…...
三级数据库技术考点(详解!!)
1、 答疑:【解析】分布式数据库系统按不同层次提供的分布透明性有:分片透明性;②位置透明性;③局部映像透明性,位置透明性是指数据分片的分配位置对用户是透明的,用户编写程序时只需 要考虑数据分片情况,不需要了解各分片在各个场地的分配情…...
【技术栈】Redis 企业级解决方案
SueWakeup 个人主页:SueWakeup 系列专栏:学习技术栈 个性签名&…...
(一)Linux+Windows下安装ffmpeg
一丶前言 FFmpeg是一个开源的音视频处理工具集,由多个命令行工具组成。它可以在跨平台的环境中处理、转换、编辑和流媒体处理音视频文件。 FFmpeg支持多种常见的音视频格式和编解码器,可以对音视频文件进行编码、解码、转码、剪辑、合并等操作。它具有广…...
docker的部署与安装以及部署一个docker(容器)应用及docker容器常出现的问题
docker 架构图 一、docker的部署与安装 1、在 CentOS 上安装 Docker 移除旧版本(如果有的话):sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-…...
harmonyOS简介及背景
harmonyOS的场景模式18n: 1(入口手机)8(电脑、VR、手环、iPad、智慧屏、)–wifi—n(车载、智能家居等所有)harmonyOS不需要考虑软硬件的差异,是一个兼容N种的超级终端harmonyOS干了两件事: (1&a…...
最新,955神仙公司名单(非外企)
955 神仙公司名单(非外企) 往常爆料最多的 955 神仙公司名单通常都是集中在一线城市的外企。 例如下面这张最为流行的名单图: 最近牛客网上有同学整理出了非外企的版本,其中不乏一些耳熟能详的互联网产品。 随手把名单分享给大家。…...
牛客周赛 Round 37 C.红魔馆的馆主
非常恶心的诈骗,手玩了半小时,发现了一堆规律,比如是11的倍数的偶数数位和奇数数位要相等 还搞上了逆元,是5的倍数必须0 or 5结尾,是9的倍数必须数位之和是9的倍数结果做不出来 然后不是构造是纯纯的暴搜 直接暴力看…...
AWS监控,AWS 性能监控工具
监控云部署的性能是 IT 环境正常运行的内在条件。AWS 云是一个架构良好的框架,管理员可以使用专用的AWS 性能监控工具增强服务的功能。执行AWS监视是为了跟踪在AWS环境中积极运行的应用程序工作负载和资源。AWS监视器跟踪各种AWS云指标,以帮助提高在其上…...
PHP姓名快速匿名化工具(重组脱敏)
PHP姓名重组工具(脱敏/匿名化工具) 将excel数据姓名列粘贴提交,得到随机姓随机中间字随机尾字的重组姓名 那些年自用瞎搞的代码,今日整理成网页交提交得到结果的交互功能分享。 <?php //PHP姓名重组工具(脱敏/匿名化工具) //将excel数据姓名列粘贴…...
JAVA后端调用OpenAI接口 实现打字机效果(SSE)
SSE SSE(Server-Sent Events,服务器发送事件)是一种基于HTTP协议的通信技术,它允许服务器持续地将数据推送给客户端,而无需客户端发起请求。这种通信方式通常用于实时性要求较高的场景,如实时更新、通知、或…...
超店建站携手太洋物产,共建跨境生意增长解决方案
2024年3月21日,至真科技旗下的超店建站与太洋物产在出海业务上达成了合作意向,标志着双方共同构建海外版图的合作正式启动。此次合作充分彰显了超店建站在海外业务方面的卓越技术能力和丰富经验,赢得了太洋物产的高度认可。 当天,…...
提高企业员工生产力的办法
在现代商业环境中,提高企业员工生产力是企业持续发展的关键因素之一。员工生产力的提升不仅有助于企业提高运营效率,还能增强企业的市场竞争力。那么,如何有效地提高企业员工生产力呢?本文将就此问题进行探讨。 一、引入先进技术软…...
XML Data – Semi-Structured Data XML 数据 - 半结构化数据
Outline • Structured, Semistructured, and Unstructured Data • XML Hierarchical (Tree) Data Model • Extracting XML Documents from Relational Databases • XML Documents, DTD, and XML Schema • XML Languages 结构化、半结构化和非结构化数据 - XML 层次&#x…...
Python自动化之如何利用allure生成测试报告
Allure测试报告框架帮助你轻松实现”高大上”报告展示。本文通过示例演示如何从0到1集成Allure测试框架。重点展示了如何将Allure集成到已有的自动化测试工程中、以及如何实现报表的优化展示。Allure非常强大,支持多种语言多种测试框架,无论是Java/Pytho…...
【晴问算法】入门篇—贪心算法—区间不相交问题
题目描述 给定n个开区间,从中选择尽可能多的开区间,使得这些开区间两两没有交集。 输入描述 输出描述 输出一个整数,表示最多选择的开区间个数。 样例1输入 4 1 3 2 4 3 5 6 7 输出 3 解释 最多选择(1,3)、(3,5)、(6,7)三个区间,它…...
WPF意外无法启动?try-catch也无法捕捉?0xc0000409?
文章目录 背景尝试原因解决 背景 周六在家加了一会会的班,公司电脑没关机,然后周一上班。。。诡异的事情发生了,在家远程都能运行的程序,突然运行不起来了 尝试 我对WPF程序做了如下尝试: 修改UI框架对OnStartup方…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
