划分字母区间
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
示例:
输入:S = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
提示:
S的长度在[1, 500]之间。
S只包含小写字母 'a' 到 'z' 。
class Solution { public: vector<int> partitionLabels(string S) {//贪心算法和双指针 int last[26]={0}; int length = S.size(); for(int i=0;i<length;i++){ last[S[i] - 'a'] = i;//找出每一个小写字符最后出现的位置 } vector<int> partition; int start =0,end = 0;//双指针,标记着每一段的开始和结束 for(int i=0;i<length;i++){ end = max(end,last[S[i] - 'a']); if(i == end){ //已经找到满足当前字段出现的所有字符均在一个字段的约束条件 //根据贪心原理,使得每个字段的长度最短 partition.push_back(end - start+1); start = end+1; } } return partition; } };
注意:
1.采用双指针,标记着每一段的开始和结束
2.第一遍遍历,确定出字符串中所有字符最后出现的位置
3.第二次遍历确定划分的片段和范围,注意始终更新end = max(end,last[S[i]-'a'])来保证当前字段出现的字符均出现在同一字段,使得满足约束条件
4.贪心原理的应用,当i == end的时候,说明找到一个可行的字段的结束,由于长度是不断递增的,所以第一次出现的即为长度最短的。由于每次取的片段都是最短片段,因此也就能获得最多的片段个数