贪心算法题解

前言

大家好,我是jiantaoyab,这篇文章将给大家介绍贪心算法和贪心算法题目的练习和解析,贪心算法的本质就是每一个阶段都是局部最优,从而实现全局最优。我们在做题的同时,不仅要把题目做出来,还要有严格的证明。

柠檬水找零

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

题目分析

如果顾客给5块钱,就收下。

如果顾客给10块钱,查找有没有5块钱,没有return false,有找5块钱

如果顾客给20块钱,此时有2种策略。

  1. 给顾客找10块钱和5块钱
  2. 给顾客找3张5块钱

在这道题目中5块钱的作用是很大的,假如我给顾客3张5块钱,那我剩下的5块钱就少了很多,当遇到下一个顾客可能不能找零,此时生意就做不成了。

我们用交换论证法证明一下

image-20240314133541087

代码

class Solution {
public:bool lemonadeChange(vector<int>& bills) {int five = 0, ten = 0;for(auto x : bills){if(x == 5) five++;else if(x == 10){if(five == 0) return false;five--; ten++;}else{if(ten && five){ten--;five--;} else if(five >= 3){five -= 3;}else return false;}}return true;}
};

将数组和减半的最少操作次数

给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。(注意,在后续操作中你可以对减半过的数继续执行操作)

题目分析

这个题目还是很好理解的,只要我们每次选出数组中最大的数减半,直到数组和减少到一半就是结果了。

选出最大的元素可以用大根堆。

用交换论证法证明,当完全遍历一次,就能得到结果了。

image-20240314142424681

代码

class Solution {
public:int halveArray(vector<int>& nums) {priority_queue<double> heap;double sum = 0.0;int count = 0;for(auto x : nums){heap.push(x);sum += x;        }sum /= 2;while(sum > 0){double tmp = heap.top();heap.pop();tmp /= 2.0;sum -= tmp;heap.push(tmp);count++;}return count;}
};

最大数

给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。

**注意:**输出结果可能非常大,所以你需要返回一个字符串而不是整数。

题目分析

题目要求返回组成的最大整数,那就要求大的数要放到前面,假设有2个数a,b,那么有3种情况。

ab > ba 此时 a 放到 b 的前面

ab =ba 此时 a和 b 谁放到前面都可以

ab < ba 此时 a放到 b 的前面

这么看这个过程,和排序的过程不是一样的吗?我们知道a>b,b>c,是能推出a>c的?那么在这道题中怎么证明能推出这个结论呢?

我们先来看看全序关系,全序关系用 “<=”表述 , 满足全序关系的有3个特点。

  • 反对称性:如果a≤b且b≤a,则a=b。
  • 传递性:如果a≤b且b≤c,则a≤c。
  • 完全性:对于集合中的任意两个元素,它们之间要么可以比较,要么其中一个元素大于另一个元素。

可以看到我们要证明出全序关系就行。

证明完全性:

ab 和 ba 我们看出一个数,那他们之间是能比较大小的,能比较大小就有可能存在一个元素大于另一个元素。

证明反对称性:ab <= ba ab >= ba ==> ab =ba

假设 a代表x位,b代表y位,那么ab 改写成 a* 10^y + b,b * 10^x + a;

a* 10^y + b 我举个例子,假如a= 100,b=20,那么ab = 10020,想要拼接是不是先得在100后面补2个0那就是b的位数。

带入上面的式子得
1 : a ∗ 1 0 y + b < = b ∗ 1 0 x + a 1:a* 10^y + b <= b * 10^x + a 1a10y+b<=b10x+a

2 : a ∗ 1 0 y + b > = b ∗ 1 0 x + a 2:a* 10^y + b >= b * 10^x + a 2a10y+b>=b10x+a

3 : a ∗ 1 0 y + b = = b ∗ 1 0 x + a 3:a* 10^y + b == b * 10^x + a 3a10y+b==b10x+a

用夹逼定理
a ∗ 1 0 y + b < = b ∗ 1 0 x + a < = a ∗ 1 0 y + b a* 10^y + b <= b * 10^x + a <=a*10^y+b a10y+b<=b10x+a<=a10y+b
所以
a ∗ 1 0 y + b = = b ∗ 1 0 x + a a* 10^y + b == b * 10^x + a a10y+b==b10x+a

最后证明传递性:

对于任意的 a,b,c, ab>=ba 且 bc<=cb ==> ac > ca;

假设 a代表x位,b代表y位,c代表z位。具体的改写和上面同理

特殊情况,a = b = c = 0 的话,还是套上面的公式,在本题中0 是可以当做一位数的
a ∗ 1 0 y + b > = b ∗ 1 0 x + a a* 10^y + b >= b * 10^x + a a10y+b>=b10x+a
通过移项,改写成;


a ∗ ( 1 0 y − a ) > = ( 1 0 x − b ) ∗ b a*(10^y -a) >= (10^x - b)*b a(10ya)>=(10xb)b
同样的,将剩下的2个式子也改写
b ∗ ( 1 0 z − 1 ) > = ( 1 0 y − 1 ) ∗ c b*(10^z -1) >= (10^y - 1)*c b(10z1)>=(10y1)c

a ∗ ( 1 0 z − 1 ) > = ( 1 0 x − 1 ) ∗ c a*(10^z -1) >= (10^x - 1)*c a(10z1)>=(10x1)c

可以看到最后的式子是没有b的,我们把b消去就行,我们现在讨论的是a,b,c至少都是有1位数的情况,本题0也能当成一位数,所以能当成分母除。
( 1 0 y − 1 / 1 0 x − 1 ) ∗ a > = b (10^y-1/10^x-1)*a >=b (10y1/10x1)a>=b

b > = ( 1 0 y − 1 / 1 0 z − 1 ) ∗ c b>=(10^y-1/10^z-1)*c b>=(10y1/10z1)c

通过上面2个式子的化简移项,最后得出
a ∗ ( 1 0 z − 1 ) > = ( 1 0 x − 1 ) ∗ c a*(10^z -1) >= (10^x - 1)*c a(10z1)>=(10x1)c
所以是满足全序关系的,所以我们这个题目是能排序的。

代码

class Solution {
public:string largestNumber(vector<int>& nums) {//将数字转化为字符串vector<string> tmp;for(auto x : nums) tmp.push_back(to_string(x));//排序sort(tmp.begin(), tmp.end(),[](const string& s1, const string& s2){return s1 + s2 > s2 + s1;});//返回结果string ret;for(auto s : tmp) ret += s;if(ret[0] == '0') return "0";return ret;}
};

摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 **摆动序列 。**第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

  • 例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。
  • 相反,[1, 4, 7, 2, 5][1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列最长子序列的长度

题目分析

可以看出题目要求求最长的摆动的子序列,把数列在坐标系中用点的形式画出来,然后连成折线。

在这里插入图片描述

用反证法证明

图像是连续的,所以上面所说的波峰和波谷在数学上称作极值点。

下面图片在贪心解中一个有4个极值点,假如最优解在这个情况下,能选更多的点,那它一定比4个极值点更多。

在这里插入图片描述

在这里插入图片描述

代码

class Solution {
public:int wiggleMaxLength(vector<int>& nums) {int n = nums.size();if(n < 2) return n;int ret = 0, left_trend = 0;for(int i = 0; i < n - 1; i++){int right_trend = nums[i + 1] - nums[i];if(right_trend == 0) continue; //平台直接跳过// <= 0 把起点也上if(right_trend * left_trend <= 0) ret++; //波峰或者波谷left_trend = right_trend;}return ret + 1; //把终点加上}
};

最长递增子序列

这道到题目前面的记忆化搜索的文章中已经解决过了,这次用贪心算法的思想来解答

题目分析

image-20240317114427363

在这里插入图片描述

但是上面这样的操作时间复杂度是On^2,并没有优化。这道题我们并不需要关系这个序列长什么样子,我们只关心最后一个元素是谁。
用二分来优化
在这里插入图片描述

代码

class Solution {
public:int lengthOfLIS(vector<int>& nums) {int n = nums.size();vector<int> ret;ret.push_back(nums[0]);for(int i = 1; i < n; i++){//大于最后一个元素不用二分,新开空间放入if(nums[i] > ret.back()){ret.push_back(nums[i]);}else{int left = 0, right = ret.size() - 1;//二分插入位置while(left < right){int mid = (left + right) >> 1;if(ret[mid] < nums[i]) left = mid + 1;else  right = mid;}ret[left] = nums[i];}}return ret.size();}
};

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

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

相关文章

9 个顶级免费视频压缩软件精选

视频有多种格式、不同的大小和不同的压缩级别。但是&#xff0c;您可以使用最好的视频压缩器来&#xff1a; 减小文件大小提高压缩质量更好地服务您的观众 我们将列出九个领先的视频压缩软件精选&#xff0c;您今天可以免费使用它们来增强您的视频。 9 个顶级免费视频压缩器精…

【黑马程序员】Python综合案例

文章目录 数据分析案例目的需求数据准备实践数据记录类 文件解析解析csv格式解析json文件 进行数据计算读取文件数据按日期累加数据 图表展示图标绘制最终效果展示 数据分析案例 目的 文件操作实践json库使用三方库pyecharts使用面向对象实践数据容器使用 需求 给定一个csv…

设计模式之外观模式(Facade Pattern)【结构性模式】

为什么用结构性模式&#xff1f; 结构性模式关注点“怎样组合对象/类&#xff1f;”所以我们关注下类的组合关系类结构型模式关心类的组合&#xff0c;由多个类可以组合成一个更大的&#xff08;继承&#xff09;对象结构型模式关心类与对象的组合&#xff0c;通过关联关系在一…

Hadoop大数据应用:HDFS 集群节点缩容

目录 一、实验 1.环境 2.HDFS 集群节点缩容 二、问题 1.数据迁移有哪些状态 2.数据迁移失败 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 主机架构软件版本IP备注hadoop NameNode &#xff08;已部署&#xff09; SecondaryNameNode &#xff08;已部署…

异常随笔xx1

关于过滤器和拦截器 看一下过滤器&#xff0c;过滤器我们可以分两步&#xff1a; 1.配置自定义过滤器 2.过滤器注册 这样它才会生效&#xff0c;拦截器也如此 先配置&#xff1a; RequiredArgsConstructor public class UserTransmitFilter implements Filter {private f…

裁员潮下,打工人的自我修养

法律规定的 裁员补偿&#xff1a; 1、平等协商解除的&#xff0c;底线是N1&#xff0c;上限能谈多少法律都支持 2、有客观原因解除的&#xff0c;是N1 3、强制违法辞退的&#xff0c;是2N Tips&#xff1a;基数是每月的全额税前工资&#xff0c;包括奖金绩效等&#xff0c…

strstr的模拟实现

一&#xff1a;strstr函数的定义&#xff1a; strstr函数功能的解释&#xff1a; 在一个字符串里面寻找另一个字符串的首次出现位置&#xff0c;返回值为该位置。 strstr函数要点&#xff1a; 1&#xff0c;如果 str2 是 str1 的一部分&#xff0c;它返回一个指向 str1 中 …

2024.3.15

1.单向循环链表 代码&#xff1a; #include"loop.h" //创建单向循环链表 loop_p create_loop_list() {loop_p H (loop_p)malloc(sizeof(loop));if(HNULL){printf("空间申请失败\n");return NULL;}H->len0;H->nextH;return H; } //创建节点 loop_p…

【C语言】打印用*组成的X形图案

代码如下&#xff1a; #include<stdio.h> int main() { int n 0; int i 0; int j 0; while (scanf("%d", &n) ! EOF) for (i 0; i < n; i) { for (j 0; j < n; j) { if (…

拼多多根据关键词取商品列表 API 返回值说明

一、应用场景 拼多多根据关键词取商品列表的API应用场景非常广泛&#xff0c;主要集中在电商领域&#xff0c;包括但不限于以下几个方面&#xff1a; 1、商品搜索与推荐&#xff1a;商家可以通过API接口&#xff0c;根据用户输入的关键词&#xff0c;实时获取拼多多平台上的相…

什么是布隆过滤器?

1、什么是布隆过滤器 ​ 布隆过滤器&#xff08;Bloom Filter&#xff09;是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多&#xff0c;缺…

Java习题中 哈希表的理论 有效的字母异位词 快乐数 两数之和

关于 哈希表的理论 今天最大的疑惑好像就是map的复杂度怎么算哈哈,一般n个元素map的复杂度就是On哦,不需要想得太复杂了,冲突的空间并不会造成一个量级,改变n前面的常数不会影响空间复杂度哈提醒&#xff01;熟悉好map,set的API哦 关于 有效的字母异位词 为什么遍历第二个字符…

小白必看的Python基础之函数篇

函数最重要的目的是方便我们重复使用相同的一段程序。 将一些操作隶属于一个函数&#xff0c;以后你想实现相同的操作的时候&#xff0c;只用调用函数名就可以&#xff0c;而不需要重复敲所有的语句。 函数的定义 首先&#xff0c;我们要定义一个函数, 以说明这个函数的功能…

BufferedOutputStream类讲解

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java IO相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

代码学习记录21--回溯算法第二天

随想录日记part21 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.16 主要内容&#xff1a;今天主要是结合类型的题目加深对回溯算法的理解&#xff1a;1&#xff1a;组合总和&#xff1b;2&#xff1a;电话号码的字母组合 216.组合总和III17.电话号码的字母…

【Redis知识点总结】(五)——Redis实现分布式锁

Redis知识点总结&#xff08;五&#xff09;——Redis实现分布式锁 setnxsetnx expiresetnx expire lua脚本set nx exset nx ex 随机值set nx ex 随机值 lua脚本set ex nx 随机值 lua脚本 锁续期RedissonRedLock 在Redis的众多应用场景中&#xff0c;分布式锁是Redis比…

解决分布式事务,Seata真香!

年IT寒冬&#xff0c;大厂都裁员或者准备裁员&#xff0c;作为开猿节流主要目标之一&#xff0c;我们更应该时刻保持竞争力。为了抱团取暖&#xff0c;林老师开通了《知识星球》&#xff0c;并邀请我阿里、快手、腾讯等的朋友加入&#xff0c;分享八股文、项目经验、管理经验等…

纯 CSS 实现文字换行环绕效果

实现效果 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title><…

Windows10中配置并使用nvidia-smi

1. 问题 当在window10系统中使用nvidia-smi命令时&#xff1a; 会得到提示&#xff1a;nvidia-smi不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 注&#xff1a;其实安装NVIDIA控制面板时&#xff0c;软件已内置安装了nvidia-smi.exe&#xff0c;我们只需…

如何彻底删除Windows10系统D盘文件夹中的DeliveryOptimization

DeliveryOptimization是传递优化创建的文件夹。Windows 10的Delivery Optimization&#xff08;传递优化&#xff09;功能是用于加快下载Windows更新及其他Microsoft Store应用程序的速度的一种技术。Delivery Optimization使用了一个名为“DeliveryOptimization”&#xff08;…