数据结构----------贪心算法
什么是贪心算法?
贪心算法(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…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...