问题描述
给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。
注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。
返回一个表示每个字符串片段的长度的列表。
[力扣网](https://leetcode.cn/)
示例 1:
输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。
示例 2:
输入:s = "eccbbbbdec"
输出:[10]
解题思路(贪心算法):
要解决这个问题,我们可以使用贪心算法来解决。算法的核心思
想是在每一步尽可能地划分出最小的片段,同时确保每个片段包含
了其中字母在字符串中出现的所有位置。为了做到这一点,需要首
先找出字符串中每个字符最后出现的位置。
解题思路
1、找出每个字符最后出现的位置:
遍历字符串 s,使用一个哈希表(或数组)来记录每个字符最后出现的位置。
2、遍历字符串并划分片段:
再次遍历字符串,并使用两个变量 left和 right来标记当前片段的起始和
结束位置。对于每个字符,更新 right为当前字符和之前字符的最后出现位置
的最大值。当遍历到的位置等于 right时,意味着当前片段不能再扩展(因为
扩展会包含其他片段的字符),这时就可以划分出一个新片段。
3、记录片段长度并继续:
将当前片段的长度(right- left+ 1)加入结果列表,并更新 left为
right+ 1,继续进行下一个片段的划分。
4、返回结果:
遍历完成后,返回记录各个片段长度的列表。
C++代码片
下面展示为力扣中的C++风格的 代码片
.
class Solution {
public:
vector<int> partitionLabels(string s) {
int n=s.size();
vector<int>res;
int hash[27]={0};//i为字符,hash[i]为字符出现的最后位置
int left=0,right=0;
for(int i=0;i<n;i++)
{
hash[s[i]-'a']=i;
}
for(int i=0;i<n;i++)
{
right=max(right,hash[s[i]-'a']);// 更新当前片段的结束位置
if(i==right)
{
// 如果达到了片段的结束位置,划分出一个新片段
res.push_back(right-left+1);
left=i+1;// 更新下一个片段的起始位置
}
}
return res;
}
};