【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(一)

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉zmh–CSDN博客
✨ 文章所属专栏:贪心算法篇–CSDN博客

在这里插入图片描述

文章目录

  • 一.贪心算法
    • 1.什么是贪心算法
    • 2.贪心算法的特点
  • 二.例题
    • 1.柠檬水找零
    • 2.将数组和减半的最小操作次数
    • 3.最大数
    • 4.摆动序列

一.贪心算法

1.什么是贪心算法

贪心算法(Greedy Algorithm)是一种在每一步选择中都采取在当前状态下的最优决策的算法策略。他并不从整体最优上加以考虑,而是做出在当前看来是最好的选择。

1.把解决问题的过程分为若干步骤。

2.解决每一步时都选取当前看起来最优的选择。

3.“希望”得到全局最优解。(注意是“希望”,可不一定就是最优解)

简单形容就是贪婪+鼠目寸光,因此叫做贪心算法。

下面介绍几个典型的示例:

在这里插入图片描述

2.贪心算法的特点

  • 贪心策略的提出
    • 贪心策略的提出是没有标准和模板的,可能每一道题的贪心策略都是不同的,因此在学习贪心算法的时候重点要掌握每一道题的策略,把这道题的策略当成经验。
  • 贪心策略的正确性
    • 前面提到一个词“希望”得到最优解,因为有可能“贪心策略是一个错误的方法,正确的贪心策略,是需要严格的数学证明。

二.例题

1.柠檬水找零

题目

在这里插入图片描述

在这里插入图片描述

算法原理

根据题意可以明白,顾客付钱有三种情况,如果是5美元,那就直接收下;如果是10美元,并且当前手里5美元的数量大于等于1,收下然后找零5美元,如果没有5美元,则返回false;如果是20美元,有两种找零方式,第一种:10+5;第二种:5+5+5;这里就用到了贪心的思想,优先使用第一种方式找零。如果第一次20美元使用第二种找零方式,恰好手里有三张5美元,一张10美元,如果第一次就使用三张5美元,等之后再次遇到10美元,就只剩一张10美元,不能找零。

这里用到的是交换论证法:如果20美元使用第二种找零方式,手里的10美元一直到最后也没有使用,因此10美元可以替换20美元找零时的两张5美元;如果第一次20美元使用第二种找零方式5+5+5,第二次使用第一种方式找零10+5,第二次的10可以和第一次的两张5交换,交换后无影响。

代码实现

bool lemonadeChange(vector<int>& bills){
    //设置两个变量一个用来表示5元的个数,一用来表示10元的个数
    int five = 0, ten = 0;

    for(auto x : bills){
        //如果给的是5元,直接收下
        if(x==5){
            five++;
        }
        //如果给的是10元,先判度是否有5元找零,有就找零收下,没有就返回
        if(x==10){
            if(five==0){
                return false;
            }
            else{
                five--;
                ten++;
            }
        }
        //如果给的是20元,有三种情况
        if(x==20){
            //贪心思想,优先考虑10+5找零
            if(ten&&five){
                five--;
                ten--;
            }
            //第一种不能找零,再考虑第二种找零方式5+5+5
            else if(five>=3){
                five -= 3;
            }
            //如果两种情况都不能找零,返回
            else{
                return false;
            }
        }
    }
    return true;
}

2.将数组和减半的最小操作次数

题目

在这里插入图片描述

在这里插入图片描述

算法原理

因此本道题的贪心策略:使用最少的操作次数完成数组和的减半,因此每次选择一个数减半时,都选择最大的那个数减半,这里就是贪心的思想,每次都选择最大的数减半。既然要快速获取数组中的最大数,就可以借助大根堆这个数据结构,每次都选择堆顶的元素减半,减半后从新放回堆中调整,然后循环进行,知道数组和减到一半,返回最小操作数。

代码实现

int halveArray(vector<int>& nums){
    //建立一个大根堆
    priority_queue<double> heap;

    //遍历数组求和并存放到堆中
    double sum = 0.0;
    for(int x : nums){
        heap.push(x);
        sum += x;
    }

    //先获取数组和的一半,每次减去堆顶元素的一半直到减为小于等于0
    sum /= 2.0;
    int count=0;
    while(sum>0){
        //获取堆顶元素的一半,并删去
        double t = heap.top() / 2.0;
        heap.pop();
        count++;
        sum -= t;
        heap.push(t);
    }

    return count;
}

3.最大数

题目

在这里插入图片描述

算法原理

根据题意要求,可以自定义排序规则,因为要返回的是组合后最大的数,所以按照自定义的排序规则从大到小的排序;比如现在有两个数,a和b,有两种组合方式ab和ba,如果组合后ab>ba,则a在前,b在后;如果ab=ba,则a=b;如果ab<ba,则b在前,a在后;比如示例一:a=10,b=2,组合后ab=102<ba=210,所以b(2)在前,a(10)在后,根据自定义排序规则将整个数组中的元素都排序后,然后从前往后组合就是要找的最大数。

这里有一个细节点,如何快速的将两个数组合比较?可以先将每一个数都转化成字符串的形式,组合时直接的将两个字符串相加拼接即可,这样就能快速的组合,最后排完序后,还可以直接从前往后将所有字符串拼接,就是要返回的结果。

至于为什么上面的这个自定义排序规则是正确的,可以看下面的证明过程:

在这里插入图片描述

代码实现

string largestNumber(vector<int>& nums){
    //先将每个数字转换成字符串,存放到字典数组中
    vector<string> dictionary;
    for(auto x : nums){
        dictionary.push_back(to_string(x));
    }

    //使用Lambda表达式自定义排序规则
    sort(dictionary.begin(), dictionary.end(), [&](const string& s1, const string& s2){
        return s1 + s2 > s2 + s1; 
    });

    string ret;
    for(auto s : dictionary){
        ret += s;
    }

    if(ret[0]=='0'){
        return "0";
    }
    return ret;
}

4.摆动序列

题目

在这里插入图片描述

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

//全局变量表示左侧的峰值
int left = 0;
int wiggleMaxLength(vector<int>& nums){
    //寻找波峰和波谷
    int ret = 0;

    for (int i = 0; i < nums.size(); i++){
        //如果是最后一个位置,直接+1
        if(i==nums.size()-1){
            ret++;
            break;
        }
        //先计算当前位置右侧的峰值
        int right = nums[i + 1] - nums[i];
        //如果右侧峰值等于0,跳过
        if(right==0){
            continue;
        }

        //如果左右两侧峰值相乘小于0,表示当前位置是波峰或者波谷
        if(left*right<=0){
            ret++;
        }

        //将当前位置的右侧峰值赋值给左侧,表示下一个位置的左侧峰值
        left = right;
    }

    return ret;
}

以上就是关于贪心算法以及一些练习题的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DRM系列七:Drm之CREATE_DUMB

本系列文章基于linux 5.15 DRM驱动的显存由GEM&#xff08;Graphics execution management&#xff09;管理。 一、创建流程 创建buf时&#xff0c;user层提供需要buf的width,height以及bpp(bite per pixel)&#xff0c;然后调用drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &…

Python从0到100(八十七):CNN网络详细介绍及WISDM数据集模型仿真

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

WPF进阶 | WPF 动画特效揭秘:实现炫酷的界面交互效果

WPF进阶 | WPF 动画特效揭秘&#xff1a;实现炫酷的界面交互效果 前言一、WPF 动画基础概念1.1 什么是 WPF 动画1.2 动画的基本类型1.3 动画的核心元素 二、线性动画详解2.1 DoubleAnimation 的使用2.2 ColorAnimation 实现颜色渐变 三、关键帧动画深入3.1 DoubleAnimationUsin…

实践网络安全:常见威胁与应对策略详解

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在数字化转型的浪潮中&#xff0c;网络安全的重要性已达到前所未有的高度。无论是个人用户、企业&#xff0c;还是政府机构…

web-SQL注入-CTFHub

前言 在众多的CTF平台当中&#xff0c;作者认为CTFHub对于初学者来说&#xff0c;是入门平台的不二之选。CTFHub通过自己独特的技能树模块&#xff0c;可以帮助初学者来快速入门。具体请看官方介绍&#xff1a;CTFHub。 作者更新了CTFHub系列&#xff0c;希望小伙伴们多多支持…

LabVIEW如何高频采集温度数据?

在LabVIEW中进行高频温度数据采集时&#xff0c;选择合适的传感器&#xff08;如热电偶或热电阻&#xff09;和采集硬件是关键。下面是一些建议&#xff0c;帮助实现高效的温度数据采集&#xff1a; 1. 传感器选择&#xff1a; 热电偶&#xff08;Thermocouple&#xff09;&am…

Deep Sleep 96小时:一场没有硝烟的科技保卫战

2025年1月28日凌晨3点&#xff0c;当大多数人还沉浸在梦乡时&#xff0c;一场没有硝烟的战争悄然打响。代号“Deep Sleep”的服务器突遭海量数据洪流冲击&#xff0c;警报声响彻机房&#xff0c;一场针对中国关键信息基础设施的网络攻击来势汹汹&#xff01; 面对美国发起的这场…

Golang Gin系列-9:Gin 集成Swagger生成文档

文档一直是一项乏味的工作&#xff08;以我个人的拙见&#xff09;&#xff0c;但也是编码过程中最重要的任务之一。在本文中&#xff0c;我们将学习如何将Swagger规范与Gin框架集成。我们将实现JWT认证&#xff0c;请求体作为表单数据和JSON。这里唯一的先决条件是Gin服务器。…

三、递推关系与母函数,《组合数学(第4版)》卢开澄 卢华明

文章目录 一、似函数、非函数1.1 母函数1.2 母函数的简单应用1.3 整数拆分1.4 Ferrers 图像1.5 母函数能做什么1.6 递推关系1.6.1 Hanoi 问题1.6.2 偶数个5怎么算 1.7 Fibonacci 序列1.7.1 Fibonacci 的奇妙性质1.7.2 Fibonacci 恒等式1.7.3 Fibonacci 的直接表达式1.7.4 Fibon…

97,【5】buuctf web [极客大挑战 2020]Greatphp

进入靶场 审代码 <?php // 关闭所有 PHP 错误报告&#xff0c;防止错误信息泄露可能的安全隐患 error_reporting(0);// 定义一个名为 SYCLOVER 的类 class SYCLOVER {// 定义类的公共属性 $sycpublic $syc;// 定义类的公共属性 $loverpublic $lover;// 定义魔术方法 __wa…

手机上运行AI大模型(Deepseek等)

最近deepseek的大火&#xff0c;让大家掀起新一波的本地部署运行大模型的热潮&#xff0c;特别是deepseek有蒸馏的小参数量版本&#xff0c;电脑上就相当方便了&#xff0c;直接ollamaopen-webui这种类似的组合就可以轻松地实现&#xff0c;只要硬件&#xff0c;如显存&#xf…

JAVA安全—反射机制攻击链类对象成员变量方法构造方法

前言 还是JAVA安全&#xff0c;哎&#xff0c;真的讲不完&#xff0c;太多啦。 今天主要是讲一下JAVA中的反射机制&#xff0c;因为反序列化的利用基本都是要用到这个反射机制&#xff0c;还有一些攻击链条的构造&#xff0c;也会用到&#xff0c;所以就讲一下。 什么是反射…

数据库和数据表的创建、修改、与删除

1.标识符命名规则 数据库名、表名不得超过30个字符&#xff0c;变量名限制为29个 必须只能包含A-Z,a-z,0-9,_共63个字符 数据库名、表名、字段名等对象名中间不能包含空格 同一个MySQL软件中&#xff0c;数据库不能同名&#xff1b;同一个库中&#xff0c;表不能重名&#…

(电脑版)植物大战僵尸幼儿园版本,开启你的冒险之旅!

欢迎来到植物大战僵尸中文版&#xff0c;园长Jen已准备好迎接你的挑战&#xff01;在这个充满乐趣和策略的游戏中&#xff0c;你将体验到多种游戏模式&#xff0c;每种模式都带来不同的挑战和乐趣。 游戏模式&#xff1a; 冒险模式&#xff1a;踏上刺激的冒险旅程&#xff0c;…

SpringBoot中关于knife4j 中的一些相关注解

1、效果图 对比可以明显的看到加了注解与没有加注解所表现出来的效果不同&#xff08;加了注解的更加明了清晰&#xff09; 2、实现效果 Tag注解‌用于为测试方法或测试类添加标签&#xff0c;以便在执行测试时根据标签进行过滤。使用Tag注解可以更灵活地控制测试的执行&#…

双目标定与生成深度图

基于C#联合Halcon实现双目标定整体效果 一&#xff0c;标定 1&#xff0c;标定前准备工作 &#xff08;获取描述文件与获取相机参数&#xff09; 针对标准标定板可以直接调用官方提供描述文件&#xff0c;也可以自己生成描述文件后用PS文件打印 2&#xff0c;相机标定 &…

操作系统1.4

一、操作系统内核 二、微内核与大内核 三、补充

Leetcode—598. 区间加法 II【简单】

2025每日刷题&#xff08;206&#xff09; Leetcode—598. 区间加法 II 实现代码 class Solution { public:int maxCount(int m, int n, vector<vector<int>>& ops) {int ans m * n;int x ops.size();if(ops.empty()) {return ans;}int xm ops[0][0], ym …

【机器学习篇】K-Means 算法详解:从理论到实践的全面解析

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

GWO优化LSBooST回归预测matlab

灰狼优化算法&#xff08;Grey Wolf Optimizer&#xff0c;简称 GWO&#xff09;&#xff0c;是一种群智能优化算法&#xff0c;由澳大利亚格里菲斯大学的 Mirjalii 等人于 2014 年提出。该算法的设计灵感源自灰狼群体的捕食行为&#xff0c;核心思想是模仿灰狼社会的结构与行为…