版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/89848881
描述:
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。
示例 1:
输入: S = "ababcbacadefegdehijhklij"
输出: [9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
注意:
S的长度在[1, 500]之间。
S只包含小写字母'a'到'z'。
这道题我们采用贪心策略,尽可能让每一个子串长度最短。蛋式由于[left ,… minRight](left指当前字符串的起始下标,minRight是S[left]最后出现的下标)中间可能出现某个字符最后出现的下标在minRight之外,这时我们就得不断更新minRight,直到left、minRight中所有的字符都只出现在这个字符串。
class Solution {
public:
vector<int> partitionLabels(string S) {
int strSize = S.size();
//第一步:统计各个字母最后一次出现的下标
vector<int> last(26, 0), resVec;
for (int index = 0; index < strSize; ++index) {
last[S[index] - 'a'] = index;
}
//第二步:从左到右扫描字符串,采取贪心策略,一直扩大当前子串的右边界
int left = 0, right = 0, minRight = 0;//当前子串的最小右边界
while (left < strSize) {
right = left + 1;//right用于扫描[left, minRight]这一段字符串
minRight = last[S[left] - 'a'];//S[left]最后出现的下标
//如果minRight大于right,则maxRight仍然需要更新,因为在[left, minRight]中可能有字符最后一次出现的下标在这之后
while (right < strSize && minRight >= right) {
minRight = max(minRight, last[S[right] - 'a']);//更新最小右边界
++right;
}
resVec.push_back(right - left);//当前子串的最小长度
left = right;
}
return resVec;
}
};