方法一
实现思想
首先要理解子片段是怎么定义的,子片段保证里面含有的字母仅出现在该子片段中,也就是不同子片段之间字母是没有交集的
利用了【LeetCode392】-判断子序列拓展题目的思想,提前存储了字符串中各个字母出现的初位置和末位置
利用了 【LeetCode452】-用最少数量的箭引爆气球 不同区间更换弓箭手的思想,当两个区间有重叠时,更新区间,当两个区间没有重叠时,将当前结果压入,更新区间的范围为新区间的范围
概括来说就是遍历求得每一种字母在字符串中起始结束位置,按照起始位置将数据升序排列,遍历该预处理的数组,进行区间合并,压入结果时压入的是区间的初末位置的长度
实现代码
bool cmp(const vector<int> &a,const vector<int> &b){
return a[0]<b[0];
}
class Solution {
public:
vector<int> partitionLabels(string S) {
vector<vector<int>> ab;
vector<int> book(26,-1);
for(int i=0;i<S.length();i++){
int t=S[i]-'a';
if(book[t]==-1){
vector<int> tt;
tt.push_back(i);
tt.push_back(i);
int nn=ab.size();
book[t]=nn;
ab.push_back(tt);
}
else{
ab[book[t]][1]=i;
}
}
sort(ab.begin(),ab.end(),cmp);
vector<int> res;
int be=ab[0][0];
int end=ab[0][1];
for(int i=1;i<ab.size();i++){
if(ab[i][0]<end) end=max(end,ab[i][1]);
else{
res.push_back(end-be+1);
be=ab[i][0];
end=ab[i][1];
}
}
res.push_back(end-be+1);
return res;
}
};
提交结果及分析
时间复杂度O(n),空间复杂度O(n)
方法二
实现思想
提前存储所有字母出现的最后一个位置,i开始遍历字符串,里面i所经历过的字母如果可以扩充end值则进行扩充来更新end值,当i等于end时说明这一子序列遍历完毕,然后更新start=end+1
实现代码
与我的方法一不同的一点在于,并没有记录出现的第一个位置,而是只记录了最后的一个位置
分析
时间复杂度O(n)