C++ 贪心算法——跳跃游戏、划分字母区间

在这里插入图片描述

   一:跳跃游戏

   55. 跳跃游戏

   题目描述:给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。

   示例 1:

输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1,然后从下标 13 步到达最后一个下标。

   示例 2:

输入:nums = [3,2,1,0,4]
输出:false
解释:无论你怎么跳,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 ,所以永远不可能到达最后一个下标。

   提示:

* 1 <= nums.length <= 10* 0 <= nums[i] <= 10

   解题思路:

   这道题最关键的地方就是不要去想在当前位置,我应该跳到哪里去,而是只需要记录当前能到达的最远位置,就可以了,遍历一遍给定的数组,若发现遍历到的当前位置i大于最远可达距离,则说明无法到达,直接返回false,若数组遍历完了,没有返回false,说明遍历到每一个i处时,均小于当时的最远距离,即均可达,返回true。

   参考程序:

class Solution {
public:bool canJump(vector<int>& nums) {int k = 0;for (int i = 0; i < nums.size(); i++) {if (i > k) return false;k = max(k, i + nums[i]);}return true;}
};

在这里插入图片描述

   二:跳跃游戏 II

   45. 跳跃游戏 II

   题目描述:给定一个长度为 n 的 0 索引整数数组 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

   提示:

* 1 <= nums.length <= 10* 0 <= nums[i] <= 1000
* 题目保证可以到达 nums[n-1]

   解题思路:

   这道题最关键的地方同样是不要去想在当前位置,我应该跳到哪里去。而且根据每次跳跃所能到达的最远距离,将给定数组划分为很多区间,遍历当前区间中所有值,得到的最远距离,作为下一个区间的右界限,划分的区间数-1即为所需的最少跳跃次数。这么说可能有点懵,下面举一个例子,大家就明白了

   例如,对于[2,3,1,1,4,2,1,1,3],起始的时候,只能从索引为0的2处起跳,

   则[2,3,1,1,4,2,1,1,3] 划分为 [2] [3,1,1,4,2,1,1,3]

   从索引为0的2处起跳,其最远可以到达的索引为2的1处,按最远可到达的区域,划分数组

   [2] [3,1,1,4,2,1,1,3] 划分为 [2] [3,1] [1,4,2,1,1,3]

   遍历新得到的区间[3,1],记录最远距离,若从3处起跳,最远可到达索引为4的4处,若从1处起跳,则只能到达4前面索引为3的1处,所以当前区间[3,1]起跳,最远可到达索引为4的4处,因此

   [2] [3,1] [1,4,2,1,1,3] 划分为 [2] [3,1] [1,4] [2,1,1,3]

   同理,遍历新得到的区间[1,4],记录最远距离,若从1处起跳,最远可到达索引为4的4处,若从4处起跳,则最远可以到达后面索引为8的3处,所以当前区间[3,1]起跳,最远可到达索引为8的3处,因此

   已经超过或恰好到达最后一个元素,不需要继续划分了,即

   起始位置: [2]

   第一次跳跃,新的可达区域 [3,1]

   第二次跳跃,新的可达区域 [1,4]

   第三次跳跃,新的可达区域 [2,1,1,3]

   上面过程中遍历当前区间,记录从当前区间起跳可到达的最远距离的过程对应下面程序中的

   maxPos = max(nums[i] + i, maxPos);

   上面每个区间的右界限,即对应下面程序中的end变量,当遍历完当前区间后,遍历当前区间时得到的最远可达距离maxPos,即为下一个区间的右界限,即end = maxPos;

   参考程序:

class Solution {
public:int jump(vector<int>& nums){int ans = 0,end = 0,maxPos = 0;for (int i = 0; i < nums.size() - 1; i++){maxPos = max(nums[i] + i, maxPos);if (i == end){ end = maxPos; ans++;}   }return ans;}};

在这里插入图片描述

   三、划分字母区间

   763. 划分字母区间

   题目描述:给你一个字符串 s。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s。返回一个表示每个字符片段长度的数组。

   示例1:

  • 输入:s = "ababcbacadefegdehijhklij"
  • 输出:[9,7,8]
  • 解释:
    划分结果为 "ababcbaca", "defegde", "hijhklij"
    每个字母最多出现在一个片段中。
    像 “ababcbacadefegde”, “hijhklij” 这样的划分是错误的,因为划分的片段数较少。

   示例2:

  • 输入:s = "eccbbdbec"
  • 输出:[10]

   注意:

  • 1 <= s.length <= 500
  • s 仅由小写英文字母组成

   解决思路一:

   ①、首先,遍历一遍给定的字符串s,记录每个字母出现的次数,存放在变量int zm[26]中。

   ②、然后,进行第二遍遍历,在每轮迭代中,将当前字符放入map中, map的键选取为字母映射编号(0~25),值选取为当前出现次数。并进行判断,若map中当前字符出现的次数与第一次遍历时存放在数组zm中的次数相等,说明该字符已经全部出现了,将其从map表中删除。若map表为空,则说明,遍历到当前位置处,前面出现的所有字符,后面均不再出现,可以在此处进行切割,将个数累计变量进行存储(也就是我们所要输出的长度),然后将累计量清零,继续进行下一轮迭代,直至第二遍遍历结束。

   上述思路的参考程序如下:

class Solution {
public:vector<int> partitionLabels(string s) {int zm[26]={0}; unordered_map<int,int> map; vector<int> ans; int iter=0;for(int i=0;i<s.size();i++){ zm[s[i]-'a']++;}  //第一遍遍历,统计各个字母出现次数for(int i=0;i<s.size();i++) //第二遍遍历,统计切割段数{ map[s[i]-'a']++; // 键选取为字母映射编号(0~25),值选取为当前出现次数auto it = map.begin();while (it != map.end()) {if (it->second == zm[it->first]) it = map.erase(it);     else break;}iter++;if(map.empty()) {ans.push_back(iter); iter=0;}  //当map为空时,说明当前已经出现过的元素,已经全部出现了}return ans;}
};

在这里插入图片描述

   上述方案的时间复杂度较低,属于时间最优的算法之一,但由于使用了额外的map表,空间复杂度比较高,下面介绍一种改进方案,不再需要使用额外的map表,从而降低空间复杂度。


   解决思路二:

   ①、首先,同样是遍历一遍给定的字符串s,所不同的是,记录的是每个字符最后出现的位置,存放在int hash[27]中。

   ②、然后,进行第二遍遍历,最远边界right初始化为0,左边界left初始化为0,在每轮迭代中,对最远边界进行更新,若当前字符i的最远边界大于right,则对right进行更新。在每轮迭代中,会进行判断,若当前字符i处于最远边界right处,则说明,到达了前面出现的所有字符的最远边界处,前面出现的所有字符,后面均不再出现,可以在此处进行切割。right-left+1,即为当前片段的长度,压入结果队列中。并将left更新为i + 1。继续进行下一轮迭代,直至第二遍遍历结束。

   上述思路的参考程序如下:

class Solution {
public:vector<int> partitionLabels(string S) {int hash[27] = {0}; // i为字符,hash[i]为字符出现的最后位置for (int i = 0; i < S.size(); i++) { // 统计每一个字符最后出现的位置hash[S[i] - 'a'] = i;}vector<int> result;int left = 0;int right = 0;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;}
}

在这里插入图片描述

   上述方案的时间复杂度同样较低,属于时间最优的算法之一,且无需使用额外的map表,空间复杂度也得到了有效降低。


在这里插入图片描述

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

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

相关文章

解决阿里云的端口添加安全组仍然无法扫描到

发现用线上的网站扫不到这个端口&#xff0c;这个端口关了&#xff0c;但是没有更详细信息了 我用nmap扫了一下我的这个端口&#xff0c;发现主机是活跃的&#xff0c;但是有防火墙&#xff0c;我们列出云服务器上面的这个防火墙list&#xff0c;发现确实没有5566端口 参考&a…

Mac环境下,简单反编译APK

一、下载jadx包 https://github.com/skylot/jadx/releases/tag/v1.4.7 下载里面的这个&#xff1a;下载后&#xff0c;找个干净的目录解压&#xff0c;我是放在Downloads下面 二、安装及启动 下载和解压 jadx&#xff1a; 下载 jadx-1.4.7.zip 压缩包。将其解压到你希望的目…

内网安全--隧道技术代理技术

注:本文仅做技术交流,请勿非法破坏... 目录 项目: 1-Ngrok 用法 2-Frp 用法 3-Nps 用法 4-Spp 用法 工具: windows下: Proxifier(推荐~) Sockscap ccproxy Linux下: Proxychains 用法 http://t.csdnimg.cn/88Ew7 隧道技术&#xff1a;解决不出网协议上线的问…

**《Linux/Unix系统编程手册》读书笔记24章**

D 24章 进程的创建 425 24.1 fork()、exit()、wait()以及execve()的简介 425 . 系统调用fork()允许父进程创建子进程 . 库函数exit(status)终止进程&#xff0c;将进程占用的所有资源归还内核&#xff0c;交其进行再次分配。库函数exit()位于系统调用_exit()之上。在调用fo…

“RabbitMQ入门指南:从入门到起飞,这一篇就够!打造高效消息通信系统的第一步“。

1.前言 RabbitMQ是一个开源的消息代理软件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff09;的标准&#xff0c;并用Erlang语言编写。作为消息代理&#xff0c;RabbitMQ接收、存储和转发消息&#xff0c;帮助应用程序之间实现异步通信。它提供了一个强大而灵活…

Qt开发技术:Q3D图表开发笔记(四):Q3DSurface三维曲面图颜色样式详解、Demo以及代码详解

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/139424086 各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究 红胖子网络科技博…

PawSQL优化 | 分页查询太慢?别忘了投影下推

​在进行数据库应用开发中&#xff0c;分页查询是一项非常常见而又至关重要的任务。但你是否曾因为需要获取总记录数的性能而感到头疼&#xff1f;现在&#xff0c;让PawSQL的投影下推优化来帮你轻松解决这一问题&#xff01;本文以TPCH的Q12为案例进行验证&#xff0c;经过Paw…

Redisson分布式锁原理解析

前言 首先Redis执行命令是单线程的&#xff0c;所以可以利用Redis实现分布式锁&#xff0c;而对于Redis单线程的问题&#xff0c;是其线程模型的问题&#xff0c;本篇重点是对目前流行的工具Redisson怎么去实现的分布式锁进行深入理解&#xff1b;开始之前&#xff0c;我们可以…

Vmess协议是什么意思? VLESS与VMess有什么区别?

VMess 是一个基于 TCP 的加密传输协议&#xff0c;所有数据使用 TCP 传输&#xff0c;是由 V2Ray 原创并使用于 V2Ray 的加密传输协议&#xff0c;它分为入站和出站两部分&#xff0c;其作用是帮助客户端跟服务器之间建立通信。在 V2Ray 上客户端与服务器的通信主要是通过 VMes…

ThinkPHP发邮件配置教程?群发功能安全吗?

ThinkPHP发邮件的注意事项&#xff1f;如何优化邮件发送的性能&#xff1f; 无论是用户注册、密码重置还是消息提醒&#xff0c;发送邮件都是一个常见的需求。AokSend将详细介绍如何在ThinkPHP框架中配置和发送邮件&#xff0c;帮助开发者轻松实现邮件功能。 ThinkPHP发邮件&…

43【PS 作图】颜色速途

1 通过PS让画面细节模糊&#xff0c;避免被过多的颜色干扰 2 分析画面的颜色 3 作图 参考网站&#xff1a; 色感不好要怎么提升呢&#xff1f;分享一下我是怎么练习色感的&#xff01;_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1h1421Z76p/?spm_id_from333.1007.…

【Python教程】3-控制流、循环结构与简单字符串操作

在整理自己的笔记的时候发现了当年学习python时候整理的笔记&#xff0c;稍微整理一下&#xff0c;分享出来&#xff0c;方便记录和查看吧。个人觉得如果想简单了解一名语言或者技术&#xff0c;最简单的方式就是通过菜鸟教程去学习一下。今后会从python开始重新更新&#xff0…

MySQL之查询性能优化(七)

查询性能优化 排序优化 无论如何排序都是一个成本很高的操作&#xff0c;所以从性能角度考虑&#xff0c;应尽可能避免排序或者尽可能避免对大量数据进行排序。前面已经提到了&#xff0c;当不能使用索引生成排序结果的时候&#xff0c;MySQL需要自己进行排序&#xff0c;如果…

人脸考勤项目实训

第一章 Python-----Anaconda安装 文章目录 第一章 Python-----Anaconda安装前言一、Anaconda是什么&#xff1f;二、Anaconda的前世今生二、Windows安装步骤1.官网下载2.安装步骤安装虚拟环境 总结 前言 工欲善其事必先利其器&#xff0c;项目第一步&#xff0c;安装我们的环境…

【Unity UGUI】Screen.safeArea获取异形屏数据失败

Screen.safeArea获取不到异形屏的尺寸位置等数据 检查AndroidManifest.xml文件是否有设置&#xff1a;android:theme"style/UnityThemeSelector"&#xff0c;没有加上即可 android:theme"style/UnityThemeSelector"

第1章Hello world 4/5:对比Rust/Java/C++创建和运行Hello world全过程:运行第一个程序

讲动人的故事,写懂人的代码 1.7 对比Rust/Java/C++创建和运行Hello world全过程 有了会听懂人类的讲话,还能做记录的编程助理艾极思,他们三人的讨论内容,都可以变成一份详细的会议纪要啦。 接下来,我们一起看看艾极思是如何记录下赵可菲创建和运行Java程序Hello world,…

简记:为Docker配置服务代理

简记 为Docker配置服务代理 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/art…

Leetcode3040. 相同分数的最大操作数目 II

Every day a Leetcode 题目来源&#xff1a;3040. 相同分数的最大操作数目 II 解法1&#xff1a;记忆化搜索 第一步可以做什么&#xff1f;做完后&#xff0c;剩下要解决的问题是什么&#xff1f; 删除前两个数&#xff0c;剩下 nums[2] 到 nums[n−1]&#xff0c;这是一个…

分享一个 .NET Core Console 项目中应用 NLog 写日志的详细例子

前言 日志在软件开发中扮演着非常重要的角色&#xff0c;通常我们用它来记录应用程序运行时发生的事件、错误信息、警告以及其他相关信息&#xff0c;帮助在调试和排查问题时更快速地定位和解决 Bug。 通过日志&#xff0c;我们可以做到&#xff1a; 故障排除和调试&#xff…

4.大模型微调技术LoRA

大模型低秩适配(LoRA)技术 现有PEFT 方法的局限与挑战 Adapter方法,通过增加模型深度而额外增加了模型推理延时。Prompt Tuning、Prefix Tuning、P-Tuning等方法中的提示较难训练,同时缩短了模型可用的序列长度。往往难以同时实现高效率和高质量,效果通常不及完全微调(f…