763_划分字母区间[MEDIUM]
约 417 字大约 1 分钟
2026-03-24
给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。
例如,字符串 "ababcc" 能够被分为 ["abab", "cc"],但类似 ["aba", "bcc"] 或 ["ab", "ab", "cc"] 的划分是非法的。
注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。
返回一个表示每个字符串片段的长度的列表。
示例 1:
输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。示例 2:
输入:s = "eccbbbbdec"
输出:[10]解题思路
贪心策略,两步走:
- 遍历一次字符串,用一个
int[26]存每个字母最后出现的位置(代替哈希表) - 再遍历一次字符串,用两个变量
currMinIndex、currMaxIndex控制当前片段的起始和最远距离,一旦i和currMaxIndex相等,说明要切一刀了,此时记录结果(止-起+1就是长度),同时刷新起始位置作为下一个片段的开始
Java实现
public List<Integer> partitionLabels(String s) {
List<Integer> results = new ArrayList<>();
int[] lastIndexs = new int[26];
// 1. 遍历字符串,用一个 `int[26]` 存每个字母最后出现的位置(代替哈希表)
for (int i = 0; i < s.length(); i++){
lastIndexs[s.charAt(i) - 'a'] = i;
}
int currMinIndex = 0;
int currMaxIndex = 0;
for (int i = 0; i < s.length(); i++){
char curr = s.charAt(i);
currMaxIndex = Math.max(currMaxIndex, lastIndexs[curr-'a']);
if (i == currMaxIndex){
results.add(currMaxIndex - currMinIndex + 1);
currMinIndex = currMaxIndex + 1;
}
}
return results;
}