数据结构----------贪心算法
什么是贪心算法?
贪心算法(Greedy Algorithm)是一种在问题求解过程中,每一步都采取当前状态下最优(即最有利)的选择,从而希望导致最终的全局最优解的算法策略。
贪心算法的核心思想是做选择时,每一步只考虑当前情况的最佳选择,不考虑整体情况,也不考虑这个选择将如何影响未来的选择。
下面是贪心算法的一些基本特点:
- 局部最优选择:在每一步选择中都采取当前状态下最优的选择。
- 不可回溯:一旦做出了选择,就不可撤销,也就是选择了某一部分的解之后,就不再考虑这个选择之前的其他可能性。
- 最优子结构:问题的最优解包含其子问题的最优解,子问题的最优解能被合并为问题的最优解。
贪心算法适用于具有“最优子结构”和“贪心选择性质”的问题。
以下是一些可以用贪心算法解决的问题的例子:
- 找零问题:给出一个金额,如何用最少数量的硬币找零。
- 哈夫曼编码:用于数据压缩的最优前缀编码方法。
- 图的最小生成树:例如普里姆算法(Prim’s Algorithm)和克鲁斯卡尔算法(Kruskal’s Algorithm)。
- 图的最短路径问题:迪杰斯特拉算法(Dijkstra’s Algorithm)在某些条件下可以看作是贪心算法。
贪心算法的步骤通常如下:
4. 初始化:根据问题设定,选择一个初始解作为当前解。
5. 选择:根据某种贪心标准,从候选集合中选出最优解的一个元素,并将它添加到当前解中。
6. 更新:根据上一步的选择,更新候选集合,排除不再可行的选项。
7. 循环:重复“选择”和“更新”步骤,直到达到问题的解。
贪心算法并不总是能得到最优解,它只有在问题具有贪心选择性质时才有效。对于一些问题,贪心算法可以得到最优解,而对于其他问题,贪心算法可能只能得到近似最优解。
贪心算法虽然简单高效,但在某些问题上可能无法得到最优解。以下是贪心算法的一些局限性:
8. 不能保证全局最优解:贪心算法在选择每一步的局部最优解时,可能不会导致全局最优解。这是因为贪心算法没有从整体的角度考虑问题,而是基于当前情况做出选择。
9. 不可回溯:贪心算法一旦做出选择,就不会撤销这个选择,即使这个选择后来被证明是错误的。这种不可回溯的特性意味着贪心算法可能无法纠正之前的错误选择。
10. 不适用于所有问题:贪心算法只适用于具有“贪心选择性质”和“最优子结构”的问题。如果一个问题不满足这些特性,贪心算法就不能保证找到最优解。
谈心算法的局限性
以下是贪心算法局限性的具体例子:
- 组合问题:在组合问题中,选择一个元素可能会影响其他元素的选择。贪心算法可能无法处理这种相互依赖的情况。
- 需要考虑所有可能组合的问题:对于需要考虑所有可能组合的问题,贪心算法可能无法工作,因为它只考虑当前的最优选择,而不是所有可能的组合。
- 动态规划问题:对于需要考虑过去选择对未来决策影响的问题,贪心算法通常不是最佳选择。动态规划算法更适合这类问题,因为它考虑了所有可能的选择。
以下是贪心算法局限性的具体表现: - 不能处理具有重叠子问题的情况:贪心算法通常不适用于具有重叠子问题的问题,因为它不会存储子问题的解以供后续使用。
- 可能需要额外的数据结构来支持:在某些情况下,贪心算法可能需要额外的数据结构(如优先队列)来有效地选择下一个最优元素,这可能会增加算法的复杂度。
- 局部最优解可能不构成全局最优解:在某些问题中,局部最优解的集合并不一定能够组合成全局最优解。
- 难以证明最优性:对于某些问题,证明贪心算法的最优性可能非常困难,甚至是不可能的。
因此,在使用贪心算法时,需要仔细分析问题是否适合贪心策略,以及是否存在更有效的算法(如动态规划、回溯算法等)来解决问题。
贪心算法和动态规划的区别是什么?
贪心算法和动态规划是两种不同的算法设计技术,它们在解决问题的方式上有显著的区别。以下是它们之间的一些主要区别:
- 问题解决策略:
- 贪心算法:在每一步选择中都采取当前状态下最优的选择,即局部最优解,不考虑这一选择将如何影响未来的选择。
- 动态规划:将复杂问题分解为多个子问题,每个子问题只解决一次,并将子问题的解存储起来以供后续使用,从而避免重复计算。
- 最优子结构:
- 贪心算法:通常假设通过局部最优选择可以构造出全局最优解,但这并不总是成立。
- 动态规划:明确利用问题的最优子结构性质,即问题的最优解包含其子问题的最优解。
- 决策过程:
- 贪心算法:做出决策后通常不可回溯,一旦选择了某个选项,就会一直使用这个选项。
- 动态规划:考虑所有可能的决策,并选择导致最优解的决策路径。
- 适用范围:
- 贪心算法:适用于具有贪心选择性质的问题,即局部最优选择能导致全局最优解。
- 动态规划:适用于具有重叠子问题和最优子结构性质的问题。
- 算法复杂度:
- 贪心算法:通常实现简单,运行效率高,但可能无法保证找到最优解。
- 动态规划:可能需要更多的计算和存储空间,因为它需要存储所有子问题的解,但可以保证找到最优解。
- 正确性证明:
- 贪心算法:证明其正确性通常比较困难,需要证明局部最优解能组合成全局最优解。
- 动态规划:正确性通常基于数学归纳法,通过证明最优解包含子问题最优解来证明。
- 例子:
- 贪心算法:找零问题、哈夫曼编码、图的最小生成树(如克鲁斯卡尔算法)。
- 动态规划:背包问题、最长公共子序列、最短路径问题(如贝尔曼-福特算法)。
总结来说,贪心算法是一种简化版的动态规划,它在每一步都做出最优选择,而不考虑这个选择对未来决策的影响。动态规划则考虑所有可能的决策,并通过子问题的最优解来构造全局最优解。贪心算法在某些问题上可能非常高效,但它不一定能找到最优解,而动态规划则可以保证在适用的问题上找到最优解。
贪心算法上楼梯
"贪心算法上楼梯"这个问题通常可以这样描述:假设你正在上楼梯,每次可以向上走1步、2步或3步,问到达楼梯顶部有多少种不同的走法。
这个问题实际上并不适合直接用贪心算法来解决,因为贪心算法在选择每一步时只考虑当前最优的选择,而不考虑未来的影响。在这个楼梯问题中,贪心选择并不一定能得到最优解,因为可能需要根据剩余楼梯的步数来调整每一步的选择。
不过,如果我们假设每一步都可以选择走1步、2步或3步,并且我们希望用最少的步数到达楼梯顶部,那么我们可以尝试用贪心算法的思想来解决这个问题。以下是使用贪心算法解决这个问题的步骤:
- 初始化:确定楼梯的总步数
n
。 - 贪心选择:在每一步尽可能多地走,优先选择3步,然后是2步,最后是1步。
- 计算步数:根据楼梯的总步数
n
,计算每一步选择的次数。
下面是一个简单的实现:
#include <stdio.h>
// 使用贪心算法计算上楼梯的最少步数
void greedyStairs(int n) {int steps = 0; // 总步数int threeSteps = 0; // 走3步的次数int twoSteps = 0; // 走2步的次数int oneStep = 0; // 走1步的次数// 首先尽可能多地走3步threeSteps = n / 3;n -= threeSteps * 3;// 然后尽可能多地走2步twoSteps = n / 2;n -= twoSteps * 2;// 最后走剩下的1步oneStep = n;// 输出结果printf("走3步的次数: %d\n", threeSteps);printf("走2步的次数: %d\n", twoSteps);printf("走1步的次数: %d\n", oneStep);printf("总步数: %d\n", threeSteps + twoSteps + oneStep);
}
int main() {int n;printf("请输入楼梯的总步数: ");scanf("%d", &n);greedyStairs(n);return 0;
}
请注意,这个贪心算法的实现仅仅计算了到达楼梯顶部所需的最少步数,并没有计算出所有可能的走法。实际上,要计算所有可能的走法,通常需要使用动态规划或递归算法。
贪心算法找零
贪心算法的一个经典例子是找零问题。在这个问题中,你有一个收银机,里面有一定数量的硬币,比如1元、5元、10元、20元和50元。当顾客需要找零时,你的目标是使用最少数量的硬币来凑成所需找零的金额。
以下是使用贪心算法解决找零问题的步骤:
- 初始化:确定需要找零的金额。
- 贪心选择:在每一步,选择面值最大的硬币,只要它不超过还需要找零的金额。
- 更新剩余金额:从需要找零的金额中减去所选硬币的面值。
- 重复:重复步骤2和步骤3,直到剩余找零金额为0。
下面是找零问题的一个简单实现:
#include <stdio.h>
// 硬币面值的数组,按从大到小的顺序排列
int coins[] = {50, 20, 10, 5, 1};
int numCoins = sizeof(coins) / sizeof(coins[0]);
// 使用贪心算法计算找零所需的最少硬币数量
void greedyChange(int amount) {int coinCount = 0; // 硬币总数for (int i = 0; i < numCoins; i++) {// 选择当前最大的硬币,只要它不超过剩余金额int coin = coins[i];int count = amount / coin; // 可以使用该硬币的数量coinCount += count;amount -= count * coin; // 更新剩余金额printf("使用面值%d元的硬币%d个\n", coin, count);}printf("总共需要%d个硬币\n", coinCount);
}
int main() {int amount;printf("请输入需要找零的金额: ");scanf("%d", &amount);greedyChange(amount);return 0;
}
在这个例子中,贪心算法能够给出最优解,因为我们假设硬币的面值是标准的,并且找零问题具有贪心选择性质,即每次选择最大面值的硬币不会影响后续选择的最优性。
贪心算法的其他例子包括:
- 哈夫曼编码:用于数据压缩的最优前缀编码方法。
- 图的最小生成树:例如普里姆算法(Prim’s Algorithm)和克鲁斯卡尔算法(Kruskal’s Algorithm)。
- 图的最短路径问题:迪杰斯特拉算法(Dijkstra’s Algorithm)在某些条件下可以看作是贪心算法。
这些例子展示了贪心算法在不同问题领域的应用,尽管在某些情况下需要额外的条件来保证贪心算法能够得到最优解。
相关文章:

数据结构----------贪心算法
什么是贪心算法? 贪心算法(Greedy Algorithm)是一种在问题求解过程中,每一步都采取当前状态下最优(即最有利)的选择,从而希望导致最终的全局最优解的算法策略。 贪心算法的核心思想是做选择时&…...

C++初学(11)
不知不觉就第11篇了QWQ 11.1、指针和自由存储空间 之前提到了计算机程序在存储数据时必须跟踪的3个基本属性: (1)信息存储在何处; (2)存储的值为多少; (3)存储的信息…...

Vba选择cad中不同类型图元(Select Case True语句和like用法)
Select Case True 是一个常见的VBA编程技巧,用于在多个条件之间进行选择。具体来说,Select Case True 语句的每个 Case 语句都包含一个布尔表达式,这些表达式会逐个与 True 进行比较。当其中一个表达式的结果为 True 时,对应的代码…...

Kafka基本讲解
Kafka基本讲解 一:Kafka介绍 Kafka是分布式消息队列,主要设计用于高吞吐量的数据处理和消息传输,适用于日志处理、实时数据管道等场景。Kafka作为实时数仓架构的核心组件,用于收集、缓存和分发实时数据流,支持复杂的…...

thinkphp6项目初始化配置方案二次修正版本
数据返回统一格式 app/BaseController.php新增文件内容在末尾,并在构造函数中实例化数据模型类 // 成功统一返回格式 function Result($data, $msg , $code 200, $httpCode 200): \think\response\Json {$res [code > $code,msg > $msg,data > $data];return j…...

XXE靶机教学
arp-scan -l主机发现 arp-scan -l 端口扫描 nmap -p- 192.168.48.139 服务探测 nmap -p80,5355 -sT -sC -sV 192.168.48.139 目录扫描 dirsearch -u http://192.168.48.139 访问robots.txt 发现两个可访问路径 burp抓包 测试是否存在xxe漏洞 <?xml version "1.…...

干货 | 2024步入数字化转型深水区,云原生业务稳定性如何保障(免费下载)
云原生业务的稳定性保障是一个涉及多个层面的复杂任务,以下是一些关键措施和策略,以确保云原生业务的高效稳定运行: 一、平台安全性评估与加固 云原生平台安全评估:对云原生平台(如Kubernetes、Docker等)…...

for(char c:s),std::vector<int> numbers 和std::int numbers[],.size()和.sizeof()区别
在C中当需要对某个容器或数组进行遍历时我们可以使用以下语句,c将会被赋值为s中的元素 for(char c:s)://s可以是任何满足条件的容器或数组for(int c:s):for(double c:s):for(float c:s):在C中我们来区分std::vector numbers {1, 2, 3, 4, 5};和std::int numbers[] …...

桌面云备份可以删除吗?安不安全
桌面云备份可以删除吗?答案是可以的。如果用户不需要这些备份或者想要释放存储空间,桌面云备份是可以进行删除的,并且删除桌面云备份是一个相对安全的过程,但需要注意以下几点来确保操作的安全性和数据的完整性。 一、桌面云备份…...

【爬虫实战】利用代理爬取电商数据
文章目录 前言工具介绍实战获取网站数据编写代码数据展示 推荐总结 前言 当今电商平台正经历着快速的转型与升级。随着技术的进步和用户需求的多样化,电商不仅从简单的在线购物演变为综合性的购物生态系统,还融合了人工智能、大数据和云计算等先进技术。…...

python如何统计列表中元素出现的次数
在 Python 中,可以使用多种方法来统计列表中元素出现的次数。以下是一些常用的方法: 方法 1: 使用 count() 方法 list 对象有一个内置的 count() 方法,可以直接统计某个元素在列表中出现的次数。 my_list [1, 2, 3, 2, 1, 4, 2] count_of…...

【算法】山脉数组的峰顶索引
难度:中等 题目描述: 给定一个长度为 n 的整数 山脉 数组 arr ,其中的值递增到一个 峰值元素 然后递减。 返回峰值元素的下标。 你必须设计并实现时间复杂度为 O(log(n)) 的解决方案。 示例 1: 输入:arr [0,1,0]…...

牛客 JZ31.栈的压入,弹出序列 C++写法
牛客 JZ31.栈的压入,弹出序列 C写法 思路🤔: 创建一个栈,push压入序列,然后用栈顶跟弹出序列比,如果一样就出栈并且继续比较,不一样就再次push入栈,直到压入序列走完,如果…...

PageHelper在Mybatis的一对多表关联时total数错误
最近在学习PageHelper遇到一个bug记录一下: 在Mybatis的一对多表中,PageHelper获取的total是所有的记录数,而不是我想要的第一次sql的记录数。 解决方案1: 不要在mapper层获取一对多关联,在service层先获取一&#…...

(20240806)硫氧镁 / 碱式硫酸镁-混凝土
一、目录 一篇博士论文,5篇硕士论文,南京航空航天大学双一流211,60。余红发团队 具体涉及到 (1) 碱式硫酸镁水泥的混凝土应用 、(一篇博士论文) 有微观分析 (2)混…...

string类的模拟实现(C++)
一、前言 想要模拟实现一个库中的类,那就要首先要熟悉如何使用这个类。建议通过下面博客,完成对Cstring类的学习。 C的string类-CSDN博客 二、模拟实现 我们将从string的成员函数即成员变量入手,模拟实现string类。 成员变量 string类的…...

C++_sizeof的相关知识点
1.指针的大小永远是固定的,取决于处理器位数,32位就是 4 字节,64位就是 8 字节 2.数组作为函数参数时会退化为指针,大小要按指针的计算 int func(char array[]) {printf("sizeof%d\n", sizeof(array));printf("s…...

Istio Proxy的Envoy代理架构中,Upstream提供的功能是:
Istio Proxy的Envoy代理架构中,Upstream提供的功能是: A. 接收来自Envoy连接和请求的主机,并返回响应 B. 连接的一组逻辑相同的上游主机 C. 将下游主机连接到Envoy的主机,用来发送请求并接受响应 选择A Istio Proxy的Envoy代理架…...

LeetCode 热题 HOT 100 (015/100)【宇宙最简单版】
【栈】No. 0155 最小栈【中等】👉力扣对应题目指路 希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦 欢迎关注、订阅专栏 【力扣详解】谢谢你的支持! …...

【HarmonyOS】鸿蒙应用实现截屏
【HarmonyOS】鸿蒙应用实现截屏 组件截屏 通过componentSnapshot的get函数,将需要截图的组件设置id传进去即可。 import { componentSnapshot } from kit.ArkUI; import { image } from kit.ImageKit;/*** 截图*/ Entry Component Preview struct SnapShotPage {S…...

Conda包依赖侦探:conda inspect命令全解析
Conda包依赖侦探:conda inspect命令全解析 在Conda环境中,管理包及其依赖关系是一项重要任务。conda inspect命令是一个强大的工具,它可以提供包的详细信息,包括依赖关系、链接、版本等。这对于诊断环境问题、理解包的依赖结构以…...

数模——灰色关联分析算法
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 文章目录 前言 一、基本概念了解 1.什么是灰色系统? 2.什么是关联分析? 二、模型原理 三、建模过程 1.找母序列(参考序列&am…...

Python爬虫技术 第27节 API和RESTful服务
Python 爬虫技术是一种自动化获取网页内容的方法,通常用于数据收集、信息抽取或自动化测试。在讲解 Python 爬虫技术时,我们通常会涉及到以下几个关键概念: HTTP 请求:爬虫通过发送 HTTP 请求来获取网页内容,这是爬虫与…...

音视频入门基础:WAV专题(4)——FFmpeg源码中获取WAV文件音频压缩编码格式、采样频率、声道数量、采样位数、码率的实现
音视频入门基础:WAV专题系列文章: 音视频入门基础:WAV专题(1)——使用FFmpeg命令生成WAV音频文件 音视频入门基础:WAV专题(2)——WAV格式简介 音视频入门基础:WAV专题…...

环境变量在Conda中的魔法:控制包安装的秘诀
环境变量在Conda中的魔法:控制包安装的秘诀 Conda不仅是Python和其他语言包的包管理器,它还是一个强大的环境管理器。在使用Conda时,环境变量可以极大地增强其功能,允许用户控制包的安装过程,实现定制化的安装策略。本…...

VS Code C/C++ MSVC编译器
官方教程 通过快捷方式打开VS Code是编译不了的,需要对tasks.json修改(Tasks: Configure default build task) 先创建tasks.json 复制这段配置到tasks.json,记得修改VsDevCmd.bat的路径 {"version": "2.0.0","windows": {"options"…...

【技巧】IDEA 个性化配置
【技巧】IDEA 个性化配置 自动补全 关闭大小写区分 自动导包 插件 Rainbow Brackets 彩色括号 更容易区分是哪个括号...

`pytest` 中一些常用的选项
下面列出的参数和功能涵盖了 pytest 中一些常用的选项,但 pytest 还有许多其他参数和功能。以下是一些补充的 pytest 命令行参数和功能: 其他命令行参数 测试配置 --confcutdir<path>: 只加载指定目录及其子目录中的配置文件。例如 --confcutdirs…...

fme从json中提取位置到kml中
fme从json中提取位置到kml中 简单参考,我自己要用的,越弄越复杂。 概述-模板总体结构 数据就是官方提供的数据,模板的基本节结构是读模块+转换器+写模块,最近爬取一些json文件,用到了。 1.使用json读模块读取数据 首先检查一下源数据 使用文本打开数据集,可以看到非缩…...

在Ubuntu 18.04上安装和配置pgAdmin 4服务器模式的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 pgAdmin 是一个针对 PostgreSQL 及其相关数据库管理系统的开源管理和开发平台。它使用 Python 和 jQuery 编写,支持 P…...