【数据结构】贪心算法:决策的艺术

贪心算法(Greedy Algorithm)是一类在每一步选择中都采取局部最优解的方法,希望最终能够达到全局最优解。通俗地说,贪心算法的思想就是“每一步都尽量做出最好的选择”,以期望整个过程的最终结果也达到最优状态。贪心算法在解决某些特定问题时可以提供快速且高效的方案,因此广泛应用于路径选择、调度、资源分配等领域。

贪心算法的工作原理


算法实战:找零问题

假设我们需要找零的金额为 amount,并且我们有一些面值的硬币。贪心算法的目标是尽可能少地使用硬币来找零。我们将从面值最大的硬币开始找零。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 找零函数
int coinChange(vector<int>& coins, int amount) {sort(coins.rbegin(), coins.rend()); // 从大到小排序int count = 0;for (int coin : coins) {while (amount >= coin) { // 当金额大于或等于硬币面值时amount -= coin; // 减去硬币面值count++; // 记录使用的硬币数量}}return amount == 0 ? count : -1; // 如果找零成功,返回硬币数量,否则返回-1
}int main() {vector<int> coins = {25, 10, 5, 1}; // 硬币面值int amount = 63; // 要找的金额int result = coinChange(coins, amount);if (result != -1) {cout << "最少需要使用的硬币数量: " << result << endl;} else {cout << "无法找零" << endl;}return 0;
}

实践中的挑战与扩展

虽然贪心算法在找零问题中表现出色,但并非所有硬币组合都能保证找到最优解。例如,若面值为 3 和 4 的硬币用于找零 6,贪心算法可能选择 4 + 3,而最优解为 3 + 3。这种情况下,动态规划将更适合解决问题,因为它能考虑所有可能的组合。

但通过动态规划解决的找零问题会考虑所有组合,确保最终解为全局最优。

如果不清除什么是动态规划的话可以去看我另外一篇文章

  • 【数据结构】动态规划:揭开算法优化的秘密
#include <iostream>
#include <vector>
#include <climits>
using namespace std;int coinChangeDP(vector<int>& coins, int amount) {vector<int> dp(amount + 1, INT_MAX);dp[0] = 0; // 基础情况for (int coin : coins) {for (int x = coin; x <= amount; x++) {if (dp[x - coin] != INT_MAX) {dp[x] = min(dp[x], dp[x - coin] + 1);}}}return dp[amount] == INT_MAX ? -1 : dp[amount];
}

贪心算法的优缺点

优点

  1. 高效:贪心算法的时间复杂度通常较低,在需要快速求解的情况下尤为适合。
  2. 实现简单:贪心算法的逻辑清晰,易于实现。它只需一步一步地做出决策,不需要复杂的回溯操作。
  3. 适用于动态数据:在许多实时计算中,贪心算法可以处理不断变化的数据,因为它只关心当前的最佳选择。

缺点

  1. 不能保证全局最优:贪心算法不能保证所有问题的最优解,有时会因局部选择导致全局次优解。
  2. 缺乏灵活性:贪心算法无法回溯,也不适合多步决策或组合问题。
  3. 适用范围有限:贪心算法主要适用于具有贪心选择性质和最优子结构性质的问题。

时空复杂度

如果不清除什么是时空复杂度的话可以去看我另外一篇文章

  • 【数据结构】时间复杂度和空间复杂度是什么?

时间复杂度

贪心算法的时间复杂度通常依赖于具体问题和实现方式。一般来说,它的时间复杂度可以通过以下几个方面进行分析:

  1. 排序:许多贪心算法需要对输入数据进行排序,例如在找零问题中,我们对硬币面值进行了排序。排序的时间复杂度为 ( O ( n log ⁡ n ) (O(n \log n) (O(nlogn),其中 ( n ) (n) (n) 是输入数据的规模。

  2. 遍历:贪心算法通常需要遍历输入数据,选择当前的最佳解。这个过程的时间复杂度通常为 (O(n)) 或 (O(m)),其中 (m) 是选定的子问题规模。

综合考虑,贪心算法的时间复杂度通常为 ( O ( n log ⁡ n ) ) (O(n \log n)) (O(nlogn)) ( O ( n ) ) (O(n)) (O(n)),具体取决于是否需要排序以及遍历的复杂性。

空间复杂度

贪心算法的空间复杂度通常较低,因为它通常不需要额外的存储空间来存储中间结果。常见的空间复杂度为:

  1. 输入数据存储:需要存储输入数据,时间复杂度与输入规模成正比,空间复杂度为 (O(n))。

  2. 常量空间:在大多数贪心算法中,只需使用常量空间来保存临时变量和结果,因此其额外空间复杂度通常为 (O(1))。

因此,贪心算法的空间复杂度一般为 (O(n)),但在许多情况下,其有效空间复杂度为 (O(1))。

复杂度总结

复杂度类型复杂度表达式说明
时间复杂度 ( O ( n log ⁡ n ) ) (O(n \log n)) (O(nlogn)) ( O ( n ) ) (O(n)) (O(n))取决于排序和遍历的复杂性
空间复杂度 ( O ( n ) ) (O(n)) (O(n)) ( O ( 1 ) ) (O(1)) (O(1))通常只需常量空间或输入空间

通过对时空复杂度的分析,我们可以更好地理解贪心算法的性能表现,并在实际应用中做出合理的选择。

常见应用

  • 最短路径问题

    在图算法中,Dijkstra算法就是一种基于贪心策略的算法,用来找到从起点到目标节点的最短路径。该算法在每一步选择当前节点的最短边,从而逐步构建最短路径。Dijkstra算法在权值非负的情况下非常有效,但在权值为负的情况下可能无法得到最优解。

  • 活动选择问题

    活动选择问题是典型的贪心算法应用之一。在一组互不相容的活动中,贪心算法可以帮助选择出最多的活动。例如,若有一组活动需要在不同时间段进行,使用贪心算法可以按活动的结束时间从早到晚排序,依次选择不冲突的活动,从而最大化活动数量。

  • 分数背包问题

    在背包问题中,贪心算法可用于求解“分数背包问题”,即物品可以按任意比例选择。贪心算法在此问题中选择单位重量价值最高的物品直到背包装满,从而实现价值最大化。

  • 区间调度问题

    区间调度问题是一种经典的贪心算法应用,它需要从一组区间中选择互不重叠的最大数量。贪心算法的策略是首先选择结束时间最早的区间,以便为后续区间腾出时间,从而实现最大化选择。

如何判断贪心算法是否适用?

在选择是否应用贪心算法时,通常需要满足以下两个条件:

  • 贪心选择性质:即可以通过局部最优解一步步获得全局最优解。
  • 最优子结构:问题可以通过子问题的最优解构建得到全局最优解。

如果问题不符合这两个条件,那么贪心算法可能不适用,可以考虑动态规划或回溯等更复杂的算法。

贪心算法与动态规划的区别

虽然贪心算法和动态规划都用于解决优化问题,但两者的策略截然不同。动态规划通过记忆化存储和子问题分解来保证全局最优解,而贪心算法则在每一步选择中追求最优。一般而言,当问题具有“贪心选择性质”和“最优子结构”时,贪心算法才适用;否则,动态规划可能是更好的选择。

贪心算法的实现步骤

在实际应用中,贪心算法的实现通常可以分为以下几步:

  1. 选择贪心策略:定义每一步的选择标准,确保每次选择局部最优。
  2. 构建选择序列:基于贪心策略逐步构建问题的解答。
  3. 验证全局解的可行性:确保贪心选择不会影响整体解的正确性。
  4. 执行选择:按照贪心策略选择直到获得最终解。

总结

贪心算法是一种高效、简便的算法,在特定条件下可以迅速求解最优问题。然而,贪心算法并非万全之策,适用于具有贪心选择性质和最优子结构的问题。它的应用领域广泛,涉及路径规划、活动选择、资源分配等多个方面。在选择是否使用贪心算法时,需要全面分析问题特点,确保其满足贪心算法的适用条件。

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

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

相关文章

【Python】深入理解Python的列表推导式与生成器表达式:简洁与性能的权衡

引言 Python因其简洁易懂的语法和强大的标准库&#xff0c;深受开发者的喜爱。为了提升代码的简洁性与可读性&#xff0c;Python引入了许多方便的语法特性&#xff0c;其中列表推导式和生成器表达式是非常重要的工具。这两者为我们提供了优雅的方式来生成序列数据&#xff0c;…

API接口开放与安全管控 - 原理与实践

API安全是接口开放的前提条件 在API对外开放时&#xff0c;确保其安全性至关重要&#xff0c;因为API直接暴露给外部环境&#xff0c;容易成为攻击目标。一旦被恶意利用&#xff0c;可能导致数据泄露、服务滥用等严重后果。因此&#xff0c;通过API网关实施严格的接口安全管理…

用“堆”模拟实现“优先级队列”

PriorityQueue优先级队列 1. 优先级队列的概念2. 优先队列的模拟实现3 堆的概念4. 堆的存储方式5. 堆向下调整6. 堆的创建7. 堆的插入8. 堆的删除9. 用堆模拟实现优先级队列 1. 优先级队列的概念 前面我们学习了队列&#xff0c;队列是一种“先进先出”的数据结构&#xff0c;…

智慧农业大数据平台:智汇田园,数驭未来

智慧农业大数据平台 计讯物联智慧农业大数据平台是一个集管理数字化、作业自动化、生产智能化、产品绿色化、环境信息化、服务现代化于一体的多功能监管系统。它通过与硬件产品的搭配使用&#xff0c;实现对农业生产全过程的实时监测、精准控制和科学管理。该平台集成了多个数…

blender 小车建模 建模 学习笔记

一、学习blender视频教程链接 案例4&#xff1a;狂奔的小车_建模_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Bt4y1E7qn?p14&spm_id_from333.788.videopod.episodes&vd_sourced0ea58f1127eed138a4ba5421c577eb1 二、开始建模 &#xff08;1&#xff09;创…

逻辑回归与神经网络

从逻辑回归开始学习神经网络 神经网络直观上解释&#xff0c;就是由许多相互连接的圆圈组成的网络模型&#xff1a; 而逻辑回归可以看作是这个网络中的一个圆圈&#xff1a; 圆圈被称为神经元&#xff0c;整个网络被称为神经网络。 本节的任务是我们究竟如何理解具体的一个神…

华为OD机试 - 芯片资源占用(Java 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

QT仿QQ聊天项目,第一节,创建项目并布置编辑登录界面

目录 一&#xff0c;创建项目 二&#xff0c;编辑登录界面 1&#xff0c;登录界面整体构造 2&#xff0c;登录界面的宽高 3&#xff0c;登录界面使用到的控件 4&#xff0c;登录界面中的控件所在的位置和大小 &#xff08;1&#xff09;qq图标label位置和大小 &#xff0…

MySQL-事务隔离级别

1. MySQL事务的四种隔离级别 1.1 读未提交&#xff08;READ UNCOMMITTED&#xff09; READ UNCOMMITED提供了事务之间最小限度的隔离&#xff0c;除了幻读和不可重复读取的操作外&#xff0c;处于这个隔离级别的事务可以读到其它事务还未提交的数据。 1.2 读已提交&#xf…

哪个牌子的电容笔值得入手?!实测西圣、品胜、倍思三大热门品牌!

电容笔逐渐走入了大众视野&#xff0c;不仅数码博主人手一支&#xff0c;很多上班族和学生党也开始使用电容笔来进行无纸化办公和学习。然而&#xff0c;市场上的电容笔品牌众多&#xff0c;产品质量参差不齐&#xff0c;为了帮助大家挑选出真正优质的产品&#xff0c;我花费了…

传奇开服教程之新GOM引擎登录器配置教程

现在新GOM引擎的版本比以前多了一些&#xff0c;是时候和你们分享一期新GOM引擎登录器配置教程了&#xff0c;顺便来和你们分享下新GOM引擎和老GOM引擎的区别。 新GOM引擎与老GOM的区别 1、老GOM引擎1108的pak.txt就在登录器配置文件夹下&#xff0c;新GOM引擎的pak.txt在登录…

使用 ASP.NET Core 8.0 创建最小 API

构建最小 API&#xff0c;以创建具有最小依赖项的 HTTP API。 它们非常适合需要在 ASP.NET Core 中仅包括最少文件、功能和依赖项的微服务和应用。 本教程介绍使用 ASP.NET Core 生成最小 API 的基础知识。 在 ASP.NET Core 中创建 API 的另一种方法是使用控制器。 有关在最小 …

哪些CRM系统适合医疗行业?主流10款产品全解析

本文介绍了10款crm系统&#xff1a;纷享销客、Zoho CRM、海创CRM、红云CRM、慧影CRM、易华录CRM、用友健康CRM、Highrise CRM、Maximizer CRM、Infusionsoft by Keap。 在医疗行业中&#xff0c;选择合适的客户关系管理&#xff08;CRM&#xff09;系统可能是一项令人头疼的挑战…

Redis 哨兵 总结

前言 相关系列 《Redis & 目录》&#xff08;持续更新&#xff09;《Redis & 哨兵 & 源码》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;《Redis & 哨兵 & 总结》&#xff08;学习总结/最新最准/持续更新&#xff09;《Redis & 哨兵…

学习笔记:黑马程序员JavaWeb开发教程(2024.10.26)

P3 Day01-02 需要记住&#xff1a; P4 Web前端开发 P34 Ajax介绍 对于异步交互的举例&#xff1a;浏览器中输入不同的关键词&#xff0c;会有不同的提示&#xff0c;但是浏览器没有进行刷新 同步&#xff0c;会进行等待&#xff0c;在浏览器中访问链接&#xff0c;点击网页什么…

keepalived+web 实现双机热备

环境&#xff1a;利用keeplived实现web服务器的双机热备(高可用) 注意&#xff1a; (1) 利用keeplivedweb做双击热备&#xff08;高可用&#xff09;&#xff0c;最少需要两台服务器&#xff0c;可以实现多域名对应一个VIP,并且访问不同域名&#xff0c;显示不同主页&#xf…

fetch: 取消请求、读取流、获取下载进度...

引言 Fetch API 提供了一个获取资源的接口(包括跨网络通信)。对于任何使用过 XMLHttpRequest 的开发者来说, 对于 Fetch 应该都能轻松上手, 而且新的 API 提供了更强大和灵活的功能集… 本文主要就是记录下, 在使用 Fetch 期间可能会碰到的几个小案例… 一、取消请求 在前端…

【动态规划】力扣509. 斐波那契数

目录 一、题目二、代码 一、题目 二、代码 class Solution {public int fib(int n) {if (n < 1) {return n;}int[] f new int[n 1];f[0] 0;f[1] 1;for (int i 2; i < n; i) {f[i] f[i - 1] f[i - 2];}return f[n];} }

从蚂蚁金服面试题窥探STW机制

背景 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;垃圾回收&#xff08;GC&#xff09;是一个至关重要的机制&#xff0c;它负责自动管理内存的分配和释放。然而&#xff0c;垃圾回收过程并非没有代价&#xff0c;其中最为显著的一个影响就是STW&#xff08;Stop-T…

Flink CDC系列之:学习理解核心概念——Data Pipeline

Flink CDC系列之&#xff1a;学习理解核心概念——Data Pipeline 数据管道sourcesink管道配置Table IDroutetransform案例 数据管道 由于 Flink CDC 中的事件以管道方式从上游流向下游&#xff0c;因此整个 ETL 任务被称为数据管道。 管道对应于 Flink 中的一系列操作。 要描…