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

文章目录

  • 前置知识
  • 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.rhkb.cn/news/127558.html

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

相关文章

OpenCV之形态学操作

形态学操作包含以下操作&#xff1a; 腐蚀 (Erosion)膨胀 (Dilation)开运算 (Opening)闭运算 (Closing)形态梯度 (Morphological Gradient)顶帽 (Top Hat)黑帽(Black Hat) 其中腐蚀和膨胀操作是最基本的操作&#xff0c;其他操作由这两个操作变换而来。 腐蚀 用一个结构元素…

YOLO目标检测——密集人群人头数据集+已标注yolo格式标签下载分享

实际项目应用&#xff1a;城市安防、交通管理、社会研究、商业应用、等多个领域数据集说明&#xff1a;YOLO密集人群人头目标检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;图片格式为jpg&#xff0c;共4300张图片。标注说明&#xff1a…

vue3详解

认识Vue3 1. Vue2 选项式 API vs Vue3 组合式API <script> export default {data(){return {count:0}},methods:{addCount(){this.count}} } </script> <script setup> import { ref } from vue const count ref(0) const addCount ()> count.value …

区块链技术与应用 - 学习笔记2【密码学基础】

大家好&#xff0c;我是比特桃。本系列笔记只专注于探讨研究区块链技术原理&#xff0c;不做其他违反相关规定的讨论。 区块链技术已被纳入国家十四五规划&#xff0c;在“加快数字发展 建设数字中国”篇章中&#xff0c;区块链被列为“十四五”七大数字经济重点产业之一&#…

kafka-- 安装kafka manager及简单使用

一 、安装kafka manager 管控台&#xff1a; # 安装kafka manager 管控台&#xff1a; ## 上传 cd /usr/local/software ## 解压 unzip kafka-manager-2.0.0.2.zip -d /usr/local/ cd /usr/local/kafka-manager-2.0.0.2/conf vim /usr/local/kafka-manager-2.0.0.2/conf/appl…

解决虚拟机克隆后IP和命名冲突问题

目录 解决IP冲突问题 解决命名冲突 解决IP冲突问题 克隆后的虚拟机和硬件地址和ip和我们原虚拟机的相同&#xff0c;我们需要重新生成硬件地址和定义ip&#xff0c;步骤如下&#xff1a; &#xff08;1&#xff09;进入 /etc/sysconfig/network-scripts/ifcfg-ens33 配置文件…

PaddleOCR学习笔记3-通用识别服务

今天优化了下之前的初步识别服务的python代码和html代码。 采用flask paddleocr bootstrap快速搭建OCR识别服务。 代码结构如下&#xff1a; 模板页面代码文件如下&#xff1a; upload.html : <!DOCTYPE html> <html> <meta charset"utf-8"> …

在UE4虚幻引擎中加入导航网格体边界体积后丧尸不能移动和发现玩家

UE4系列文章目录 文章目录 UE4系列文章目录前言一、用到的知识点二、问题原因 前言 最近使用ue4做第一人称视角射击游戏发现问题&#xff0c;加入导航网格体边界体积后丧尸不能移动和发现玩家。下图是出现的问题图片 一、用到的知识点 1.行为树&#xff1a;控制并显示AI的决…

基于Zookeeper搭建Kafka高可用集群(实践可用)

目录 一、Zookeeper集群搭建 1.1 下载 & 解压 1.2 修改配置 1.3 标识节点 1.4 启动集群 1.5 集群验证 二、Kafka集群搭建 2.1 下载解压 2.2 拷贝配置文件 2.3 修改配置 2.4 启动集群 2.5 创建测试主题 2.6 写入数据测试 一、Zookeeper集群搭建 为保证集群高可…

Python实操:内存管理与优化策略

在 Python 开发过程中&#xff0c;合理有效地管理和优化内存使用是提高程序性能和效率的关键。本文将深入探讨 Python 中的内存管理机制&#xff0c;并分享一些实用的优化策略和具体操作步骤&#xff0c;帮助您更好地利用资源、减少内存占用并提升代码执行速度。 一、了解 Pyth…

66.C++多态与虚函数

目录 1.什么是多态 2.多态的分类 3.对象转型 3.1 向上转型&#xff1a; 3.2 向下转型&#xff1a; 4.虚函数 1.什么是多态 生活中的多态&#xff0c;是指的客观的事物在人脑中的主观体现。例如&#xff0c;在路上看到⼀只哈士奇&#xff0c;你可以看做是哈士奇&#xf…

Scrapy的基本介绍、安装及工作流程

一.Scrapy介绍 Scrapy是什么&#xff1f; Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架(异步爬虫框架) 通常我们可以很简单的通过 Scrapy 框架实现一个爬虫&#xff0c;抓取指定网站的内容或图片。 Scrapy使用了Twisted异步网络框架&…

HTML的有序列表、无序列表、自定义列表

目录 背景: 过程: 无序列表: 简介: 代码展示: 效果展示:​ 无序列表: 简介: 效果展示:​ 自定义列表: 简介&#xff1a; 效果展示: 总结&#xff1a; 背景: 1.有序列表&#xff08;Ordered List&#xff09;&#xff1a; 有序列表是最早的列表类型之一&#xff…

Spring Web Flow远程代码执行漏洞复现(CVE-2017-4971)

一、搭建环境 cd vulhub/spring/CVE-2017-4971 docker-compose up -d 影响版本:Spring Web Flow 2.4.0 ~ 2.4.4 触发条件: 1.MvcViewFactoryCreator对象的useSpringBeanBinding参数需要设置为false&#xff08;默认值&#xff09; 2. flow view对象中设置BinderConfiguration…

Yolov5如何训练自定义的数据集,以及使用GPU训练,涵盖报错解决

本文主要讲述了Yolov5如何训练自定义的数据集&#xff0c;以及使用GPU训练&#xff0c;涵盖报错解决&#xff0c;案例是检测图片中是否有救生圈。 最后的效果图大致如下&#xff1a; 效果图1效果图2 前言 系列文章 1、详细讲述Yolov5从下载、配置及如何使用GPU运行 2、…

数据结构大作业 成绩分析c语言程序设计

界面加载 界面展示 成绩输入 求平均成绩 升序排列 降序排列 名字排序 按名字搜索 按ID搜索 每门课成绩分析 成绩单展示 -

Mac 手动安装 sshpass

1. 下载安装包 https://sourceforge.net/projects/sshpass/ 解压并进入到安装包目录 tar -zxvf sshpass-xx.xx.tar.gz cd sshpass-xx.xx2. 检验环境&#xff0c;编译源码安装 ./configuremake&&make install3. 检测安装是否成功 ▶ sshpass Usage: sshpass [-f|-…

2023/9/8 -- C++/QT

作业 1> 自行封装一个栈的类&#xff0c;包含私有成员属性&#xff1a;栈的数组、记录栈顶的变量 成员函数完成&#xff1a;构造函数、析构函数、拷贝构造函数、入栈、出栈、清空栈、判空、判满、获取栈顶元素、求栈的大小 02stack.h: #ifndef __02STACK_H__ #define __…

网络协议从入门到底层原理学习(三)—— 路由

网络协议从入门到底层原理学习&#xff08;三&#xff09;—— 路由 1、简介 路由&#xff08;routing&#xff09;是指分组从源到目的地时&#xff0c;决定端到端路径的网络范围的进程 在不同网段之间转发数据&#xff0c;需要有路由器的支持 默认情况下&#xff0c;路由器…

linux并发服务器 —— 项目实战(九)

阻塞/非阻塞、同步/异步 数据就绪 - 根据系统IO操作的就绪状态 阻塞 - 调用IO方法的线程进入阻塞状态&#xff08;挂起&#xff09; 非阻塞 - 不会改变线程的状态&#xff0c;通过返回值判断 数据读写 - 根据应用程序和内核的交互方式 同步 - 数据的读写需要应用层去读写 …