贪心算法相关知识

news2024/10/6 21:29:21

 

目录

 基础

定义

工作原理

步骤一:分解问题

步骤二:确定贪心策略

步骤三:求解子问题

步骤四:合并结果

适用场景

活动安排问题

找零问题

哈夫曼编码

局限性

高级

与动态规划的对比

决策方式

最优性保证

时间复杂度和空间复杂度

算法实现要点

贪心策略的证明

数据结构的选择

更多的实际应用示例

资源分配问题

文件压缩中的行程长度编码(RLE)改进

股票买卖问题(简单情况)

贪心算法的优化方向

贪心算法的挑战与应对

贪心算法的未来发展趋势

进阶

贪心算法的数学基础与理论拓展

贪心算法在复杂系统中的应用

贪心算法的性能分析与改进方法


 基础

定义

  • 贪心算法(Greedy Algorithm)是一种在每一步选择中都采取在当前状态下看起来是最好的选择的算法策略。也就是说,它不从整体最优上加以考虑,而是在局部最优解的基础上,希望通过一系列局部最优的选择来达到全局最优。

工作原理

  • 步骤一:分解问题

    • 将一个复杂的问题分解为一系列的子问题。例如,在找零问题中,要将找零的总金额分解为各种面额组合的子问题。
  • 步骤二:确定贪心策略

    • 针对每个子问题,确定一种贪心的选择策略。在活动安排问题中,贪心策略是每次选择结束时间最早的活动,这样可以在有限的时间内安排尽可能多的活动。
  • 步骤三:求解子问题

    • 按照贪心策略,依次对每个子问题进行求解,不考虑整体的最优解情况。如在哈夫曼编码问题中,贪心策略是每次选择频率最低的两个节点合并,不断构建哈夫曼树。
  • 步骤四:合并结果

    • 将各个子问题的解合并起来得到最终的解。在任务调度问题中,按照每个任务的某种贪心属性(如最短处理时间等)安排任务顺序后,最终得到整体的任务调度方案。

适用场景

  • 活动安排问题

    • 有一系列活动,每个活动都有开始时间和结束时间。要在有限的时间内安排尽可能多的活动。贪心算法按照活动结束时间的先后顺序对活动进行排序,然后依次选择不与已选活动冲突的活动,这样可以得到最多的活动安排数量。
  • 找零问题

    • 给定一个需要找零的金额,以及有限种类的硬币面额(如 1 元、5 角、1 角等)。贪心算法的策略是每次选择尽可能大面额的硬币,直到凑够找零金额。这种算法在硬币面额满足特定条件(如任意大面额都是小面额的整数倍)时能得到最优解。
  • 哈夫曼编码

    • 对于一组字符及其出现的频率,要构建一种编码方式使得总编码长度最短。贪心算法通过每次选择频率最低的两个子树合并来构建哈夫曼树,最终得到每个字符的哈夫曼编码。

局限性

  • 贪心算法并不总是能得到全局最优解。例如在旅行商问题(Travelling Salesman Problem,TSP)中,要找到一个旅行商经过所有城市且每个城市只经过一次的最短路径。如果采用贪心算法,比如每次选择距离当前城市最近的未访问城市作为下一个目标,这样得到的路径往往不是全局最短路径。因为贪心算法只考虑了当前的局部最优选择,而忽略了后续选择可能产生的影响。

高级

与动态规划的对比

  • 决策方式

    • 贪心算法在每一步只做出当前看起来最优的决策,而不考虑这一决策对未来步骤的影响。例如在任务调度问题中,如果贪心策略是选择执行时间最短的任务先执行,它不会去考虑这个任务执行完之后对其他任务的连锁影响是否会导致整体最优性被破坏。
    • 动态规划则会考虑整个问题的所有子问题以及它们之间的相互关系。动态规划会通过记录子问题的解来避免重复计算,在做决策时会综合考虑各个子问题的最优解组合来得到全局最优解。例如在最长公共子序列问题中,动态规划会通过填充一个二维数组来记录不同长度的子序列之间的公共子序列长度,最后通过回溯这个数组得到最长公共子序列,而不是像贪心算法那样只考虑局部的最优选择。
  • 最优性保证

    • 贪心算法不一定能保证得到全局最优解,只有在问题具有特定的结构性质(如拟阵结构等)时才能保证。例如在部分背包问题中,因为物品可以分割,贪心算法(按照单位价值最高优先选择物品)可以得到最优解;但在 0 - 1 背包问题中,每个物品要么全选要么不选,贪心算法就不能保证得到最优解。
    • 动态规划如果正确地定义了状态和状态转移方程,是能够保证得到全局最优解的。
  • 时间复杂度和空间复杂度

    • 贪心算法通常具有较低的时间复杂度和空间复杂度。由于它只需要进行一次扫描或者有限次数的操作就能得到解,其时间复杂度往往是多项式级别的,如或者等,空间复杂度也比较低,很多时候只需要常数级或者与输入规模线性相关的空间。例如在找零问题中,贪心算法的时间复杂度主要取决于对硬币面额的排序时间(如果需要排序的话),通常为(假设 n 是硬币面额的种类数),空间复杂度为。
    • 动态规划的时间复杂度和空间复杂度相对较高。因为它需要存储所有子问题的解,时间复杂度可能是多项式的高次幂或者指数级别的,空间复杂度也可能很高。例如在矩阵链乘法问题中,动态规划的时间复杂度是,空间复杂度是,其中 n 是矩阵的个数。

算法实现要点

  • 贪心策略的证明

    • 在使用贪心算法之前,最好能够证明贪心策略的正确性。对于一些简单的问题,可以通过直观的分析和反证法来证明。例如在活动安排问题中,可以假设存在一个最优解不是按照贪心策略(按活动结束时间最早排序选择)得到的,然后通过调整活动顺序可以证明这个最优解可以转换为按照贪心策略得到的解,从而证明贪心策略的正确性。
    • 对于复杂的问题,可能需要借助一些数学工具,如数学归纳法、拟阵理论等。例如,对于具有拟阵结构的问题,可以利用拟阵的性质来证明贪心算法的正确性。
  • 数据结构的选择

    • 根据贪心策略和问题的特点选择合适的数据结构。在找零问题中,如果硬币面额是固定的,并且不需要排序,可能只需要一个简单的数组来存储面额信息就可以了。
    • 在活动安排问题中,为了方便按照活动结束时间排序并选择活动,可以使用排序算法(如快速排序)先对活动的时间区间进行排序,这时候就需要用到数组或者链表等数据结构来存储活动信息。在哈夫曼编码问题中,构建哈夫曼树时通常会用到优先队列(最小堆或者最大堆)来高效地选择频率最低的节点进行合并操作。

更多的实际应用示例

  • 资源分配问题

    • 假设有多个任务和有限的资源(如 CPU 时间、内存等),每个任务需要一定的资源量并且有相应的收益。贪心算法可以根据不同的贪心策略来分配资源,例如按照单位资源的收益最高来分配资源给各个任务。如果资源是可分割的,这种贪心策略可能会得到较好的结果,但如果资源不可分割(如每个任务只能分配完整的 CPU 核心),贪心算法可能无法保证全局最优。
  • 文件压缩中的行程长度编码(RLE)改进

    • 在基本的行程长度编码中,它通过连续重复字符的个数和字符本身来表示数据。可以使用贪心算法对其进行改进,例如在对图像数据进行编码时,不是简单地按照顺序统计重复字符个数,而是根据图像的局部特征(如颜色块的分布等)采用贪心策略来选择更合适的编码单元,可能会提高压缩效率。
  • 股票买卖问题(简单情况)

    • 如果只能进行一次股票买入和卖出操作,并且已知股票在未来一段时间内每天的价格。贪心算法的策略可以是记录最低价格,然后在价格高于最低价格时卖出,这样可以获得最大的利润。但这种情况是比较简单的,对于更复杂的股票买卖规则(如多次买卖、手续费等情况),贪心算法可能需要更复杂的策略或者可能不再适用。

贪心算法的优化方向

  • 结合其他算法:贪心算法可以与其他算法结合使用,以提高求解问题的效率和准确性。例如,可以将贪心算法与模拟退火、遗传算法等启发式算法相结合,在贪心算法得到一个局部最优解的基础上,通过启发式算法进行进一步的搜索和优化,以期望找到更接近全局最优的解。
  • 动态调整贪心策略:在一些复杂的问题中,固定的贪心策略可能无法适应不同的情况。可以根据问题的特点和求解过程中的反馈信息,动态地调整贪心策略。例如,在网络路由问题中,可以根据网络的拥塞情况和链路质量的变化,动态地调整路由选择的贪心策略,以提高网络的性能和可靠性。
  • 多阶段贪心算法:对于一些可以分为多个阶段的问题,可以设计多阶段的贪心算法。在每个阶段,根据当前的情况选择局部最优的决策,然后在后续的阶段中根据前面阶段的决策结果进行调整和优化。例如,在项目规划问题中,可以将项目分为多个阶段,每个阶段都采用贪心算法进行资源分配和任务安排,同时考虑前一阶段的结果对后续阶段的影响。

贪心算法的挑战与应对

  • 局部最优陷阱:贪心算法的主要挑战之一是可能陷入局部最优解而无法得到全局最优解。为了避免这种情况,可以采用多种方法进行尝试。例如,可以使用不同的初始状态进行贪心算法的求解,然后选择其中最好的结果;或者在贪心算法的求解过程中,引入一定的随机性,以增加跳出局部最优解的可能性。
  • 问题的复杂性:对于一些复杂的问题,很难确定一个合适的贪心策略。在这种情况下,可以通过对问题进行分析和简化,找到问题的关键特征和约束条件,从而设计出有效的贪心策略。同时,可以通过实验和分析,评估贪心算法在不同情况下的性能和效果,以便进行进一步的优化和改进。
  • 数据的不确定性:在实际应用中,数据往往存在不确定性,这可能会影响贪心算法的性能和结果。为了应对数据的不确定性,可以采用一些鲁棒性的贪心策略,例如在选择决策时考虑多种可能的情况,并选择最稳定的决策;或者使用一些数据预处理技术,如数据清洗、数据平滑等,以减少数据的不确定性对贪心算法的影响。

贪心算法的未来发展趋势

  • 自适应贪心算法:随着人工智能和机器学习技术的发展,未来可能会出现自适应的贪心算法,能够根据问题的特点和求解过程中的反馈信息,自动调整贪心策略和参数,以提高算法的性能和适应性。
  • 并行贪心算法:对于大规模的问题,并行计算可以显著提高算法的效率。未来可能会出现并行的贪心算法,能够利用多核处理器、分布式计算等技术,同时对多个子问题进行求解,以加快算法的求解速度。
  • 贪心算法与深度学习的结合:深度学习在图像识别、自然语言处理等领域取得了巨大的成功。未来可能会出现贪心算法与深度学习相结合的方法,利用深度学习的强大特征提取能力和贪心算法的高效求解能力,解决复杂的实际问题。例如,可以使用深度学习模型对问题进行建模和预测,然后使用贪心算法进行优化和决策。

进阶

  1. 贪心算法的数学基础与理论拓展

    • 拟阵理论:拟阵是一种抽象的数学结构,它为贪心算法提供了坚实的理论基础。在拟阵中,独立集的性质类似于贪心算法中的局部最优选择。通过判断一个问题是否可以建模为拟阵,可以确定贪心算法是否能得到全局最优解。例如,在图的最小生成树问题中,可以通过将图的边集看作拟阵的元素,利用贪心算法(Kruskal 算法和 Prim 算法)有效地求解最小生成树。
    • 博弈论视角下的贪心算法:在某些情况下,可以将贪心算法看作一种博弈过程。每个决策步骤可以看作是参与者在博弈中的行动,而目标是在这个博弈中达到最优的结果。通过分析博弈的均衡状态和参与者的策略,可以更好地理解贪心算法的性能和局限性。例如,在资源分配问题中,不同的参与者可能会根据自己的利益进行决策,而贪心算法可以看作是一种逐步逼近均衡状态的过程。
  2. 贪心算法在复杂系统中的应用

    • 复杂网络分析:在复杂网络中,贪心算法可以用于节点重要性评估、社区发现等任务。例如,在评估节点重要性时,可以采用贪心算法选择具有最高度、介数等特征的节点,这些节点往往在网络的信息传播、稳定性等方面起着关键作用。在社区发现问题中,可以通过贪心算法逐步合并相似的节点或子社区,以得到网络的社区结构。
    • 供应链管理:在供应链管理中,贪心算法可以用于优化库存管理、物流路径规划等问题。例如,在库存管理中,可以根据贪心策略(如最小化库存成本、最大化服务水平等)来确定最佳的库存水平和补货策略。在物流路径规划中,可以采用贪心算法选择最短路径、最小化运输成本等目标下的最优路径。
  3. 贪心算法的性能分析与改进方法

    • 性能分析指标:除了传统的时间复杂度和空间复杂度外,还可以使用其他指标来评估贪心算法的性能。例如,可以考虑算法的近似比,即贪心算法得到的解与最优解之间的比例关系。如果一个贪心算法的近似比是有界的,那么它可以在一定程度上保证得到接近最优解的结果。此外,还可以分析算法的稳定性和鲁棒性,即在输入数据存在噪声或不确定性时,算法的性能表现。
    • 改进方法:为了提高贪心算法的性能,可以采用多种改进方法。例如,可以结合局部搜索、模拟退火等启发式算法,在贪心算法得到的解的基础上进行进一步的优化。还可以采用并行计算、分布式计算等技术,加快贪心算法的求解速度。另外,通过对问题进行更深入的分析和建模,设计更合适的贪心策略和数据结构,也可以提高算法的性能。

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

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

相关文章

C++ 算法学习——1.3 深度优先搜索

深度优先搜索:简单讲就是搜到某条路尽头,再掉头回溯搜其他的路。此中重点是尽头的判断,和对走过的路进行标记。 一般采用递归的写法,模板大致如下: DFS(node,visited):if node is in visited:returnadd node to visi…

通用mybatis-plus查询封装(QueryGenerator)

结果如下图所示 java类代码分别如下 1 package com.hdx.contractor.util.mybatis;import com.hdx.contractor.common.user.SecurityUser; import com.hdx.contractor.common.user.UserDetail; import com.hdx.contractor.util.query.oConvertUtils; import lombok.extern.slf…

OpenHarmony(鸿蒙南向开发)——轻量系统芯片移植案例(一)

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 持续更新中…… 轻量带屏解决方案之恒玄芯片移植案例 本文章基于恒玄科技BES2600W…

【AI知识点】交叉验证(Cross-Validation)

交叉验证(Cross-Validation) 是机器学习中常用的一种模型评估方法,用于评估模型的性能和泛化能力。它通过在不同的训练集和验证集上多次训练和测试模型,从而有效地评估模型在未见数据上的表现,帮助防止模型的过拟合和欠…

【RTD MCAL 篇2】 K312 UART DMA

【RTD MCAL 篇2】 K312 UART DMA 一,文档简介二, 功能实现2.1 K312 MINIEVB硬件配置2.2 EB 配置2.2.1 Mcl module2.2.2 Mcu module2.2.3 Platform module2.2.4 Port module2.2.5 Uart module2.2.6 Rm module 2.3 main code 三,测试结果 一&am…

Clio——麻省理工学院增强机器人场景理解算法

概述 机器人感知长期以来一直受到现实世界环境复杂性的挑战,通常需要固定设置和预定义对象。麻省理工学院的工程师 已经开发了Clio这项突破性的系统可以让机器人直观地理解并优先考虑周围环境中的相关元素,从而提高其高效执行任务的能力。 了解对更智…

【Python】Marmir 使用指南:Python 驱动的电子表格生成器

Marmir 是一个由 Python 驱动的电子表格生成工具,专门用于将 Python 数据结构(如字典、列表等)转换为电子表格文件(如 Excel)。Marmir 的设计目标是提供比传统电子表格库(如 xlwt)更强大和灵活的…

ctf.bugku-备份是个好习惯

访问页面得到字符串 这串字符串是重复的; d41d8cd98f00b204e9800998ecf8427e 从前端、源码上看,除了这段字符串,没有其他信息;尝试解密,长度32位;各种解密方式试试; MD5免费在线解密破解_MD5在…

文件后缀名不见了怎么办?

有一天,突然有需要更改文件的后缀名,可奇怪的是文件只有名称,后缀不见了,这该如何修改呢? 第一步:打开此电脑,最上面一栏选择“查看” 第二步:将“文件扩展名”勾选上 第三步&…

会议时如何实现扫码签到?

如何实现扫码签到? 在现代活动管理中,签到环节是不可或缺的一部分。它不仅关系到活动的顺利进行,还涉及到参与者的体验。传统的签到方式往往耗时且效率不高,而随着技术的发展,扫码签到成为了一种高效且便捷的解决方案。…

用小学生可以理解的语言讲一下什么是大模型

好的,用小学生的语言来说,大模型就像是一个超级聪明的机器人老师,它懂得很多东西,可以帮助我们做很多事情。 1. **懂得很多**:大模型知道很多知识,就像一个巨大的图书馆,里面有很多书&#xff0…

【星汇极客】单片机竞赛之2024睿抗机器人大赛-火线速递赛道(持续更新)

前言 本人是一名嵌入式学习者,在大学期间也参加了不少的竞赛并获奖,包括但不限于:江苏省电子设计竞赛省一、睿抗机器人国二、中国高校智能机器人国二、嵌入式设计竞赛国三、光电设计竞赛国三、节能减排竞赛国三。 后面会经常写一下博客&…

归并排序:递归、非递归实现、文件排序(归并排序实现)

目录 归并排序递归实现 1.归并排序基本思想 2.归并排序单趟思路 3.代码思路步骤 3.1.归并排序实现思路步骤 3.2.总结 3.2.1.数组归并与链表归并的差异 (1)数组归并 (2)链表归并 (3)总结 3.2.2.归并排序的递归实现总结 4.归并排序递归实现代码 5.归并排序递归递归展…

用AI做电子萌宠,快速涨粉变现

今天给大家分享一个很热门的小副业—AI宠物视频 项目介绍 前一阵刷到一个萌宠账号,爆款率可真高,涨粉可真快呀。 28篇笔记涨粉3.2万,点赞更是达到了十几万。其中有6篇点赞上万。 至于究竟是不是AI其实没那么重要,重要的是&…

华为OD机试 - Excel单元格数值统计(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Python/JS/C/C)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,…

安可数据库产品目录

‌国家安可数据库产品目录包括以下主要产品‌: ‌华为GaussDB、openguass: 由华为云计算技术有限公司提供。‌金仓数据库管理系统:由中电科金仓(北京)科技股份有限公司提供。‌神通数据库管理系统:由天津神…

上学迟到问题

刚看到这题时&#xff0c;我突然就有了思路。说起来挺可笑的当我写完这题后&#xff0c;并成功AC时&#xff0c;看着我那冗长的代码我陷入了深思&#xff0c;难道真的有必要写这么一长串吗? 这是我的代码 #include<stdio.h> int main(){int s,v,t;scanf("%d %d&q…

ROW_NUMBER

How to rewrite a query which uses the ROW_NUMBER() window function in versions 5.7 or earlier before window functions were supported e.g., SELECT ROW_NUMBER() OVER (PARTITION BY fieldA) AS rownum, myTable.* FROM myTable; index 用不上的 Solution Assuming…

Linux高阶——0928—Github数据上传markdown语言

1、Github三要素 仓库、提交、分支 提交 绿色&#xff1a;新加 红色&#xff1a;删除 主分支master或main 项目的存储单位——仓库 实际代码的存储单位——分支 分支的协同开发 2、本地数据上传到云端的过程 3、markdown

OpenHarmony(鸿蒙南向开发)——轻量和小型系统三方库移植指南(一)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 本文为OpenHarmony开发者提供一些组织编译形式比较常见&…