代码随想录第十六天|贪心算法(2)
目录
LeetCode 134. 加油站
LeetCode 135. 分发糖果
LeetCode 860. 柠檬水找零
LeetCode 406. 根据身高重建队列
LeetCode 452. 用最少数量的箭引爆气球
LeetCode 435. 无重叠区间
LeetCode 763. 划分字母区间
LeetCode 56. 合并区间
LeetCode 738. 单调递增的数字
总结
歇逼了两天,再次开始
LeetCode 134. 加油站
题目链接:LeetCode 134. 加油站
思想:路过每个加油站的剩余量是gas[i] - cost[i]。那么从0加到第i个加油站的剩余量,如果小于零,说明[0,i]区间内都不能作为起始位置,因为到i就会断油。之后再从i+1位置算起,从0开始计算新一轮的油剩余量。
代码如下:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int index = 0;int sum = 0;int result = 0;for (int i = 0; i < gas.size(); i++) {sum += gas[i] - cost[i];result += gas[i] - cost[i];if (sum < 0) {index = i + 1;sum = 0;}}if (result < 0) return -1;return index;}
时间复杂度:O(n),空间复杂度:O(1)。
LeetCode 135. 分发糖果
题目链接:LeetCode 135. 分发糖果
思想:因为除了开头和结尾的孩子,每个孩子都有相邻的两个方向左边和右边,不能同时考虑,所以本题应该要分开考虑,即先考虑孩子的右边,再考虑孩子的左边。先考虑孩子的右边,从前往后遍历,如果右孩子的评级高于当前孩子的话,右孩子分配到的糖果应当是当前孩子分配到的+1;再考虑左孩子,从后往前遍历,如果左孩子的评级高于当前孩子的话,左孩子分配到的糖果应当是左孩子原本分配到的糖果与当前孩子分配到的糖果+1取最大值。因为前面我们已经遍历且分配了一轮糖果了,不再是原本大家都是1糖果了,所以这里要取最大。
代码如下:
int candy(vector<int>& ratings) {vector<int> candyNums(ratings.size(), 1);for (int i = 0; i < ratings.size() - 1; i++) {if (ratings[i] < ratings[i + 1]) {candyNums[i + 1] = candyNums[i] + 1;}}for (int i = ratings.size() - 2; i >= 0; i--) {if (ratings[i] > ratings[i + 1]) {candyNums[i] = max(candyNums[i], candyNums[i + 1] + 1);}}int minCandy = 0;for (int i = 0; i < candyNums.size(); i++) minCandy += candyNums[i];return minCandy;}
时间复杂度:O(n),空间复杂度:O(1)。
LeetCode 860. 柠檬水找零
题目链接:LeetCode 860. 柠檬水找零
思想:本题其实十分简单,遇到5就收下;遇到10,就查看5是否有多余的,如果有就收下10,指出1张5,如果没有就return false;遇到20,优先支出1张10和1张5,因为收到的10只能用于20的补零,而5可以补10和20,灵活度更高,如果没有1张10和1张5的话,就支出3张5,如果没有3张5的话就return false。
代码如下:
bool lemonadeChange(vector<int>& bills) {int five = 0;int ten = 0;int twenty = 0;for (int i = 0; i < bills.size(); i++) {if (bills[i] == 5) five++;else if (bills[i] == 10) {if (five > 0) {five--;ten++;}else {return false;}}else {if (ten > 0 && five > 0) {five--;ten--;twenty++;} else if (five > 2) {five-=3;twenty++;} else {return false;}}}return true;}
时间复杂度:O(n),空间复杂度:O(1)。
LeetCode 406. 根据身高重建队列
题目链接:LeetCode 406. 根据身高重建队列
思想:因为本题是根据身高来重建队列,[h,k]分别是身高h和队列里前面有k个高于当前的人。所以可以按照身高h来先重新排列,从大到小,如果身高相同的话则k小的站前面,让高个子站前面。之后就遍历新排列的数组,按照k来插入到新数组,插入不影响前后顺序。
代码:
static bool cmp(const vector<int>& a, const vector<int>& b) {return a[0] == b[0] ? a[1] < b[1] : a[0] > b[0];}vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {sort(people.begin(), people.end(), cmp);vector<vector<int>> result;for (int i = 0; i < people.size(); i++) {int position = people[i][1];result.insert(result.begin() + position, people[i]);}return result;}
时间复杂度:O(nlogn),空间复杂度:O(n)。
LeetCode 452. 用最少数量的箭引爆气球
题目链接:LeetCode 452. 用最少数量的箭引爆气球
思想:因为所有气球位置在数组里面是随机排列的,所以现在我们可以先对数组进行一个排序,对气球的左边界排序,小的在前面,大的在后面。然后遍历数组里面的元素,如果当前气球的左边界大于上一个气球的右边界的话,就需要多一个箭头;反之就让当前气球的右边界等于上一个气球的右边界,也就是可以用同一个箭头处理这一类的气球。
代码如下:
static bool cmp(vector<int>& a, vector<int>& b) {return a[0] < b[0];} int findMinArrowShots(vector<vector<int>>& points) {if (points.size() == 0) return 0;sort(points.begin(), points.end(), cmp);int result = 1;for (int i = 1; i < points.size(); i++) {if (points[i][0] > points[i - 1][1]) {result++;} else {points[i][1] = min(points[i - 1][1], points[i][1]);}}return result;}
时间复杂度:O(nlogn),空间复杂度:O(1)。
LeetCode 435. 无重叠区间
题目链接:LeetCode 435. 无重叠区间
思想:首先本题也需要先重新排序输入数组,这里我选择的根据一个区间的左边界来进行排序,接下来就是找出重叠的区间,先标记一个区间的起始点,这里分为从前往后还是从后往前,这里我选择从后往前,这样做的原因是非常好进行对比。对比什么呢,如果这个标记点大于等于前一个区间的右边界的话,说明两个区间重叠了,就令标记点等于前一个区间的左边界,令重复数组标记+1。最后返回区间个数-重复数组的个数。
代码如下:
static bool cmp(vector<int>& a, vector<int>& b) {return a[0] < b[0];}int eraseOverlapIntervals(vector<vector<int>>& intervals) {if (intervals.size() == 0) return 0;sort(intervals.begin(), intervals.end(), cmp);int result = 1;int start = intervals[intervals.size() - 1][0];for (int i = intervals.size() - 1; i > 0; i--) {if (start >= intervals[i - 1][1]) {start = intervals[i - 1][0];result++;} else {continue;}}return intervals.size() - result;}
时间复杂度:O(nlogn),空间复杂度:O(1)。
LeetCode 763. 划分字母区间
题目链接:LeetCode 763. 划分字母区间
思想:要让同一个字母最多出现在一个片段中,首先就要记录一个字母最后出现的下标。然后遍历这个字符串,标记一个片段的左边界和右边界,左右边界最开始为0,右边界在遍历的过程中等于右边界和当前字母最后出现的下标取最大值,如果遇到当前遍历的下标和右边界相等之后,就往结果数组压入当前的长度,即right - left + 1,左边界就更新为i + 1。
代码如下:
vector<int> partitionLabels(string s) {int hash[27] = {0};for (int i = 0; i < s.size(); i++) {hash[s[i] - 'a'] = i;}int left = 0;int right = 0;vector<int> result;for (int i = 0; i < s.size(); i++) {right = max(right, hash[s[i] - 'a']);if (i == right) {result.push_back(right - left + 1);left = i + 1;}}return result;}
时间复杂度:O(n),空间复杂度:O(1)。
LeetCode 56. 合并区间
题目链接:LeetCode 56. 合并区间
思想:本题首先需要借用一个额外的数组来存储合并区间,如果只是在原来的数组上合并并更改区间的话,会导致遍历中遍历不完数组或者数组越界的情况。首先本题也需要对数组进行排序,我采用的是对左边界排序,然后往结果数组里面存放第一个区间,再遍历排序过后的区间数组,如果结果数组的最后一个区间的右边界大于或等于区间数组当前区间的左边界的话,说明两个区间重叠了,就进行合并,就是更改结果数组中的最后一个区间的右边界等于本身和区间数组当前区间的右边界取最大值;如果小于的话,就直接放入结果数组。
代码如下:
static bool cmp(vector<int>& a, vector<int>& b) {return a[0] < b[0];}vector<vector<int>> merge(vector<vector<int>>& intervals) {vector<vector<int>> result;if(intervals.size() == 0) return intervals;sort(intervals.begin(), intervals.end(), cmp);result.push_back(intervals[0]); for (int i = 1; i < intervals.size(); i++) {if (result.back()[1] >= intervals[i][0]) {result.back()[1] = max(result.back()[1], intervals[i][1]);} else {result.push_back(intervals[i]);}}return result;}
时间复杂度:O(nlogn),空间复杂度:O(n)。
LeetCode 738. 单调递增的数字
题目链接:LeetCode 738. 单调递增的数字
思想:本题有一个十分有趣的规律,就是如果要使一个数字成为一个单调递增的数字的话,如果它本身不是,则可以先找到它不满足单调递增的地方,例如123123123,就需要找到第二个1的地方,令其减小一位,将其后面满足单调递增的数字改为9,第三个123也是如此操作。
代码如下:
int monotoneIncreasingDigits(int n) {vector<int> count;if (n == 0) return 0;while (n) {count.push_back(n % 10);n = n / 10;}int flag = -1;for (int i = 0; i < count.size() - 1; i++) {if (count[i] < count[i + 1]) {count[i + 1]--;flag = i;}}int sum = 0;for (int i = flag; i >= 0; i--) {count[i] = 9;}for (int i = 0; i < count.size(); i++) {sum += count[i] * pow(10, i);}return sum;}
时间复杂度:O(n),空间复杂度:O(n)。
总结
贪心算法没学到什么,能自己做出来的屈指可数,不过学到了sort函数的新方法,可以根据自定义的函数来进行排序。
相关文章:
代码随想录第十六天|贪心算法(2)
目录 LeetCode 134. 加油站 LeetCode 135. 分发糖果 LeetCode 860. 柠檬水找零 LeetCode 406. 根据身高重建队列 LeetCode 452. 用最少数量的箭引爆气球 LeetCode 435. 无重叠区间 LeetCode 763. 划分字母区间 LeetCode 56. 合并区间 LeetCode 738. 单调递增的数字 总…...
花几千上万学习Java,真没必要!(二十二)
1、final关键字: 测试代码1: package finaltest.com;public class FinalBasicDemo {public static void main(String[] args) {// final修饰基本数据类型变量final int number 5;// 尝试修改number的值,这将导致编译错误// number 10; // …...
在RK3568上如何烧录MAC?
这里我们用RKDevInfoWriteTool 1.1.4版本 下载地址:https://pan.baidu.com/s/1Y5uNhkyn7D_CjdT98GrlWA?pwdhm30 提 取 码:hm30 烧录过程: 1. 解压RKDevInfoWriteTool_Setup_V1.4_210527.7z 进入解压目录,双击运行RKDevInfo…...
1.30、基于卷积神经网络的手写数字旋转角度预测(matlab)
1、卷积神经网络的手写数字旋转角度预测原理及流程 基于卷积神经网络的手写数字旋转角度预测是一个常见的计算机视觉问题。在这种情况下,我们可以通过构建一个卷积神经网络(Convolutional Neural Network,CNN)来实现该任务。以下…...
Windows如何使用Python的sphinx
在Windows上使用Python的Sphinx进行文档渲染和呈现,可以遵循以下步骤进行操作: 安装Python:首先,确保你的Windows系统上已经安装了Python。你可以从Python的官方网站下载并安装适合你系统(32位或64位&…...
C++ STL nth_element 用法
一:功能 将一个序列分为两组,前一组元素都小于*nth,后一组元素都大于*nth, 并且确保第 nth 个位置就是排序之后所处的位置。即该位置的元素是该序列中第nth小的数。 二:用法 #include <vector> #include <a…...
【PostgreSQL教程】PostgreSQL 选择数据库
博主介绍:✌全网粉丝20W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…...
C# —— HashTable
集合collections命名空间,专门进行一系列的数据存储和检索的类,主要包含了:堆栈、和队列、list、ArrayList、数组 HashTable 字典 storeList 排序列表等类 Array 数组 长度固定, 类型固定 通过索引值来进行访问 ArrayList动态数组,…...
LeetCode 第407场周赛个人题解
目录 100372. 使两个整数相等的位更改次数 原题链接 思路分析 AC代码 100335. 字符串元音游戏 原题链接 思路分析 AC代码 100360. 将 1 移动到末尾的最大操作次数 原题链接 思路分析 AC代码 100329. 使数组等于目标数组所需的最少操作次数 原题链接 思路分析 A…...
使用Django框架实现音频上传功能
数据库设计(models.py) class Music(models.Model):""" 音乐 """name models.CharField(verbose_name"音乐名字", max_length32)singer models.CharField(verbose_name"歌手", max_length32)# 本质…...
[路由器]IP-MAC的绑定与取消
背景:当公司的网络不想与外部人员进行共享,可以在路由器页面配置IP-MAC的绑定,让公司内部人员的手机和电脑的mac,才能接入到公司。第一步:在ARP防护中,启动IP-MAC绑定选项,必须启动仅允许IP-MAC…...
Idea配置远程开发
Idea配置远程开发 本篇博客介绍使用idea通过ssh连接ubuntu服务器进行开发 目录 Idea配置远程开发1.idae上点击file->Remote Development2.点击New Connection3.填写相关信息4.输入密码5.选择IDE版本和项目路径5.1 点击open an SSH terminal打开控制台5.2 依次执行命令 6.成…...
lua 实现 函数 判断两个时间戳是否在同一天
函数用于判断两个时间戳是否在同一天。下面是对代码的详细解释: ### 函数参数 - stampA 和 stampB:两个时间戳,用于比较。- resetInfo:一个可选参数,包含小时、分钟和秒数,用于调整时间戳。 ### 函数实现…...
工作纪实53-log4j日志打印文件隔离
在项目中,我有一堆业务日志需要打印,另一部分的日志,是没有格式的,需要被云平台离线解析并收集到kafka或者hdfs、hive等,需要将日志隔离打印到不同的文件 正常的log4j配置是下面这样的,配合Sl4j直接使用默认…...
7月21日,贪心练习
大家好呀,今天带来一些贪心算法的应用解题、 一,柠檬水找零 . - 力扣(LeetCode) 解析: 本题的贪心体现在对于20美元的处理上,我们总是优先把功能较少的10元作为找零,这样可以让5元用处更大 …...
FPGA DNA 获取 DNA_PORT
FPGA DNA DNA 是 FPGA 芯片的唯一标识, FPGA 都有一个独特的 ID ,也就是 Device DNA ,这个 ID 相当于我们的身份证,在 FPGA 芯片生产的时候就已经固定在芯片的 eFuse 寄存器中,具有不可修改的属性。在 xilinx 7series…...
使用 hutool工具实现导入导出功能。
hutool工具网址 Hutool参考文档 pom依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.20</version></dependency><dependency><groupId>org.apache.poi</gro…...
大语言模型-Transformer-Attention Is All You Need
一、背景信息: Transformer是一种由谷歌在2017年提出的深度学习模型。 主要用于自然语言处理(NLP)任务,特别是序列到序列(Sequence-to-Sequence)的学习问题,如机器翻译、文本生成等。Transfor…...
spring(二)
一、为对象类型属性赋值 方式一:(引用外部bean) 1.创建班级类Clazz package com.spring.beanpublic class Clazz {private Integer clazzId;private String clazzName;public Integer getClazzId() {return clazzId;}public void setClazzId(Integer clazzId) {th…...
MAC 数据恢复软件: STELLAR Data Recovery For MAC V. 12.1 更多增强功能
天津鸿萌科贸发展有限公司是 Stellar 系列软件的授权代理商。 STELLAR Data Recovery For MAC 该数据恢复软件可从任何存储驱动器、清空的回收站以及崩溃或无法启动的 Mac 设备中恢复丢失或删除的文件。 轻松恢复已删除的文档、照片、音频文件和视频。自定义扫描以帮助恢复特…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
