LeetCode刷题笔记【26】:贪心算法专题-4(柠檬水找零、根据身高重建队列、用最少数量的箭引爆气球)

news2025/1/12 6:09:11

文章目录

  • 前置知识
  • 860.柠檬水找零
    • 题目描述
    • 解题思路
    • 代码
  • 406.根据身高重建队列
    • 题目描述
    • 解题思路
    • 代码
  • 452. 用最少数量的箭引爆气球
    • 题目描述
    • 踩坑-进行模拟
    • 正确思路的贪心
  • 总结

前置知识

参考前文

参考文章:
LeetCode刷题笔记【23】:贪心算法专题-1(分发饼干、摆动序列、最大子序和)
LeetCode刷题笔记【24】:贪心算法专题-2(买卖股票的最佳时机II、跳跃游戏、跳跃游戏II)
LeetCode刷题笔记【25】:贪心算法专题-3(K次取反后最大化的数组和、加油站、分发糖果)

860.柠檬水找零

题目描述

截图

LeetCode链接:https://leetcode.cn/problems/lemonade-change/description/

解题思路

思路: 用vector<int> counter(3,0)来记录5, 10, 20元钞票的数量;
如果顾客正好给5 , ‘ c o u n t e r [ 0 ] + + ‘ ; 如果顾客给的钱 ‘ m > 5 ‘ , `counter[0]++`; 如果顾客给的钱`m>5` ,counter[0]++;如果顾客给的钱m>5‘, target = m-5;
m=15, m=5的时候分类讨论即可;
当发现counter[0]<0时返回false;
最后返回true

代码

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        vector<int> counter(3,0);
        for(int m : bills){
            int target = m-5;
            if(target==0){//1 顾客直接给5$
                counter[0]++;
            }else if(target==5){//2 顾客给10$
                counter[1]++;
                counter[0]--;
            }else if(target==15){//3 顾客给20$
                if(counter[1]>=1){//3.1 有10$
                    counter[2]++;
                    counter[1]--;
                    counter[0]--;
                }else{//3.2 没有10$
                    counter[2]++;
                    counter[0] -= 3;
                }
            }
            if(counter[0]<0 || counter[1]<0)
                return false;
        }
        return true;
    }
};

406.根据身高重建队列

题目描述

截图

LeetCode链接:https://leetcode.cn/problems/queue-reconstruction-by-height/description/

解题思路

先按照身高, 进行从大到小排列, 身高相同的人根据k, 从小到大排列;
然后从排列后的people数组中依次提取person, 加入ans;
加入时直接通过k, 选择空位插入;

感觉似乎有些玄学, 如果一定要总结的话, 应该着眼于sort之后插入的环节:
每次插入的这个P都是未插入的person里面最高的, 相比于已经排好队的人, 是更矮的, 所以只要从前往后数k个, 直接插入即可.

代码

class Solution {
public:
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(),[](vector<int>& a, vector<int>& b){
            return (a[0]>b[0]) || (a[0]==b[0] && a[1]<b[1]);
        });
        vector<vector<int>> ans;
        for(vector<int> person : people){
            ans.insert(ans.begin()+person[1], person);
        }
        return ans;
    }
};

452. 用最少数量的箭引爆气球

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/description/

踩坑-进行模拟

思路: 创建一个unordered_map<int,int> counter, 记录从x坐标垂直向上看, 有多少个气球
每次都选择气球最多的那个x坐标发射一支箭, 然后看击破哪些气球, 更新counter
直到气球被打完
思考了一下, 还是用vector<int> counter吧, 先遍历一下points, 求一下x轴最大值

class Solution {
private:
    vector<int> refreshX(vector<vector<int>>& points, int maxX){
        vector<int> counter(maxX+1, 0);
        for(vector<int> point : points){
            for(int x=point[0]; x<=point[1]; ++x){
                counter[x]++;
            }
        }
        return counter;
    }
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.size()==0)
            return 0;
        else if(points.size()==1)
            return 1;
        int maxX=INT_MIN;
        for(vector<int> point : points){
            maxX = max(maxX, point[1]);
        }
        vector<int> counter = refreshX(points, maxX);
        // for(int i=0; i<counter.size(); ++i){
        //     cout << i << ":" << counter[i] << " " << endl;
        // }
        int ans=0;
        while(!points.empty()){
            ans ++;// 没有跳出, 那么本轮一定要射出一箭
            // 寻找本轮需要在哪个位置(shootingX)射箭
            int shootingX=0, shootingNum=INT_MIN;
            for(int i=1; i<counter.size(); ++i){
                if(counter[i] > shootingNum){
                    shootingNum = counter[i];
                    shootingX = i;
                }
            }
            for(int i=0; i<points.size(); ++i){
                points.erase(remove_if(points.begin(), points.end(), [shootingX](vector<int> p){
                    return p[0]<=shootingX && p[1]>=shootingX;
                }), points.end());
            }
            counter = refreshX(points, maxX);
        }
        return ans;
    }
};

以上写法没问题, 但是没有考虑区间为负的情况
这样的话咱们还是用unordered_map

class Solution {
private:
    map<int,int> refreshX(vector<vector<int>>& points){
        map<int,int> counter;
        for(vector<int> point : points){
            for(int x=point[0]; x<=point[1]; ++x){
                counter[x]++;
            }
        }
        return counter;
    }
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.size()==0)
            return 0;
        else if(points.size()==1)
            return 1;
        bool overlapping = false;
        for(int i=0; i<points.size()-1; ++i){
            if(points[i][1]>=points[i+1][0])
                overlapping=true;
        }
        if(overlapping==false)
            return points.size();

        map<int,int> counter = refreshX(points);
        int ans=0;
        while(!points.empty()){
            ans ++;// 没有跳出, 那么本轮一定要射出一箭
            // 寻找本轮需要在哪个位置(shootingX)射箭
            // cout << "此时的counter情况是: " ;
            // for(auto& pair : counter){
            //     cout << pair.first << ":" << pair.second << " " ;
            // }
            // cout << endl;

            int shootingX=0, shootingNum=INT_MIN;
            for(auto& pair : counter){
                if(pair.second > shootingNum){
                    shootingNum = pair.second;
                    shootingX = pair.first;
                }
            }

            // cout << "shootingX= " << shootingX << endl;

            for(int i=0; i<points.size(); ++i){
                points.erase(remove_if(points.begin(), points.end(), [shootingX](vector<int> p){
                    return p[0]<=shootingX && p[1]>=shootingX;
                }), points.end());
            }
            counter = refreshX(points);
        }
        return ans;
    }
};

正确思路的贪心

以上想法很好, 也可以通过大部分案例, 就是每次射爆最多的气球;
但是对于测试用例[[9,17],[4,12],[4,8],[4,8],[7,13],[3,4],[7,12],[9,15]]而言
你先从x=8/9/10处射箭(最开始时这三点重叠气球最多), 之后就需要再射2
但是如果第一箭先x=4处射, 那么之后只用射1

所以转变思路:
① 先用左区间为index, sort points
依次从第二个气球i开始遍历, 不断更新"重叠的一组气球";
如果气球ii-1没有重叠, 那么ans++;
否则就更新i的右边界为ii-1的最小右边结(which means是"这一组重叠气球的右边界")

class Solution{
public:
    int findMinArrowShots(vector<vector<int>>& points){
        if(points.empty())
            return 0;
        sort(points.begin(), points.end(), [](vector<int>& a, vector<int>&b){
            return a[0] < b[0];
        });
        int ans=1;
        for(int i=1; i<points.size(); ++i){
            if(points[i][0] > points[i-1][1]){
                ans ++;
            }else{
                points[i][1] = min(points[i][1], points[i-1][1]);
            }
        }
        return ans;
    }
};

总结

贪心真的防不胜防, 波云诡谲, 难以捉摸;
今天第三题本来以为自己已经找到正确的贪心思路了(每次都捡能打掉最多气球的点射箭), 然而并不是;
所以个人其实认为将这些乱七八糟的东西都归到"贪心算法"中进行分类, 某种程度上并不是很严谨合理.
做的过程中多看看题解, 学习参考为主吧, 别硬磕, 伤身劳心费神.

本文参考:
柠檬水找零
根据身高重建队列
用最少数量的箭引爆气球

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

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

相关文章

【DockerCE】Docker-CE 24.0.6正式版发布

官网下载地址&#xff08;For RHEL/CentOS 7.9&#xff09;&#xff1a; https://download.docker.com/linux/centos/7/x86_64/stable/Packages/ 相对于24.0.5版本&#xff0c;本次24.0.6版本更新的rpm包有 5 个&#xff0c;使用目录对比软件对比的结果如下&#xff1a; 在Lin…

Rabbitmq 常见问题处理

Rabbitmq queue NaN status code 如下图&#xff1a; 参考文章 ## https://groups.google.com/g/rabbitmq-users/c/4MlYbOXvy4E## https://groups.google.com/g/rabbitmq-users/c/SsXtN165_30### https://www.cnblogs.com/weschen/p/13321817.html### https://community.piv…

Ubuntu终端指令

目录 一、基本指令 1.命令行提示符 2.切换用户 3.修改密码 4.查看当前目录下的文件 5.修改文件权限---chmod 6.cd 切换路径 7.touch 8.cat 9.echo 10.mkdir 11. rm/rmdir 二、在线下载软件 1.更新软件源 2.更新软件列表 3.下载软件 三、离线安装软件 1. 软件安装…

ES-OAS-ERP-电子政务-企业信息化

ES-OAS-ERP-电子政务-企业信息化 专家系统ES办公自动化系统OAS企业资源规划ERP典型的信息系统架构模型 专家系统ES 模拟人类专家&#xff0c;解决结构化&#xff0c;半结构化问题 数据级&#xff0c;知识库级&#xff0c;控制级 专家系统的特点就是和人的区别 启发性知识&#…

citavi合并重复文献题录

文章目录 一、宏macro的使用方法二、合并重复题录的macro代码2.1 下载并加载macro代码2.2 显示重复题录并合并2.3 合并的规则2.4 其他 附&#xff1a;macro代码 一、宏macro的使用方法 参考官方文档 Using macros - Citavi 6 Manual Macro files have the .cs file extension…

Echarts 柱状图逐条加载动画

展示效果: 相关代码: let xAxisData = []; const data1=[]; const data2=[]; const year = [2000

dll修复精灵,dll修复工具下载方法分享,mfc140u.dll缺失损坏一键修复

今天&#xff0c;我将为大家分享一个关于mfc140u.dll的问题。首先&#xff0c;我想问一下在座的网友们&#xff0c;有多少人知道mfc140u.dll是什么&#xff1f;又有多少人知道它的作用以及如何解决这个问题呢&#xff1f;在接下来的演讲中&#xff0c;我将详细介绍mfc140u.dll的…

炫我科技成功为乐歌提供渲染私有云系统解决方案

炫我科技于2023年8月25日成功交付乐歌渲染私有云系统项目。 “乐歌”为乐歌人体工学科技股份有限公司 品牌名。致力于以机、电、软一体化的线性驱动为核心&#xff0c;打造创新家居生活与办公方式&#xff0c;为全球用户提供健康、舒适、安全、高效的整体智能解决方案。主营产…

黑客利用 MinIO 存储系统漏洞危害服务器

据观察&#xff0c;未知威胁行为者利用 MinIO 高性能对象存储系统中的高严重性安全漏洞进行武器化&#xff0c;以在受影响的服务器上实现未经授权的代码执行。 国际知名白帽黑客、东方联盟创始人郭盛华表示&#xff0c;此次入侵利用了公开可用的漏洞利用链对 MinIO 实例进行后…

网络技术三:局域网基本原理

局域网基本原理 使用的协议及线缆 物理层 双绞线 同轴电缆 光纤 无线电 数据链路层 以太网 唯一事实标准 令牌环 淘汰 FDDI 光纤分布式接口 网络层 IP 唯一的事实标准 IPX 淘汰 Apple talk 淘汰 局域网设备 集线器 内部为总线型拓扑 任意时间只能由一台主机占用总线&a…

upload-labs 16/17关

16 将gif文件和包含一句话木马的php文件放在同一目录下&#xff0c;用cmd的copy命令将php文件整合进文件中。 可以看到最后一行包含了注入代码 将b1文件上传到服务器后&#xff0c;发现并未能正常执行代码&#xff0c;将上传后的文件下载到本地&#xff0c;打开后发现最后的代…

Unity的GPUSkinning进一步介绍

大家好&#xff0c;我是阿赵。   在几年前&#xff0c;我曾经写过一篇介绍GPUSkinning的文章&#xff0c;这么多年之后&#xff0c;还是看到不停有朋友在翻看这篇旧文章。今天上去GitHub看了一下&#xff0c;GPUSkinning这个开源的插件已经很久没有更新过了&#xff0c;还是停…

手写Spring:第11章-容器事件和事件监听器

文章目录 一、目标&#xff1a;容器事件和事件监听器二、设计&#xff1a;容器事件和事件监听器三、实现&#xff1a;容器事件和事件监听器3.1 工程结构3.2 容器事件和事件监听器类图3.3 定义和实现事件3.3.1 定义事件抽象类3.3.2 定义应用上下文事件实现类3.3.3 上下文刷新事件…

日常开发小点汇总(1)

1.浮动元素 生成一个浮动流&#xff0c;块级元素看不到&#xff0c;文本、行内属性元素及行内元素可见 <div class"demo1"></div><span>123</span><div class"demo2"></div>.demo1 {width: 100px;height: 100px;backg…

fastadmin 框架中图片点击放大

fastadmin的原生图片预览,重新打开一个窗口太麻烦&#xff0c;使用layui做一个弹窗式的图片预览 效果如下&#xff1a; 点击放大&#xff1a; 第一步&#xff1a;在backend-init.js文件中添加如下代码&#xff1a; $(body).on(click, [data-tips-image], function () {var…

网络技术九:生成树协议

生成树协议 二层环路带来的问题 广播风暴 MAC地址表震荡 生成树的定义 STP&#xff0c;用来解决二层环路问题 STP相关概念 BPDU 四个参数放在BPDU里面决定四个“角色” 定义 桥协议数据单元&#xff0c;用于传递STP协议相关报文 分类 配置BPDU 用来传递STP的配置信…

Unity ProBuilder(自己创建斜面、拐角)

目录 基础操作 下载 打开面板 新增对象 材质保存 1.斜面实例 2.拐角实例 3.切割实例 4.单独面赋值 基础操作 下载 打开面板 新增对象 选中想创建的块体后&#xff0c;在编辑器见面拉出块体 材质保存 打开材质编辑器后&#xff0c;将材质赋值&#xff0c;之后&am…

三种方式查看 JVM 垃圾收集器

一、引言 不同版本的 JVM 默认使用的垃圾收集器是不同的&#xff0c;目前的新生代和老年代的垃圾收集器如下图所示&#xff0c;新生代和老年代之间的连线表示这些垃圾收集器可以进行搭配使用 垃圾收集器的名字和 JVM 里面的参数对照表如下&#xff0c;即在 JVM 里面并不是存储的…

人工智能和大数据:跨境电商如何实现定制化营销?

在跨境电商竞争激烈的市场中&#xff0c;如何精准地满足消费者的需求并提供个性化的购物体验成为了商家们面临的重要挑战。幸运的是&#xff0c;人工智能和大数据技术的崛起为跨境电商带来了新的机遇&#xff0c;使得定制化营销成为可能。本文将探讨人工智能和大数据在跨境电商…

C# wpf 实现截屏框热键截屏功能

wpf截屏系列 第一章 使用GDI实现截屏 第二章 使用DockPanel制作截屏框 第三章 实现截屏框热键截屏&#xff08;本章&#xff09; 第四章 实现截屏框实时截屏 第五章 使用ffmpeg命令行实现录屏 文章目录 wpf截屏系列前言一、实现步骤1、响应热键2、截屏显示&#xff08;1&#…