剖析算法内部结构----------贪心算法

什么是贪心算法?

贪心算法(Greedy Algorithm)是一种在问题求解过程中,每一步都采取当前状态下最优(即最有利)的选择,从而希望导致最终的全局最优解的算法策略。
贪心算法的核心思想是做选择时,每一步只考虑当前情况的最佳选择,不考虑整体情况,也不考虑这个选择将如何影响未来的选择。
下面是贪心算法的一些基本特点:

  1. 局部最优选择:在每一步选择中都采取当前状态下最优的选择。
  2. 不可回溯:一旦做出了选择,就不可撤销,也就是选择了某一部分的解之后,就不再考虑这个选择之前的其他可能性。
  3. 最优子结构:问题的最优解包含其子问题的最优解,子问题的最优解能被合并为问题的最优解。
    贪心算法适用于具有“最优子结构”和“贪心选择性质”的问题。
    以下是一些可以用贪心算法解决的问题的例子:
  • 找零问题:给出一个金额,如何用最少数量的硬币找零。
  • 哈夫曼编码:用于数据压缩的最优前缀编码方法。
  • 图的最小生成树:例如普里姆算法(Prim’s Algorithm)和克鲁斯卡尔算法(Kruskal’s Algorithm)。
  • 图的最短路径问题:迪杰斯特拉算法(Dijkstra’s Algorithm)在某些条件下可以看作是贪心算法。

贪心算法的步骤通常如下:
4. 初始化:根据问题设定,选择一个初始解作为当前解。
5. 选择:根据某种贪心标准,从候选集合中选出最优解的一个元素,并将它添加到当前解中。
6. 更新:根据上一步的选择,更新候选集合,排除不再可行的选项。
7. 循环:重复“选择”和“更新”步骤,直到达到问题的解。
贪心算法并不总是能得到最优解,它只有在问题具有贪心选择性质时才有效。对于一些问题,贪心算法可以得到最优解,而对于其他问题,贪心算法可能只能得到近似最优解。
贪心算法虽然简单高效,但在某些问题上可能无法得到最优解。以下是贪心算法的一些局限性:
8. 不能保证全局最优解:贪心算法在选择每一步的局部最优解时,可能不会导致全局最优解。这是因为贪心算法没有从整体的角度考虑问题,而是基于当前情况做出选择。
9. 不可回溯:贪心算法一旦做出选择,就不会撤销这个选择,即使这个选择后来被证明是错误的。这种不可回溯的特性意味着贪心算法可能无法纠正之前的错误选择。
10. 不适用于所有问题:贪心算法只适用于具有“贪心选择性质”和“最优子结构”的问题。如果一个问题不满足这些特性,贪心算法就不能保证找到最优解。

在这里插入图片描述

谈心算法的局限性

以下是贪心算法局限性的具体例子:

  • 组合问题:在组合问题中,选择一个元素可能会影响其他元素的选择。贪心算法可能无法处理这种相互依赖的情况。
  • 需要考虑所有可能组合的问题:对于需要考虑所有可能组合的问题,贪心算法可能无法工作,因为它只考虑当前的最优选择,而不是所有可能的组合。
  • 动态规划问题:对于需要考虑过去选择对未来决策影响的问题,贪心算法通常不是最佳选择。动态规划算法更适合这类问题,因为它考虑了所有可能的选择。
    以下是贪心算法局限性的具体表现:
  • 不能处理具有重叠子问题的情况:贪心算法通常不适用于具有重叠子问题的问题,因为它不会存储子问题的解以供后续使用。
  • 可能需要额外的数据结构来支持:在某些情况下,贪心算法可能需要额外的数据结构(如优先队列)来有效地选择下一个最优元素,这可能会增加算法的复杂度。
  • 局部最优解可能不构成全局最优解:在某些问题中,局部最优解的集合并不一定能够组合成全局最优解。
  • 难以证明最优性:对于某些问题,证明贪心算法的最优性可能非常困难,甚至是不可能的。
    因此,在使用贪心算法时,需要仔细分析问题是否适合贪心策略,以及是否存在更有效的算法(如动态规划、回溯算法等)来解决问题。

在这里插入图片描述

贪心算法和动态规划的区别是什么?

贪心算法和动态规划是两种不同的算法设计技术,它们在解决问题的方式上有显著的区别。以下是它们之间的一些主要区别:

  1. 问题解决策略
    • 贪心算法:在每一步选择中都采取当前状态下最优的选择,即局部最优解,不考虑这一选择将如何影响未来的选择。
    • 动态规划:将复杂问题分解为多个子问题,每个子问题只解决一次,并将子问题的解存储起来以供后续使用,从而避免重复计算。
  2. 最优子结构
    • 贪心算法:通常假设通过局部最优选择可以构造出全局最优解,但这并不总是成立。
    • 动态规划:明确利用问题的最优子结构性质,即问题的最优解包含其子问题的最优解。
  3. 决策过程
    • 贪心算法:做出决策后通常不可回溯,一旦选择了某个选项,就会一直使用这个选项。
    • 动态规划:考虑所有可能的决策,并选择导致最优解的决策路径。
  4. 适用范围
    • 贪心算法:适用于具有贪心选择性质的问题,即局部最优选择能导致全局最优解。
    • 动态规划:适用于具有重叠子问题和最优子结构性质的问题。
  5. 算法复杂度
    • 贪心算法:通常实现简单,运行效率高,但可能无法保证找到最优解。
    • 动态规划:可能需要更多的计算和存储空间,因为它需要存储所有子问题的解,但可以保证找到最优解。
  6. 正确性证明
    • 贪心算法:证明其正确性通常比较困难,需要证明局部最优解能组合成全局最优解。
    • 动态规划:正确性通常基于数学归纳法,通过证明最优解包含子问题最优解来证明。
  7. 例子
    • 贪心算法:找零问题、哈夫曼编码、图的最小生成树(如克鲁斯卡尔算法)。
    • 动态规划:背包问题、最长公共子序列、最短路径问题(如贝尔曼-福特算法)。
      总结来说,贪心算法是一种简化版的动态规划,它在每一步都做出最优选择,而不考虑这个选择对未来决策的影响。动态规划则考虑所有可能的决策,并通过子问题的最优解来构造全局最优解。贪心算法在某些问题上可能非常高效,但它不一定能找到最优解,而动态规划则可以保证在适用的问题上找到最优解。

在这里插入图片描述

贪心算法上楼梯

"贪心算法上楼梯"这个问题通常可以这样描述:假设你正在上楼梯,每次可以向上走1步、2步或3步,问到达楼梯顶部有多少种不同的走法。
这个问题实际上并不适合直接用贪心算法来解决,因为贪心算法在选择每一步时只考虑当前最优的选择,而不考虑未来的影响。在这个楼梯问题中,贪心选择并不一定能得到最优解,因为可能需要根据剩余楼梯的步数来调整每一步的选择。
不过,如果我们假设每一步都可以选择走1步、2步或3步,并且我们希望用最少的步数到达楼梯顶部,那么我们可以尝试用贪心算法的思想来解决这个问题。以下是使用贪心算法解决这个问题的步骤:

  1. 初始化:确定楼梯的总步数n
  2. 贪心选择:在每一步尽可能多地走,优先选择3步,然后是2步,最后是1步。
  3. 计算步数:根据楼梯的总步数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元。当顾客需要找零时,你的目标是使用最少数量的硬币来凑成所需找零的金额。
以下是使用贪心算法解决找零问题的步骤:

  1. 初始化:确定需要找零的金额。
  2. 贪心选择:在每一步,选择面值最大的硬币,只要它不超过还需要找零的金额。
  3. 更新剩余金额:从需要找零的金额中减去所选硬币的面值。
  4. 重复:重复步骤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)在某些条件下可以看作是贪心算法。
    这些例子展示了贪心算法在不同问题领域的应用,尽管在某些情况下需要额外的条件来保证贪心算法能够得到最优解。
    在这里插入图片描述

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

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

相关文章

StringJoiner更优雅创建含分隔符的字符序列

文章目录 1 why2 what3 how4 练习手段 1 why StringBuilder拼接包含分隔符的字符序列时&#xff0c;分隔符需要一个一个添加&#xff0c;或者需要手动删除末尾冗余的分隔符&#xff0c;代码不美观&#xff0c;不好看。 比如&#xff0c;单个字符串依次拼接时&#xff1a; Stri…

[io]进程间通信 -信号函数 —信号处理过程

sighandler_t signal(int signum, sighandler_t handler); 功能&#xff1a; 信号处理函数 参数&#xff1a; signum&#xff1a;要处理的信号 handler&#xff1a;信号处理方式 SIG_IGN&#xff1a;忽略信号 SIG_DFL&#xff1a;执行默认操作 handler&#xff1a;捕捉信 …

Ubuntu 无法进行SSH连接,开启22端口

我们在VM中安装好Ubuntu 虚拟机后&#xff0c;经常需要使用Xshell等工具进行远程连接&#xff0c;但是会出现无法连接的问题&#xff0c;原因是Ubuntu中默认关闭了SSH 服务。 1、 查看Ubuntu虚拟机IP地址 2、 利用Tabby等工具进行远程连接 命令&#xff1a;ssh ip地址 这里就是…

Ubuntu 20.04 中安装 Nginx (通过传包编译的方式)、开启关闭防火墙、开放端口号

文章目录 前言一、安装包下载二、上传服务器并解压缩三、依赖配置安装四、生成编译脚本五、编译六、查看是否编译完成七、开始安装八、查看是否安装成功九、设置为开机自启动 前言 参考大佬文章并在基础上做了点修改&#xff0c;发篇文章记录下 防止下次遇到。 参考文章&#…

leetcode169. 多数元素,摩尔投票法附证明

leetcode169. 多数元素 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例 1&#xff1a; 输入&#xff1a;nums [3,2,3] 输…

Animate软件基本概念:基本工具、工作区和颜色

在我们之前的教程中&#xff0c;有不少同学都在纠结为什么没有讲一些基本概念&#xff0c;其实我们在使用Animate软件时&#xff0c;很少会考虑某一个工具为什么这么称呼&#xff0c;它的原理又是什么&#xff0c;毕竟Animate软件只是工具。而且我们从Flash软件到现在Animate软…

008 | 基于RNN和LSTM的贵州茅台股票开盘价预测

基于RNN和LSTM的贵州茅台股票开盘价预测 项目简介&#xff1a; 本项目旨在通过使用Tushare下载贵州茅台的股票数据&#xff0c;并基于这些历史数据&#xff0c;使用TensorFlow 2.0实现循环神经网络&#xff08;RNN&#xff09;和长短期记忆网络&#xff08;LSTM&#xff09;来…

H3C MSR NAT66配置指北

正文共&#xff1a;1456 字 14 图&#xff0c;预估阅读时间&#xff1a;1 分钟 通过前面的介绍&#xff08;企业路由器配置IPv6家用宽带的PPPoE拨号示例&#xff09;&#xff0c;想必你已经可以实现让MSR路由器通过PPPoE拨号接入IPv6网络。 正常来讲&#xff0c;通过前面的配置…

Qt自定义TreeWidget,实现展开折叠按钮在右侧,且一条竖直线上对齐

效果如下&#xff1a; 图片随便找的&#xff0c;可能需要调下样式&#xff0c;代码复制可用&#xff0c;留给有需要的人。 #ifndef CustomTreeWidget_h__ #define CustomTreeWidget_h__#include <QTreeWidget> #include <QPushButton>class CCustomTreeWidget : p…

Java数据结构(六)——树和二叉树

文章目录 二叉树树初识树有关树的概念树的表示树的应用 二叉树二叉树的概念二叉树的性质二叉树的存储二叉树的遍历二叉树的操作(代码实现)遍历结点数二叉树高度查找 二叉树的相关练习对称二叉树平衡二叉树二叉树的构建及遍历前序和中序构造二叉树最近的公共祖先二叉树构建字符串…

redis的安装与命令

一、redis与memcache总体对比 1.性能 Redis&#xff1a;只使用单核&#xff0c;平均每一个核上Redis在存储小数据时比Memcached性能更高。 Memcached&#xff1a;可以使用多核&#xff0c;而在100k以上的数据中&#xff0c;Memcached性能要高于Redis。 2.内存使用效率 Mem…

【C#】计算多边形的面积

一、问题分析 在 C# 中计算多边形面积的一种常见方法是使用顶点坐标。 假设您有一个由一系列 (x, y) 顶点坐标定义的多边形&#xff0c;您可以使用“鞋带公式”&#xff08;也称为高斯公式&#xff09;来计算其面积。 如果是计算多边形的面积可以分为正常多边形、dicom图像中…

java之贪婪爬取和非贪婪爬取

public class RegexDemo6 {public static void main(String[] args) {String str"java自从95年问世以来,abbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaa" " 经历了很多版本,目前企业中用的最多是java8和java11,""因为这俩个是长期版本,下一个长期支持版本是java…

【平衡二叉树】数据结构—平衡二叉树

平衡二叉树&#xff08;Balanced Binary Tree&#xff09;是一种特殊的二叉树&#xff0c;它的左右子树的高度差不超过1&#xff0c;这样可以保证树的高度相对较低&#xff0c;从而使得查找、插入和删除操作的时间复杂度保持在 。 平衡二叉树的基本概念 1. 二叉树&#xff1a…

RTT-网络组件-AT命令-未完成

AT指令文档 调用树 at_client_init();at_client_para_init();client_parser();struct at_client {rt_device_t device;at_status_t status;char end_sign;char *send_buf;/* The maximum supported send cmd length */rt_size_t send_bufsz;/* The length of last cmd */rt_si…

【HBZ分享】Spring启动时核心refresh方法流程

refresh核心代码所在位置 在AbstractApplicationContext类中的refresh方法中 refresh的业务流程编排 调用obtainFreshBeanFactory()去创建一个全新的BeanFactory工厂&#xff0c;类型为DefaultListableBeanFctory&#xff0c;其功能为【解析xml】将里面bean标签内容解析成【…

尚硅谷谷粒商城项目笔记——十、调试前端项目renren-fast-vue【电脑CPU:AMD】

十、调试前端项目renren-fast-vue 如果遇到其他问题发在评论区&#xff0c;我看到后解决 1 先下载安装git git官网下载地址 2 登录gitee搜索人人开源找到renren-fast-vue复制下载链接。【网课视频中也有详细步骤】 3 下载完成后桌面会出现renren-fast-vue的文件夹 4 开始调…

对于springboot无法连接redis解决方案

对于springboot无法连接redis解决方案 一、测试是否能在本地应用上访问到你的redis&#xff08;如果是部署在linux上的话&#xff09;1. 开启telnet功能2. 开始测试端口是否能访问到&#xff08;适用于所有&#xff0c;包括MQ&#xff09;3. 开放6379端口4. 看spring的配置文件…

java springboot mqtt控制海康摄像头

GHHKControlService 接口 package org.gh.ghhk.service;public interface GHHKControlService {boolean monitorControl(String payload);}GHHKControlServiceImpl 实现类 ​ package org.gh.ghhk.service.impl;import com.alibaba.fastjson.JSONArray; import com.alibaba.…

MySQL —— CRUD

CRUD CRUD 即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首字母缩写。 我们常说增删查改&#xff0c;增删改查… 这里我们的增删查改是对表格的数据行进行操作的~~ 新增 1.1.1 单行数据 全列插入 插入一行新数据行&#xff0c;使用 insert into t…