版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/musechipin/article/details/82737162
1.从第一个字母开始,找到它最后一次出现的位置,那么这一段就是当前最短的一节(因为一节需要把同一个字母全都包含进去)。但是在这一节中如果有别的字母在之后又出现了,这一节的长度需要延长到那个字母最后一次出现的位置。
2.同一个字母第一次遇到的时候其首尾之间的距离将是最大的,所以一个字母只要找一次记下来即可。
算法主要分为两个循环,第一个循环找到每个字母的首位最大距离(记录头和尾)。第二个循环顺序计算,如果某个字母的头位置超出了上一节的结尾,说明上一节结束了,开始新的一节。两个循环好像也可以合并成一个循环,我没有做,速度还是很快,4msbeat99%。
class Solution {
public:
vector<int> partitionLabels(string S) {
vector<int> res;
int n = S.length();
vector<pair<int, int>> index(26);
vector<bool> record(26,false);
for (int i = 0; i < n;i++)
{
if (record[S[i] - 'a'] == false)
{
int j = n - 1;
while (S[j] != S[i]) j--;
index[S[i] - 'a'] = make_pair(i, j);
record[S[i] - 'a'] = true;
}
}
int head = index[S[0] - 'a'].first;
int tail = index[S[0] - 'a'].second;
for (int i = 0; i < n; i++)
{
if (index[S[i] - 'a'].first > tail)
{
res.push_back(tail - head + 1);
head = index[S[i] - 'a'].first;
tail = index[S[i] - 'a'].second;
}
else if (index[S[i] - 'a'].second > tail) tail = index[S[i] - 'a'].second;
}
res.push_back(tail - head + 1);
return res;
}
};
emmmm看了一下别人的做法,发现其实不用记录首位置:
class Solution {
public:
vector<int> partitionLabels(string S) {
vector<int> last(26, 0);
int length = (int)S.length();
for (int i = 0; i < length; i++) {
last[S.at(i) - 'a'] = i;
}
int start = 0, end = 0;
vector<int> partition;
for (int i = 0; i < length; i++) {
end = max(last[S.at(i) - 'a'], end);
if (end == i) {
partition.push_back(end - start + 1);
start = i + 1;
}
}
return partition;
}
};