[贪心_7] 最优除法 | 跳跃游戏 II | 加油站

目录

1.最优除法

题解

2.跳跃游戏 II

题解

3.加油站

题解


利用 单调性,可以实现 区间跳跃

1.最优除法

链接: 553. 最优除法

给定一正整数数组 numsnums 中的相邻整数将进行浮点除法。

  • 例如,nums = [2,3,4],我们将求表达式的值 "2/3/4"

但是,你可以在任意位置添加任意数目的括号,来改变算数的优先级。你需要找出怎么添加括号,以便计算后的表达式的值为最大值。

以字符串格式返回具有最大值的对应表达式。

注意:你的表达式不应该包含多余的括号。

示例 1:

输入: [1000,100,10,2]
输出: "1000/(100/10/2)"
解释: 1000/(100/10/2) = 1000/((100/10)/2) = 200
但是,以下加粗的括号 "1000/((100/10)/2)" 是冗余的,
因为他们并不影响操作的优先级,所以你需要返回 "1000/(100/10/2)"。其他用例:
1000/(100/10)/2 = 50
1000/(100/(10/2)) = 50
1000/100/10/2 = 0.5
1000/100/(10/2) = 2

给定一正整数数组 nums,nums 中的相邻整数将进行浮点除法。

例如,nums = [2,3,4],我们将求表达式的值 “2/3/4”。
但是,你可以在任意位置添加任意数目的括号,来改变算数的优先级。

  • 你需要找出怎么添加括号,以便计算后的表达式的值为最大值。
  • 题意其实就是数组给一堆数,数中间其实都有除法的,此时让我们任意位置添加一些括号,使表达式的值为最大值,最后返回的是以字符串格式返回具有最大值的对应表达式。
  • 注意:你的表达式不应该包含多余的括号。

原本括号里面顺序是3/4/5,现在多添加一个括号还是(3/4)/5。

题解

举一个例子来提取我们的贪心策略

这个时候我们要明白一点,在这个表达式中添加括号最终都会转换为 x/y 的形式。

也就是从这些数中挑一些放在分子上,一些数放在分母上,


我们最终要的是 x/y 是最大的,一个分数要最大,要么就是分子变大,要么就是分子变小。

  • 接下来我们设计表达式就是尽可能让分子大,分母小。
  • 这就是我们的贪心方向。

还有一点无论在表达式哪里填上括号,a都是在分子上,b都是在分母上

  • 所以a和b这两个无法通过添加括号去改变的a/b。所以最终a一定在分子上,b一定在分母上。
  • 现在可供我们选择的就是c、d、e、f,为了使最终结果最大,我们就想无脑的把c、d、e、f和a一起放在分子上。

这里可以用贪心优化就是因为这个值乘起来是越来越大的

贪心策略:除了前两个数以外,其余的数全部放在分子即可

  • 如何实现贪心策略呢?
    这里我们用小学就学过的知识,负负得正。除除得正。因此我们仅需在b之前填一个(,f后填一个)
  • 括号里面得除法全都因为括号外面得除法变成除除得正

class Solution {
public:string optimalDivision(vector<int>& nums) {string str;if(nums.size()==1) return to_string(nums[0]);if(nums.size()==2){str+=to_string(nums[0]);str+='/';str+=to_string(nums[1]);return str;}for(int i=0;i<nums.size();i++){str+=to_string(nums[i]);str+='/';if(i==0) str+='(';if(i==nums.size()-1) {str.pop_back();str+=')';}}return str;}
};

2.跳跃游戏 II

链接: 45. 跳跃游戏 II

给定一个长度为 n0 索引整数数组 nums。初始位置为 nums[0]

每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i]
  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]

示例 1:

输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

示例 2:

输入: nums = [2,3,0,1,4]
输出: 2

给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。

  • 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。
  • 换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处。

这句话特别重要的地方就是 任意

  • 下面举个例子,刚开始在0号位置最大跳跃长度是3,可以跳到下标3的位置。
    你可以跳转到任意 nums[i + j] 处,这句话意思
  • eg. nums[i]里面存的3是最大跳跃长度,你可以选择跳3步、跳2步、跳1步。

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。

题解

  1. 贪心(X)

刚开始处于0好位置,这里有一个最大跳跃长度,那每次跳跃的时候就非常贪心的跳最长跳跃长度。但是这种贪心是错的。


2. 动态规划

这个模型无非就是从左往右的一个模型,其实就是动规里面非常常规的线性dp问题。

1.状态表示

  • dp[i] 表示:从 0 位置开始,到达 i 位置的时候最小跳跃次数

2.状态转移方程

根据最近一步划分情况:

  • 能够到 i 位置的前提是要满足 nums[j] + j >= i,说明能够从 j 位置到达 i 位置,那到达 j 位置的最小跳跃次数 在 加上 从 j 到 i 这一跳跃次,就是到达 i 位置最小跳跃次数,j的位置有很多
  • 因此外面要求dp[i]的最小值。

3.初始化

  • dp[0] = 0 初始就在0位置
  • 然后要取dp[i]的最小值,因此0位置之后可以初始化 INT_MAX

4.填表顺序

  • 从左往右

5.返回值

  • dp[i] 表示:从 0 位置开始,到达 i 位置的时候最小跳跃次数
  • 我们要的是到底n-1位置的最小跳跃次数,因此返回dp[n-1]
class Solution {
public:int jump(vector<int>& nums) {int n=nums.size();if(n==1) return 0;vector<int> dp(n,0x3f3f3f3f);dp[0]=0;for(int i=1;i<n;i++){for(int j=0;j<=i-1;j++){if(j+nums[j]>=i)dp[i]=min(dp[i],dp[j]+1);//交给 计算机//j-->i 次数要+1}}return dp[n-1];}
};

虽然可以通过,但是实际复杂度是O(N^2)

1. 类似于层序遍历的过程

刚开始在2这个位置,此时起跳可以跳到3和1的位置。

  • 2这里可以表示第1次起跳的位置,3和1表示第2次起跳的位置。
  • 通过第2次起跳的位置,我们可以得到第3从起跳的位置,然后把重叠的删除,这里其实也有一点小贪心,如果能从第2次的1起跳,那为什么还要从第3次重叠的1起跳呢?
  • 跳跃次数更多了。所以只有1和4是第三次起跳的位置。
  • 同理从第3次起跳位置,我们可以得到第4次起跳位置,

  • 你会发现这里类似于层序遍历,每次都能知道起跳的左端点和右端点,然后遍历这一层的时候,又能找到下一层的左端点和右端点。

只要发现更新出来下一次起跳位置能够覆盖到n-1位置的时候就停止,因为次数已经可以跳到最后一个位置了

如何实现呢?

  • 我们仅需搞两个指针,left指向当前起跳的左端点,right指向当前起跳的右端点
  • 把这个区间遍历一遍就可以找到下一个起跳区间
  • 其中找左端点很好找就是right + 1,找右端点就是在遍历的过程中,拿着nums[i] + i 找到其中的最大值就是右端点。

在这个遍历过程中,我们仅需遍历一次就行了,所以时间复杂度是O(N)

class Solution {
public:int jump(vector<int>& nums) {int ret=0,n=nums.size();int left=0,right=0;while(left<=right){if(right>=n-1) return ret;int tmp=right;for(int i=left;i<=tmp;i++){right=max(right,nums[i]+i);}left=tmp+1;ret++;}return -1;}
};

不要忘了,还要处理跳不到的情况

  • while(left<=right)
  • return -1;

3.加油站

链接: 134. 加油站

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gascost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

示例 1:

输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

选择某个加油站为出发点,环绕一周看是否能回到出发点。

如果可以就返回对应的下标,不能就返回-1。

  • 初始时油箱是空的,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i],油箱容量是无限的。
  • 假设从3位置出发,刚开始油箱为空,此时可以补充1升汽油,但是需要3升汽油才能到下一个位置。所以这个位置不可以,同理4和5都不可以。
  • 可以从1位置出发 ,从这里可以补充4升汽油,仅需消耗1升就可以到下一个位置,到下一个位置还剩下3升
  • 到2的位置,补充5升,现在共有8升,消耗2升,到下一个位置还有6升


然后补充1升,消耗3升,到下一个位置还剩4,在补充2升,消耗4升,到下一个位置还剩2升,在补充3升,消耗5升,到出发点正好剩下0,可以到达,返回3。

题解

解法一:暴力解法 -> 枚举

首先可以想到一个优化,仅需考虑g和c的差就可以了,比如第一个位置会加1升油,消耗3升油,它们的差就是从这个加油站获得的净收益。

如果从负开始走绝对是走不到下一个位置的,所以肯定会选择净收益为正的作为出发点。

我们这道题其实特别像是一道模拟的题,任意枚举一个位置看看从这个位置能不能绕一圈会回来就可以。

如果不能就去枚举下一个位置。

所以我们的暴力策略就很简单:

  1. (预处理) 计算出 每一步的 diff
  2. 依次枚举所有的起点
  3. 从起点开始,模拟一遍加油的流程即可

虽然策略很简单,但是要注意这里是有环的,所以写代码的时候要考虑如何从最后一个位置回到0位置。

  • diff [-2, -2, -2, 3, 3]

我们的贪心就是根据暴力优化来的,所以先搞定暴力的代码。然后优化的时候仅需加一句代码,就能将时间复杂度从O(N^2)变成O(N)

如何实现暴力的代码?

  • 这里我们主要考虑就是如何从最后一个位置回到第一个位置,其实这里两层for循环就可以搞定
  • 我们创建一个变量step,用这个变量表示从 i 往后走了多少步,step变化是从 0 ~ n - 1。
  • 然后 (i + step)% n (数组大小) 就可以从最后一个位置回到第一个位置。
class Solution {
public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int n=gas.size();vector<int> diff(n);for(int i=0;i<n;i++){diff[i]=gas[i]-cost[i];}for(int i=0;i<n;i++){bool check=false;if(diff[i]>=0){check=true;int sum=diff[i];for(int step=1;step<n;step++){int curr=(i+step)%n;sum+=diff[curr];if(sum<0){check=false;break;}}}if(check) return i;}return -1;}
};

解法二:优化 -> 找规律(贪心)

diff表示g-c的差,我们的暴力解法是依次固定一个位置为起点,从这个起点开始模拟加油流程,其实就是把净收益加一下。

  • 如果发现从a加到f小于0了,说明从f这个位置开始就不能往后走了,所以从a为起来最多能到f这个位置。这里有一个等式。
    我们的暴力是枚举下一个起点然后在走。然后我们这里也有个不等式,
  • 我们要想从a走到b,一定是a>=0的,从a加到f < 0,现在第二个不等式又少了a,那更是< 0
  • 同理从c为起点也是越不过f的,a + b >= 0才能到c,等式少了a+b,那更小于0
    所以说发现有一个起点点都跑不到某个位置,那中间的都不用在考虑了,不用在枚举了。直接让 i 指针更新到 五角星 后面的一个位置,也就是 i = i + step 

我们最差会遍历数组两遍,假设还是以a为起点,发现到h走不到了,下一个位置就是i,最差我们绕回去在遍历一遍再走到h位置,相当于遍历了数组两遍

  • 然后接下来更新 i 的时候 是 i + step + 1 此时就已经越界了。
  • 所以最差遍历数组两遍,时间复杂度O(N)
class Solution {
public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int n=gas.size();vector<int> diff(n);for(int i=0;i<n;i++){diff[i]=gas[i]-cost[i];}for(int i=0;i<n;i++){int step=0;int sum=0;for(;step<n;++step){int curr=(i+step)%n;sum+=diff[curr];if(sum<0){break;}}if(sum>=0) return i;i+=step;}return -1;}
};

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

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

相关文章

“Daz to Unreal”将 G8 角色(包括表情)从 daz3d 导入到 UE5。在 UE5 中,我发现使用某个表情并与闭眼混合后,上眼睑出现了问题

1) Bake & Export Corrective Morphs from Daz before you go into UE5 1) 在进入 UE5 之前&#xff0c;从 Daz 烘焙并导出修正型变形 In Daz Studio 在 Daz Studio 中 Load your G8 head, dial in the exact mix (e.g. Smile 1.0 Eyes Closed 1.0). 加载你的 G8 头部&am…

【机器学习速记】面试重点/期末考试

自用,有错误欢迎评论区指出 目录 一、机器学习基础概念 二、机器学习类型分类 三、经典算法与原理 1. 线性模型 2. 决策树 3. SVM(支持向量机) 4. K近邻(KNN) 5. 贝叶斯分类 6. 集成学习 四、模型评价指标 五、模型泛化能力与调参 六、特征工程与数据预处理 七、维…

Redis 原子操作

文章目录 前言✅ 一、什么是「原子操作」&#xff1f;&#x1f50d; 二、怎么判断一个操作是否原子&#xff1f;&#x1f9ea; 三、项目中的原子 vs 非原子案例&#xff08;秒杀系统&#xff09;✅ 原子性&#xff08;OK&#xff09;❌ 非原子性&#xff08;高风险&#xff09;…

中建海龙MiC模块化建筑赋能“好房子”新范式

中国建筑国际集团旗下中建海龙科技有限公司&#xff08;以下简称“中建海龙”&#xff09;以科技创新为引擎&#xff0c;持续推动建筑行业向工业化、数字化、绿色化转型升级。近期&#xff0c;其自主研发的模块化集成建筑&#xff08;MiC&#xff09;技术成功入选中国建筑首批产…

DDL自联表

自联表 create table t_menu (id int AUTO_INCREMENT,name varchar(20),image varchar(20),url varchar(20),pid varchar(20),constraint pk_id primary key(id),constraint fk_id foreign key(pid) references t_menu(id) );

【版本控制】SVN + TortoiseSVN版本管理实用教程(附安装+开发常用操作)

摘要&#xff1a; 本文将带你从零开始掌握 SVN 版本控制系统&#xff0c;结合 TortoiseSVN 图形客户端工具&#xff0c;深入学习包括安装、检出、提交、更新、回滚、冲突解决等常用开发操作&#xff0c;快速上手团队协作&#xff01; &#x1f9e9; 什么是 SVN&#xff1f; SV…

C语言实现对哈希表的操作:创建哈希表与扩容哈希表

一. 简介 前面文章简单了解了哈希表 这种数据结构&#xff0c;文章如下&#xff1a; 什么是哈希表-CSDN博客 本文来学习一下哈希表&#xff0c;具体学习一下C语言实现对哈希表的简单实现。 二. C语言实现对哈希表的操作 1. 哈希表 哈希表&#xff08;Hash Table&#xff…

UML 活动图详解:以机票预订系统用户注册为例

目录 一、UML 活动图的基本元素 二、题目原型 三、机票预订系统用户注册的活动图分析 四、活动图绘画 五、总结 在软件开发过程中&#xff0c;UML&#xff08;统一建模语言&#xff09;活动图是一种非常重要的工具&#xff0c;它能够帮助我们清晰地理解系统的业务流程和工…

FX10(CYUSB4014)USB3.2(10Gbps)开发笔记分享(1):硬件设计与开发环境搭建

作者&#xff1a;Hello&#xff0c;Panda 大家早上好&#xff0c;中午好&#xff0c;下午好&#xff0c;晚上好&#xff0c;熊猫君又来了。这次计划做一个连载&#xff0c;大概6期左右&#xff0c;主要介绍英飞凌最新的FX5/10/20的器件应用。目前&#xff0c;熊猫君手上调试的…

前端项目部署

一、本地服务器部署&#xff1a; 解决页面刷新404问题&#xff1a; 1、使用 hash 模式 2、当路径不匹配的时候&#xff0c;直接访问 index.html 3、使用插件&#xff1a;connect-history-api-fallback https://www.npmjs.com/package/connect-history-api-fallback npm ins…

观测云数据在Grafana展示的最佳实践

背景 在当今的数据驱动世界中&#xff0c;组织越来越依赖于实时数据来做出决策。数据可视化是理解和分析这些数据的关键工具&#xff0c;它帮助用户将复杂的数据集转换成直观的图表和仪表板&#xff0c;从而更容易识别趋势、模式和异常。Grafana&#xff0c;作为一个功能强大的…

架构师面试(三十六):广播消息

题目 在像 IM、短视频、游戏等实时在线类的业务系统中&#xff0c;一般会有【广播消息】业务&#xff0c;这类业务具有瞬时高流量的特点。 在对【广播消息】业务实现时通常需要同时写 “系统消息库” 和更新用户的 “联系人库” 的操作&#xff0c;用户的联系人表中会有未读数…

大模型微调 - transformer架构

什么是Transformer Transformer 架构是由 Vaswani 等人在 2017 年提出的一种深度学习模型架构&#xff0c;首次发表于论文《Attention is All You Need》中 Transformer 的结构 Transformer 编码器&#xff08;Encoder&#xff09; 解码器&#xff08;Decoder&#xff09; …

基于华为云 ModelArts 的在线服务应用开发(Requests 模块)

基于华为云 ModelArts 的在线服务应用开发&#xff08;Requests 模块&#xff09; 一、本节目标 了解并掌握 Requests 模块的特点与用法学会通过 PythonRequests 访问华为云 ModelArts 在线推理服务熟悉 JSON 模块在 Python 中的数据序列化与反序列化掌握 Python 文件 I/O 的基…

python pymysql如何保证数据库更新成功

python pymysql如何保证数据库更新成功 在使用Python的PyMySQL库与MySQL数据库交互时,确保数据库更新操作成功执行,可以通过以下几种方式: 使用execute()和commit() 当执行一个更新(UPDATE)、插入(INSERT)或删除(DELETE)操作时,你需要调用execute()方法来执行SQL语句…

【数据可视化-30】Netflix电影和电视节目数据集可视化分析

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

【深度强化学习 DRL 快速实践】逆向强化学习算法 (IRL)

Inverse Reinforcement Learning (IRL) 详解 什么是 Inverse Reinforcement Learning&#xff1f; 在传统的强化学习 (Reinforcement Learning, RL) 中&#xff0c;奖励函数是已知的&#xff0c;智能体的任务是学习一个策略来最大化奖励 而在逆向强化学习 (Inverse Reinforc…

入侵检测系统(IDS)与入侵防御系统(IPS):功能对比与部署实践

入侵检测系统&#xff08;IDS&#xff09;与入侵防御系统&#xff08;IPS&#xff09;&#xff1a;功能对比与部署实践 在网络安全防御体系中&#xff0c;入侵检测系统&#xff08;Intrusion Detection System, IDS&#xff09;与入侵防御系统&#xff08;Intrusion Preventio…

P12167 [蓝桥杯 2025 省 C/Python A] 倒水

P12167 [蓝桥杯 2025 省 C/Python A] 倒水 题目描述 小蓝有 n n n 个装了水的瓶子&#xff0c;从左到右摆放&#xff0c;第 i i i 个瓶子里装有 a i a_i ai​ 单位的水。为了美观&#xff0c;小蓝将水循环染成了 k k k 种颜色&#xff0c;也就是说&#xff0c;第 i i i …

短视频矩阵系统可视化剪辑功能开发,支持OEM

在短视频营销与内容创作竞争日益激烈的当下&#xff0c;矩阵系统中的可视化剪辑功能成为提升内容产出效率与质量的关键模块。它以直观的操作界面和强大的编辑能力&#xff0c;帮助创作者快速将创意转化为优质视频。本文将结合实际开发经验&#xff0c;从需求分析、技术选型到核…