划分字母
Leetcode : 763. Partition Labels (Medium)
题目:
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。
示例 1:
输入: S = “ababcbacadefegdehijhklij”
输出: [9,7,8]
解释:
划分结果为 “ababcbaca”, “defegde”, “hijhklij”。
每个字母最多出现在一个片段中。
像 “ababcbacadefegde”, “hijhklij” 的划分是错误的,因为划分的片段数较少。
注意:
S的长度在[1, 500]之间。
S只包含小写字母’a’到’z’。
解题思路:
明确每个字母只会出现在其中一个片段中,想到需要把每个字母 最后出现的位置 记录下来。
1.使用一个数组存储每个字母最后出现的位置
2.从头开始查找这样的 “字符串” ,对应字符串中的每个字母,它出现的最后的那个字母已经包含在整个字符串中。
3.答案需要返回每一个截取的长度,所以需要记录start的位置和end的位置。
public List<Integer> partitionLabels(String S) {
if(S.length() == 0 || S == null){
return new ArrayList<>();
}
List<Integer> result = new ArrayList<>();
int[] lastIndex = new int[26];//存储a~z
//记录每个字母最后出现的下标
for(int i = 0; i < S.length(); i++){
lastIndex[S.charAt(i) - 'a'] = i;
}
//记录每个字符串的开始和结尾
//从0开始
int start = 0;
int end = lastIndex[S.charAt(0) - 'a'];//获取第一个字母的最后出现的下标
//从第一个开始查找,如果当前的下标和end相等,说明该字符串划分结束,继续下一个字符串的划分
for(int i = 0; i < S.length(); i++){
//对比当前的i的下标和之前的结束下标end谁的大,如果当前的大,说明当前的end应该作为结尾,才能符合同一个字母只会出现在其中一个片段
end = Math.max(lastIndex[S.charAt(i) - 'a'], end);
//如果当前等于了结束end,说明当前字符串片段划分完毕
if(i == end){
result.add(end - start + 1);
start = end + 1;
}
}
return result;
}