763. 划分字母区间(力扣LeetCode)

news2024/12/24 2:38:49

763. 划分字母区间

题目描述

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。

返回一个表示每个字符串片段的长度的列表。

示例 1:

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

示例 2:

输入:s = “eccbbbbdec”
输出:[10]

提示:

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

贪心算法

一想到分割字符串就想到了回溯,但本题其实不用回溯去暴力搜索。

题目要求同一字母最多出现在一个片段中,那么如何把同一个字母的都圈在同一个区间里呢?

如果没有接触过这种题目的话,还挺有难度的。

在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。

可以分为如下两步:

  • 统计每一个字符最后出现的位置
  • 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点

如图:
在这里插入图片描述

rfind函数

以下是对于给出的代码的详细注释,解释了它是如何解决问题的:

#include <vector>
#include <string>
using namespace std;

class Solution {
public:
    vector<int> partitionLabels(string s) {
        vector<int> res; // 用于存储每个片段的长度
        int end=0; // 记录当前遍历到的所有字符中,最远的出现位置
        int cnt=0; // 当前片段的长度计数器

        // 遍历给定的字符串
        for(int i=0; i<s.size(); i++) {
            cnt++; // 每遍历一个字符,当前片段的长度加1
            // 更新当前片段中字符最远出现位置的最大值
            // s.rfind(s[i]) 返回字符s[i]最后一次出现的位置
            // 因为s.rfind的返回类型为size_t,可能与int类型的end不匹配,所以要进行类型转换
            end = max(end, (int)s.rfind(s[i]));

            // 如果当前字符是当前片段中最远出现位置的字符,
            // 则说明到目前为止的这一段可以独立为一个片段
            if (end == i) {
                // 将当前片段的长度添加到结果列表中
                res.push_back(cnt);

                // 重置计数器为下一个片段做准备
                cnt = 0;
            }
        }
        // 返回结果列表,包含了每个片段的长度
        return res;
    }
};

这段代码核心在于,通过遍历字符串,并使用end变量跟踪当前遍历到的所有字符中最远的出现位置。每当end与当前遍历的索引i相等时,说明到目前为止的这一段字符串可以划分为一个片段,因为它包含了一组字符,这些字符之后不再出现。然后,记录下这个片段的长度,并重置计数器和end变量,以便计算下一个片段的长度。最终,所有片段的长度被添加到结果列表中并返回。

易错:rfind函数返回值问题

在我没进行强制类型转换时,代码报错

Line 10: Char 17: error: no matching function for call to 'max'
   10 |             end=max(end,s.rfind(s[i]));
      |                 ^~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/algorithmfwd.h:407:5: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('int' vs. 'size_type' (aka 'unsigned long'))
  398 |     max(const _Tp&, const _Tp&);
      |     ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_algo.h:3467:5: note: candidate template ignored: could not match 'initializer_list<_Tp>' against 'int'
 3458 |     max(initializer_list<_Tp> __l, _Compare __comp)
      |     ^

这个错误信息表明max函数无法匹配到合适的重载版本,原因是传递给max的两个参数ends.rfind(s[i])具有不同的类型。在C++中,rfind返回的是size_type类型,这通常是一个无符号整数类型(比如unsigned long),而end被定义为int类型,是一个有符号整数。

在C++标准库中,max要求两个参数具有相同的类型,因为它需要能够比较这两个参数并返回其中较大的一个。当你尝试使用两个不同类型的参数调用max时,编译器无法决定应该使用哪个类型来比较,因此会报错。

解决这个问题的一种方法是,确保max的两个参数类型一致。如果你确认end变量不会存储超过int类型能表示的范围的值,可以通过强制类型转换将rfind的返回值转换为int类型,如下所示:

end = max(end, (int)s.rfind(s[i]));

哈希表

这段代码是一个解决上述问题的C++实现。我将在代码的每一部分提供详细的注释来解释它的作用。

#include <vector>
#include <string>

using namespace std;

class Solution {
public:
    vector<int> partitionLabels(string s) {
        vector<int> res; // 创建一个空的整数向量来存储最后的片段长度结果

        // 数组用于记录每个字符最后出现的索引位置
        // 因为输入字符串只包含小写字母,所以只需要大小为26的数组
        int index[26];

        // 第一个循环遍历字符串s的每个字符
        for(int i = 0; i < s.size(); i++)
            // 计算字符到'a'的距离,作为数组索引,并更新这个字符对应的最后出现位置
            // 'a'的ASCII码将被用作基准点,所以任何字符都可以通过减去'a'得到一个0到25的索引值
            index[s[i] - 'a'] = i;

        // 初始化用于追踪当前片段最右端字符的索引
        int right = 0;
        int cnt = 0; // 计数器,用于记录当前片段的长度

        // 第二个循环同样遍历字符串的每个字符
        for(int i = 0; i < s.size(); i++) {
            // 增加当前片段的计数器
            cnt++;
            // 通过字符索引,找到当前片段最右端字符的索引,与当前的`right`比较,取较大者
            // 这样可以确保当前片段包含所有已遍历字符的最后出现
            right = max(right, index[s[i] - 'a']);

            // 如果当前字符的位置i与`right`相等,说明当前片段不会再扩展了
            if(right == i) {
                // 把当前片段的长度加入到结果集
                res.push_back(cnt);
                // 重置计数器,为下一个片段准备
                cnt = 0;
            }
        }
        // 返回分段的长度数组
        return res;
    }
};

该代码分为两个主要部分:第一部分遍历字符串,记录每个字符最后出现的位置;第二部分再次遍历字符串,根据每个字符的最后出现位置,确定每个片段的边界并记录其长度。

这种方法能够确保每个字符仅出现在一个片段中,且得到的片段数目是最大化的。最终,我们得到一个数组,记录了根据给定规则得到的每个片段的长度。

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

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

相关文章

Linux:基础IO

回顾C文件接口 stdin & stdout & stderr C 默认会打开三个输入输出流&#xff0c;分别是 stdin, stdout, stderr 仔细观察发现&#xff0c;这三个流的类型都是 FILE*, fopen 返回值类型&#xff0c;文件指针 系统文件I/O 接口介绍 open man open #include <sy…

LeetCode 每日一题 Day 109-115

1969. 数组元素的最小非零乘积 给你一个正整数 p 。你有一个下标从 1 开始的数组 nums &#xff0c;这个数组包含范围 [1, 2p - 1] 内所有整数的二进制形式&#xff08;两端都 包含&#xff09;。你可以进行以下操作 任意 次&#xff1a; 从 nums 中选择两个元素 x 和 y 。 选…

【贫民版】Springboot导入返回错误Excel表格 ---- 通过session存储字节数据,再获取写到响应体中。

目录 前言一、需求二、需求分析三、代码 前言 在开发中会遇到导入文件后&#xff0c;失败的数据需要整理在加上导入失败原因。 按照目前主流的方法&#xff0c;要么通过流输出到response响应体中&#xff0c;或者把失败的excel上传到服务器中&#xff0c;返回url让前端下载。…

pyqt 创建右键菜单栏

class MainModule(QMainWindow, Ui_MainWindow):def __init__(self):super().__init__(parentNone)self.setupUi(self)# 允许出现菜单栏self.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu)# 对空间添加右键菜单栏处理 self.tableWidget.customContextMenuRequested.…

Redis入门到实战-第十九弹

Redis实战热身Count-min-sketch篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#xff09;&#xff0c;用作数据库、缓存、…

cuDNN——核心概念

在讨论graph和legacy API的细节之前&#xff0c;这一部分先介绍两者共同的核心概念。 cuDNN Handle cuDNN库暴露了一系列主机API&#xff0c;但是假设所有用到GPU的op&#xff0c;其必要的数据都可以直接从设备上访问。 使用cuDNN的应用必须先调用cudnnCreate()来初始化句柄…

【C/C++】C++中的四种强制类型转换

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

USART发送各种数据类型数据的原理及程序实现

硬件接线&#xff1a; 显示屏的SCA接在B11&#xff0c;SCL接在B10&#xff0c;串口的RX连接A9&#xff0c;TX连接A10。 新建Serial.c和Serial.h文件 在Serial.c文件中&#xff0c;实现初始化函数&#xff0c;等需要的函数&#xff0c;首先对串口进行初始化&#xff0c;只需要…

信创实力进阶,Smartbi再获华为云鲲鹏技术认证

日前&#xff0c;经华为技术有限公司评测&#xff0c;思迈特商业智能与数据分析软件Smartbi Insight V11与华为技术有限公司Kunpeng 920 Taishan 200完成并通过相互兼容性测试认证&#xff0c;成功再获华为云鲲鹏技术认证书&#xff0c;标志着Smartbi与华为云鲲鹏产业生态合作更…

http模块—http请求练习

题目要求&#xff1a;搭建如下http服务&#xff1a; 1.当浏览器向我们的服务器发送请求时&#xff0c;当请求类型是get请求&#xff0c;请求的url路径地址是/login。响应体结果是登录页面 2.当浏览器向我们的服务器发送请求时&#xff0c;当请求类型是get请求&#xff0c;请求…

物流智能蓝牙锁控设计方案

一、行业背景与需求分析 物流行业作为全球贸易和供应链管理的关键环节&#xff0c;其安全性和效率对整个经济体系的运作至关重要。随着电子商务的兴起和全球市场的一体化&#xff0c;物流行业正面临着前所未有的挑战&#xff0c;尤其是在货物安全、运输效率、成本控制和信息管…

C#学生信息成绩管理系统

一、系统功能描述 本系统包括两类用户&#xff1a;学生、管理员。管理员可以通过系统来添加管理员信息、修改管理员信息、添加学生信息、修改学生信息&#xff1b;开设课程、查询课程、录入成绩、统计成绩、修改成绩、修改个人密码等&#xff0c;而学生则可以通过系统来选择课…

干货分享:品牌如何通过社媒激发年轻人消费力?

随着年轻人的消费愈发理性&#xff0c;年轻人在消费时更偏向于熟人种草场景下的信任决策&#xff0c;社交媒体成为品牌吸引用户的必争之地。今天媒介盒子就来和大家聊聊&#xff1a;品牌如何通过社媒激发年轻人消费力。 一、 激发用户共鸣&#xff0c;与用户产生情感连接。 虽…

Midjourney辞典AIGC中英双语图文辞典+Midjourney提示关键词

完整内容下载&#xff1a;https://download.csdn.net/download/u010564801/89042077 完整内容下载&#xff1a;https://download.csdn.net/download/u010564801/89042077 完整内容下载&#xff1a;https://download.csdn.net/download/u010564801/89042077

哈希表(hash_table) 哈希存储 算法相关知识 稳定性 时间复杂度

哈希存储(散列存储) 为了快速定位数据 哈希表 哈希冲突 / 哈希矛盾 关键字不一样&#xff0c;但是映射之后结果一样 如何避免 哈希矛盾&#xff1f; 1、重新设计哈希函数&#xff0c;尽可能均匀散列分布在哈希表 2、开放定址法&#xff1a;向下寻找未存储的位置进行存放数…

aardio - 【库】godking.plusSkin 设置plus样式

库名&#xff1a;godking.plusSkin 库文件下载工具&#xff1a;http://chengxu.online/show.asp?softid272 使用本库&#xff0c;可以快速设置plus样式。主要针对按钮样式进行快速批量设置。 部分用法如下&#xff1a; import win.ui; /*DSG{{*/ var winform win.form(tex…

C++初学者:如何优雅地写程序

我喜欢C语言的功能强大&#xff0c;简洁&#xff0c;我也喜欢C#的语法简单&#xff0c;清晰&#xff0c;写起来又方便好用。 一、为什么不用C语言写程序。 C语言用来做题目&#xff0c;考试研究是很方便的&#xff0c;但是用来写程序做软件&#xff0c;你就会发现&#xff0c…

Android中运动事件的处理

1.目录 目录 1.目录 2.前言 3.程序演示 4.第二种程序示例 5.扩展 2.前言 触摸屏&#xff08;TouchScreen&#xff09;和滚动球&#xff08;TrackBall&#xff09;是 Android 中除了键盘之外的主要输入设备。如果需要使用触摸屏和滚动球&#xff0c;主要可以通过使用运动事…

[DS]Polar靶场web(一)

静以养心&#xff0c;宽以养气。 跟着Dream ZHO大神学专升安的一天 swp 直接dirb扫出.index.php.swp的目录 function jiuzhe($xdmtql){return preg_match(/sys.*nb/is,$xdmtql);//如果包含以 "sys" 开始&#xff0c;后跟任意字符直到 "nb" 的字符串&…

[XG] HTTP

我希望风起&#xff0c;而你好像更希望风停。 闲来无事&#xff0c;跟着Z3r4y-CSDN博客大神学一学web吧 [NewStarCTF 2023]Begin of HTTP 1.题目要求使用GET方式来给ctf参数传入任意值&#xff0c;那就传吧。 2.又让以POST方式来传递secert参数&#xff0c;并且要找一下参数…