python
from collections import defaultdict
class Solution:
def partitionLabels(self, s: str) -> List[int]:
end_pos = defaultdict(int)
start, end = 0, 0
res = []
# 记录每个字母的最后出现位置
for i, ch1 in enumerate(s):
end_pos[ch1] = i
# 不断更新end
# 当j == end时,说明当前子字符串的所有字母的最后位置都已遍历到,添加答案
for j, ch2 in enumerate(s):
end = max(end, end_pos[ch2])
if j == end:
res.append(end-start+1)
start = end + 1
return res
c++
合并区间思想
vector<int> partitionLabels(string s) {
// 思路: 计算每个字符的出现区间[第一次出现位置start, 最后一次出现位置end]
// 对所有区间以start升序排序
// 合并区间,返回各独立区间长度
vector<int> res;
vector<pair<int, int> > interval_vec;
unordered_map<char, pair<int, int> > char_interval;
// 计算每个字符出现区间
for (int i = 0; i < s.size(); ++i) {
if (char_interval.count(s[i]) == 0) {
char_interval[s[i]] = make_pair(i, i);
} else {
char_interval[s[i]].second = i;
}
}
// 排序区间
for (auto& it : char_interval) {
interval_vec.push_back(it.second);
}
sort(interval_vec.begin(), interval_vec.end(), [](const pair<int, int>& a, const pair<int, int>& b) {
return a.first < b.first;});
// 合并区间
int start = interval_vec[0].first, end = interval_vec[0].second;
for (int i = 1; i < interval_vec.size(); ++i) {
if (interval_vec[i].first > end) {
res.push_back(end - start + 1);
start = interval_vec[i].first;
end = interval_vec[i].second;
} else {
end = max(interval_vec[i].second, end);
}
if (i == interval_vec.size() - 1) {
res.push_back(end - start + 1);
}
}
return res;
}
贪心
vector<int> partitionLabels(string s) {
// 思路: 记录每个字符最后一次出现的位置
unordered_map<char, int> last_pos_map;
vector<int> res;
for (int i = 0; i < s.size(); i++) {
last_pos_map[s[i]] = i;
}
int start = 0, end = 0;
for (int i = 0; i < s.size(); i++) {
end = max(end, last_pos_map[s[i]]);
if (i == end) {
res.push_back(end - start + 1);
start = i + 1;
}
}
return res;
}