leetcode 763.划分字母区间
题干
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。
示例 1:
输入:S = “ababcbacadefegdehijhklij”
输出:[9,7,8]
解释:
划分结果为 “ababcbaca”, “defegde”, “hijhklij”。
每个字母最多出现在一个片段中。
像 “ababcbacadefegde”, “hijhklij” 的划分是错误的,因为划分的片段数较少。
提示:
S的长度在[1, 500]之间。
S只包含小写字母 ‘a’ 到 ‘z’ 。
题解
丑陋的代码,大体上用了一点点哈希表的思想+贪心算法+双指针
* 头尾一个字母分出单独区间的情况要注意
* 其实不用存左界,二维数组可以改一维数组
* 具体处理临界情况的写法可以再优化一下,今天想不动了…
class Solution {
public:
vector<int> partitionLabels(string S) {
vector<int> ans;
bool repeat[26];
//alphaBound[i][j]储存每个出现字母的左右界,j=0左界,j=1右界
int alphaBound[26][2];
memset(alphaBound,0,sizeof(alphaBound));
memset(repeat,false,sizeof(repeat));
int n = S.length();
for(int i=0;i<n;i++){
if(repeat[S[i]-'a']==false){
alphaBound[S[i]-'a'][0] = i;
alphaBound[S[i]-'a'][1] = i;
repeat[S[i]-'a'] = true;
}
else{
alphaBound[S[i]-'a'][1] = i;
}
}
int startIndex = 0;
int endIndex = alphaBound[S[0]-'a'][1];
int ptr = startIndex;
while(ptr<n){
if(ptr==endIndex){
cout<<"1"<<endl;
ans.push_back(endIndex-startIndex+1);
ptr++;
if(ptr==n)
break;
startIndex = ptr;
endIndex = alphaBound[S[ptr]-'a'][1];
}
//更新分段右界,将一个分段的结尾指向第一个字母最后一次出现的下标
endIndex = max(alphaBound[S[ptr]-'a'][1],endIndex);
if(ptr==endIndex){
ans.push_back(endIndex-startIndex+1);
if(ptr==n)
break;
startIndex = ptr + 1;
endIndex = alphaBound[S[ptr]-'a'][1];
}
ptr++;
}
return ans;
}
};