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.mzph.cn/news/851017.shtml

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

相关文章

《大道平渊》· 拾壹 —— 商业一定是个故事:讲好故事,员工奋发,顾客买单。

《大道平渊》 拾壹 "大家都在喝&#xff0c;你喝不喝&#xff1f;" 商业一定是个故事&#xff0c;人民群众需要故事。 比如可口可乐的各种故事。 可口可乐公司也只是被营销大师们&#xff0c; 作为一种故事载体&#xff0c;发挥他们的本领。 营销大师们开发故事…

基于51单片机俄罗斯方块小游戏

基于51单片机俄罗斯方块游戏 &#xff08;仿真&#xff0b;程序&#xff09; 功能介绍 具体功能&#xff1a; 1.用LCD12864显示游戏界面&#xff1b; 2.用四个按键控制游戏&#xff08;左、右移、下移、翻转&#xff09;&#xff1b; 3.游戏规则和平时玩的俄罗斯方块一样&a…

点估计参数估计

点估计&#xff08;Point Estimation&#xff09;是一种统计推断的方法&#xff0c;用于通过样本统计量来估计总体参数。在概率论和数理统计中&#xff0c;点估计是将总体的未知参数估计为某个确定的值或在某个确定的点上&#xff0c;因此也被称为定值估计。 定义&#xff1a; …

ESP32连接xbox手柄

本文简单介绍一下如何使用ESP32连接xbox的蓝牙手柄&#xff0c;使之变成一个相对通用的遥控器。 硬件平台 XBOX ONE S手柄蓝牙版 EPS32-DOWN-V3&#xff0c;需要注意Xbox One S手柄使用经典蓝牙&#xff0c;ESP32有较多型号仅支持BLE&#xff0c;需要选一个支持经典蓝牙BLE的…

AXI Quad SPI IP核中命令的使用

1 双通道SPI和混合内存模式下支持的常用命令 对于配置中Mode设置为Dual且Slave Device设置为Mixed的情况&#xff0c;IP核支持表3-1中列出的命令。这些命令在Winbond、Micron和Spansion内存设备上具有相同的命令、地址和数据行为。 某些命令&#xff0c;如fast read、dual I/…

从年金理论到杠杆效应,再到财务报表与投资评估指标

一、解释普通年金终值和普通年金现值的概念。 普通年金终值&#xff1a;以利率为1%&#xff0c;每期收款100元&#xff0c;5期为例&#xff0c;普通年金终值的折算过程如图&#xff1a; 普通年金现值&#xff1a;以利率为1%&#xff0c;每期收款100元&#xff0c;5期为例&am…

【RabbitMQ】RabbitMQ配置与交换机学习

【RabbitMQ】RabbitMQ配置与交换机学习 文章目录 【RabbitMQ】RabbitMQ配置与交换机学习简介安装和部署1. 安装RabbitMQ2.创建virtual-host3. 添加依赖4.修改配置文件 WorkQueues模型1.编写消息发送测试类2.编写消息接收&#xff08;监听&#xff09;类3. 实现能者多劳 交换机F…

(C++)string模拟实现

string底层是一个是字符数组 为了跟库里的string区别&#xff0c;所以定义一个命名空间将类string包含 一、构造 1.构造函数 注意&#xff1a;将char*传给const char*是范围缩小&#xff0c;因此只能1&#xff1a;1构造一个 strlen遇到nullptr解引用会报错&#xff0c;因此…

C++类与对象(拷贝与类的内存管理)

感谢大佬的光临各位&#xff0c;希望和大家一起进步&#xff0c;望得到你的三连&#xff0c;互三支持&#xff0c;一起进步 个人主页&#xff1a;LaNzikinh-CSDN博客 文章目录 前言一.对象的动态建立和释放二.多个对象的构造和析构三.深拷贝与浅拷贝四.C类的内存管理总结 前言 …

element-plus日历组件el-calendar自定义内容,每天绑定不同的值

效果 代码 <template><el-calendar v-model"calendarDate"><template #date-cell"{ data }"><p :class"data.isSelected ? is-selected : ">{{ data.day.split("-").slice(1).join("-") }}{{ d…

LE Audio音频广播新功能Auracast介绍

LE Audio音频广播新功能Auracast介绍 /*! \copyright Copyright (c) 2019-2022 Qualcomm Technologies International, Ltd. All Rights Reserved. Qualcomm Technologies International, Ltd. Confidential and Proprietary. \file audio_sources.h \defgroup audio_so…

最新网赚骗局详细解析

最新网赚骗局多种多样&#xff0c;而且随着技术的发展&#xff0c;这些骗局也在不断演变和升级。以下是一些揭秘最新网赚骗局的要点&#xff1a; 1. 刷单返利类诈骗&#xff1a;骗子往往通过微信群、QQ群等社交平台发布虚假的刷单任务&#xff0c;承诺完成刷单任务后可以获得高…

IDEA创建SpringBoot项目的时候,如何使用Java8,怎么办?

在创建springboot项目的时候,IDEA提示&#xff0c;最低Java版本要求17&#xff0c;但是实际上我们可能不需要这么高的版本&#xff0c;怎么使用Java8呢&#xff1f; 解决办法 修改Server URL地址即可&#xff1a;https://start.aliyun.com

pika消费者退出

pika消费者退出问题 https://stackoverflow.com/questions/32220057/interrupt-thread-with-start-consuming-method-of-pika import threading import pikaclass WorkerThread(threading.Thread):def __init__(self):super(WorkerThread, self).__init__()self._is_interrupte…

天才程序员周弈帆 | Stable Diffusion 解读(二):论文精读

本文来源公众号“天才程序员周弈帆”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;Stable Diffusion 解读&#xff08;二&#xff09;&#xff1a;论文精读 【小小题外话】端午安康&#xff01; 在上一篇文章天才程序员周弈帆 …

【数据结构】排序(上)

个人主页~ 堆排序看这篇~ 还有这篇~ 排序 一、排序的概念及应用1、概念2、常见的排序算法 二、常见排序的实现1、直接插入排序&#xff08;1&#xff09;基本思想&#xff08;2&#xff09;代码实现&#xff08;3&#xff09;时间复杂度&#xff08;4&#xff09;空间复杂度 2…

【设计模式】创建型设计模式之 工厂模式

一、介绍 工厂模式可以分为 3 个小类 简单工厂模式工厂方法模式抽象工厂模式 工厂模式的工厂类&#xff0c;并不一定以 Factory 结尾&#xff0c;例如 DataFormat、Calender 他们都是工厂类&#xff0c;通过静态方法来创建实例。 除此之外&#xff0c;创建对象的方法名称一…

VBA即用型代码手册:删除重复行Delete Duplicate Rows

我给VBA下的定义&#xff1a;VBA是个人小型自动化处理的有效工具。可以大大提高自己的劳动效率&#xff0c;而且可以提高数据的准确性。我这里专注VBA,将我多年的经验汇集在VBA系列九套教程中。 作为我的学员要利用我的积木编程思想&#xff0c;积木编程最重要的是积木如何搭建…

电商项目-day01

文章目录 虚拟机的导入 虚拟机的导入 现根据镜像文件进行导入

streamlit:如何快速构建一个应用,不会前端也能写出好看的界面

通过本文你可以了解到&#xff1a; 如何安装streamlit&#xff0c;运行起来第一个demo熟悉streamlit的基本语法&#xff0c;常用的一些组件使用streamlit库构建应用 大模型学习参考&#xff1a; 大模型学习资料整理&#xff1a;如何从0到1学习大模型&#xff0c;搭建个人或企业…