算法沉淀——贪心算法一(leetcode真题剖析)

在这里插入图片描述

算法沉淀——贪心算法一

  • 01.柠檬水找零
  • 02.将数组和减半的最少操作次数
  • 03.最大数
  • 04.摆动序列

贪心算法(Greedy Algorithm)是一种基于贪心策略的优化算法,它通常用于求解最优化问题,每一步都选择当前状态下的最优解,以期望通过局部最优的选择最终达到全局最优。贪心算法的思想是在每一步都做出在当前状态下局部最优的选择,而不考虑未来可能造成的影响。

在应用贪心算法时,通常需要满足两个基本要素:

  1. 最优子结构性质(Optimal Substructure): 问题的最优解包含了其子问题的最优解。这意味着通过解决子问题可以得到原问题的最优解。
  2. 贪心选择性质(Greedy-Choice Property): 在做每一步的选择时,选择当前状态下的最优解,即局部最优解。这样希望通过局部最优选择达到全局最优。

贪心算法适用于一些特定类型的问题,但并不适用于所有问题。它通常比动态规划算法更加高效,因为它不需要考虑所有可能的解,只需选择当前状态下的最优解。然而,贪心算法的局限性在于可能会错过全局最优解,因为它没有考虑未来的影响。

经典应用贪心算法的问题包括:

  • 活动选择问题(Activity Selection Problem): 选择一组互不相交的活动,使得参与的活动数最大。
  • 霍夫曼编码(Huffman Coding): 用变长编码表示不同字符,使得编码长度的加权和最小。
  • 最小生成树问题(Minimum Spanning Tree Problem): 在一个连通图中找到一棵包含所有顶点的树,使得树上边的权值之和最小。
  • 单源最短路径问题的Dijkstra算法: 在一个带权图中,从一个顶点出发,找到到达其他顶点的最短路径。

需要注意的是,贪心算法并不总是能够找到问题的最优解,因此在应用时需要仔细分析问题的性质,确定贪心选择是否能够保证得到全局最优解。

01.柠檬水找零

题目链接:https://leetcode.cn/problems/lemonade-change/

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

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

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

给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false

示例 1:

输入:bills = [5,5,5,10,20]
输出:true
解释:
前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
由于所有客户都得到了正确的找零,所以我们输出 true。

示例 2:

输入:bills = [5,5,10,10,20]
输出:false
解释:
前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
由于不是每位顾客都得到了正确的找零,所以答案是 false。

提示:

  • 1 <= bills.length <= 105
  • bills[i] 不是 5 就是 10 或是 20

思路

  1. 当你收到 5 美元时,可以直接收下,不需要找零。
  2. 当你收到 10 美元时,你可以找零一个 5 美元,因为这样保留了足够的 5 美元找零。
  3. 当你收到 20 美元时,可以优先选择找零一个 10 美元和一个 5 美元的组合,因为这样可以保留更多的 5 美元找零。

代码

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        int five = 0, ten = 0;
        for(int& 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;
    }
};

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

题目链接:https://leetcode.cn/problems/minimum-operations-to-halve-array-sum/

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

请你返回将 nums 数组和 至少 减少一半的 最少 操作数。

示例 1:

输入:nums = [5,19,8,1]
输出:3
解释:初始 nums 的和为 5 + 19 + 8 + 1 = 33 。
以下是将数组和减少至少一半的一种方法:
选择数字 19 并减小为 9.5 。
选择数字 9.5 并减小为 4.75 。
选择数字 8 并减小为 4 。
最终数组为 [5, 4.75, 4, 1] ,和为 5 + 4.75 + 4 + 1 = 14.75 。
nums 的和减小了 33 - 14.75 = 18.25 ,减小的部分超过了初始数组和的一半,18.25 >= 33/2 = 16.5 。
我们需要 3 个操作实现题目要求,所以返回 3 。
可以证明,无法通过少于 3 个操作使数组和减少至少一半。

示例 2:

输入:nums = [3,8,20]
输出:3
解释:初始 nums 的和为 3 + 8 + 20 = 31 。
以下是将数组和减少至少一半的一种方法:
选择数字 20 并减小为 10 。
选择数字 10 并减小为 5 。
选择数字 3 并减小为 1.5 。
最终数组为 [1.5, 8, 5] ,和为 1.5 + 8 + 5 = 14.5 。
nums 的和减小了 31 - 14.5 = 16.5 ,减小的部分超过了初始数组和的一半, 16.5 >= 31/2 = 15.5 。
我们需要 3 个操作实现题目要求,所以返回 3 。
可以证明,无法通过少于 3 个操作使数组和减少至少一半。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 107

思路

  1. 选择最大值: 每次从数组中选择当前最大的数。这可以通过使用堆来实现,具体来说是最大堆(Max Heap)。最大堆可以在O(1)时间内找到当前最大的元素。
  2. 减半: 将所选的最大值减半。这一步确保了每次选择都在尽量降低总和。
  3. 重复操作: 重复上述步骤直到数组和减少到至少一半。

代码

class Solution {
public:
    int halveArray(vector<int>& nums) {
        priority_queue<double> heap;
        double sum=0.0;
        for(int x:nums){
            heap.push(x);
            sum+=x;
        }
        sum/=2.0;

        int count=0;
        while(sum>0){
            double tmp=heap.top()/2.0;
            heap.pop();
            sum-=tmp;
            count++;
            heap.push(tmp);
        }
        return count;
    }
};

03.最大数

题目链接:https://leetcode.cn/problems/largest-number/

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

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

示例 1:

输入:nums = [10,2]
输出:"210"

示例 2:

输入:nums = [3,30,34,5,9]
输出:"9534330"

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 109

思路

  1. 将所有的数字转换为字符串,以便方便拼接和比较。
  2. 定义一个新的排序规则,按照以下原则排序:
    • 如果 A 拼接 B 大于 B 拼接 A,那么 A 在前,B 在后。
    • 如果 A 拼接 B 等于 B 拼接 A,则 AB 顺序无关。
    • 如果 A 拼接 B 小于 B 拼接 A,那么 B 在前,A 在后。
  3. 按照新的排序规则对所有数字进行排序。
  4. 将排序后的数字依次拼接,得到最大的数字。

代码

class Solution {
public:
    string largestNumber(vector<int>& nums) {
        vector<string> strs;
        for(int x:nums) strs.push_back(to_string(x));
        sort(strs.begin(),strs.end(),[](const string& s1,const string& s2){return s1+s2>s2+s1;});

        string ret;
        for(string& s:strs) ret+=s;

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

04.摆动序列

题目链接:https://leetcode.cn/problems/wiggle-subsequence/

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

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

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

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

示例 1:

输入:nums = [1,7,4,9,2,5]
输出:6
解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。

示例 2:

输入:nums = [1,17,5,10,13,15,10,5,16,8]
输出:7
解释:这个序列包含几个长度为 7 摆动序列。
其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

示例 3:

输入:nums = [1,2,3,4,5,6,7,8,9]
输出:2

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

思路

  1. 从数组的第一个元素开始,逐个比较相邻的元素,找到第一个波峰(当前元素大于前一个元素且大于后一个元素)或波谷(当前元素小于前一个元素且小于后一个元素)。
  2. 一旦找到波峰或波谷,将其计数,并开始寻找下一个波峰或波谷。在此过程中,确保不重复计数已经找到的波峰或波谷。
  3. 重复以上步骤,直到遍历整个数组。

代码

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n=nums.size();
        if(n<2) return n;

        int ret=0,left=0;
        for(int i=0;i<n-1;i++){
            int right = nums[i+1]-nums[i];
            if(right==0) continue;
            if(right*left<=0) ret++;
            left=right;
        }
        return ret+1;
    }
};

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

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

相关文章

动动嘴就能搞研发?百度Comate带你0门槛玩转代码

3月1日&#xff0c;百度旗下智能代码助手Baidu Comate 又添两大重磅能力&#xff1a;“Comate ” 开放平台、AutoWork “私人研发助理”&#xff0c;为行业首家免费开放试用。本次发布&#xff0c;Baidu Comate 将更加贴合软件研发现场&#xff0c;通过易用的研发平台、丰富的插…

Docker的安装跟基础使用一篇文章包会

目录 国内源安装新版本 1、清理环境 2、配置docker yum源 3、安装启动 4、启动Docker服务 5、修改docker数据存放位置 6、配置加速器 现在我们已经完成了docker的安装和初始配置。以下为基本测试使用 自带源安装的版本太低 docker官方源安装的话速度太慢了 所以本篇文…

2023年算法OOA-DBSCAN聚类

2023年算法OOA-DBSCAN聚类 鱼鹰优化算法&#xff08;Osprey optimization algorithm&#xff0c;OOA&#xff09;由Mohammad Dehghani 和 Pavel Trojovsk于2023年提出&#xff0c;其模拟鱼鹰的捕食行为。鱼鹰是鹰形目、鹗科、鹗属的仅有的一种中型猛禽。 DBSCAN聚类算法&#x…

RLNNA-DBSCAN聚类

RLNNA-DBSCAN聚类 RLNNA算法&#xff08;基于强化学习的神经网络优化算法&#xff09;是一种性能较佳的优化算法。DBSCAN聚类算法&#xff08;密度聚类算法&#xff09;是一种基于密度的聚类算法&#xff0c;其主要思想是通过寻找样本点周围的密度可达关系来聚类数据。 使用RL…

小白跟做江科大51单片机之DS1302可调时钟

原理部分 1.DS1302可调时钟介绍 单片机定时器主要占用CPU时间&#xff0c;掉电不能继续运行 图1 2.原理 图2 内部有寄存器&#xff0c;寄存的时候以时分秒寄存&#xff0c;以通信协议实现数据交互&#xff0c;就可以实现对数据进行访问和读写 3.主要寄存器定义 CE芯片使能…

线性代数 --- 特征值与特征向量

特征值与特征向量 已知任意向量x&#xff0c;现有矩阵A对x进行操作后&#xff0c;得到新的向量Ax。这就好比是自变量x与函数f(x)的关系一样&#xff0c;向量x通过类似“函数”的处理得到了一个新的向量Ax。这个新的向量可能和原向量x方向相同&#xff0c;也可能不同(事实上大多…

五、布局布线约束、系统优化参数、时序优化收敛 关键技术点

在实际的工程当中&#xff0c;出现了时序违例的情况如何解决呢&#xff1f; 本章内容将介绍例外约束、布局布线的具体操作&#xff0c;实现系统参数的优化。 **前言:**通过约束时钟&#xff0c;比如基准时钟&#xff0c;和生成时钟&#xff0c;让我们的综合工具知道我们的时序…

2024年阿里Android高级面试题分享,送给正在迷茫的你

前言 很多公司在招人这件事情上都会面临一个问题&#xff1b; “我们的招聘要求又不高&#xff0c;能做项目就行&#xff0c;但为什么就是招不到人&#xff1f;” 很多公司还面临一个问题&#xff0c;招聘的时候这人各方面都不错&#xff0c;但上岗了就是不出活&#xff0c;绩…

2024春招面试,文末有彩蛋

前言 Flutter 作为Google出品的一个新兴的跨平台移动客户端UI开发框架&#xff0c;正在被越来越多的开发者和组织使用&#xff0c;包括阿里的咸鱼、腾讯的微信等。 今天&#xff0c;我主要讲解Flutter中文本组件方面的Widget&#xff0c;包括Text、RichText、TextField&#…

元宇宙线上展厅——如何利用3D展示平台创新吸引客户与展示产品

在数字化转型的浪潮中&#xff0c;元宇宙线上展厅作为一种全新的虚拟展示平台&#xff0c;正以其独特的创新功能和沉浸式体验&#xff0c;吸引着越来越多的企业和用户的目光。 一、元宇宙线上展厅的创新功能 1、沉浸式体验与交互设计 元宇宙线上展厅通过先进的3D建模技术和VR技…

selenium4的相对定位

selenium4相对定位 Selenium 4新增了相对定位器&#xff0c;能帮助用户查找元素附近的其他元素。可用的相对定位器有above、below、toLeftOf、toRightOf、near。在Selenium 4中&#xff0c;find_element方法能够接受一个新方法withTagName&#xff0c;它将返回一个RelativeLoca…

《2023年DDoS攻击现状及趋势报告》

执行概要 与第一季度相比&#xff0c;2023年第二季度的DDoS攻击活动增长了387%。 电信公司遭受的攻击最为频繁&#xff0c;占总攻击量的50%&#xff0c;在2023年上半年发生了超过37,000次攻击&#xff1b;然而&#xff0c;在所有行业中&#xff0c;电信公司的攻击活动在同一时…

mac电脑总卡蓝屏是怎么回事,苹果电脑老卡蓝屏怎么办

电脑老卡蓝屏是比较常见的电脑故障之一&#xff0c;导致这一问题的出现很可能是电脑本身的硬件&#xff0c;或电脑上的驱动安装错误&#xff0c;没法运行&#xff0c;当然也不排除其他的一些因素。虽说电脑蓝屏是电脑几乎都会出现的小毛病&#xff0c;不足以致命&#xff0c;但…

Day19:信息打点-红蓝队自动化项目资产侦察武器库部署企查产权网络空间

目录 各类红蓝队优秀工具项目集合 自动化-武器库部署-F8x 自动化-网络空间-AsamF 自动化-企查信息-ENScan 自动化-综合架构-ARL&Nemo 思维导图 章节知识点 Web&#xff1a;语言/CMS/中间件/数据库/系统/WAF等 系统&#xff1a;操作系统/端口服务/网络环境/防火墙等 应…

一本书讲透ChatGPT,实现从理论到实践的跨越!大模型技术工程师必读

这里写目录标题 前言内容简介作者简介专家推荐读者对象目录直播预告 前言 OpenAI 在 2022 年 11 月推出了人工智能聊天应用—ChatGPT。它具有广泛的应用场景&#xff0c;在多项专业和学术基准测试中表现出的智力水平&#xff0c;不仅接近甚至有时超越了人类的平均水平。这使得 …

垃圾分类网站|基于Springboot框架+java+MYSQL数据库的垃圾分类网站开发设计与实现(可运行源码+数据库+文档)

目录 1.摘 要 2.系统结构设计 3.系统顺序图设计 4.数据库设计 5.系统详细设计 用户前台功能模块 管理员功能模块 垃圾分类管理员功能模块 论文参考 文末获取源码 1.摘 要 本论文主要论述了如何使用JAVA语言开发一个垃圾分类网站 &#xff0c;本系统将严格按照软件开发…

探索直播美颜SDK背后的算法:如何实现高效的美颜处理?

直播中&#xff0c;美颜功能更是成为了吸引用户的一大利器&#xff0c;为了实现这一目标&#xff0c;各大直播平台纷纷推出了美颜功能&#xff0c;而直播美颜SDK背后的算法成为了实现这一功能的关键。 一、美颜算法的重要性 美颜算法在直播美颜SDK中扮演着至关重要的角色。它不…

isNaN和Number.isNaN()的区别

一句话概括&#xff1a; isNaN()会先尝试转换为数字&#xff0c;如果无法转换为数字则返回true&#xff0c;否则返回false Number.isNaN()&#xff1a;直接检查一个值是否为NaN 示例如下&#xff1a; 对于isNaN() NaN直接就返回true "abc"是字符串且无法转换为数…

连锁经营如何降低财务成本和税务风险

连锁经营的财务是一个比较复杂的体系。连锁经营通过规模化运作&#xff0c;连锁企业可以享受采购、生产和销售方面的经济规模优势&#xff0c;从而降低采购成本、生产成本和运营成本。可以通过统一管理和监控各个门店的财务状况&#xff0c;实现资源的最优配置&#xff0c;减少…

如何单独设置cPanel的PHP扩展

我们在上周遇到购买Hostease的Linux虚拟主机客户网站页面需要使用mb_strlen函数。像这种需要特定PHP函数的设置需求&#xff0c;我们是可以单独在cPanel面板进行设置。 步骤 1&#xff1a;登录到 cPanel 打开您的 Web 浏览器&#xff0c;登录您的 cPanel 控制面板登录页面。 步…