一、题目描述
字符串 S
由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
二、解题思路
使用滑动窗口来解决,根据上面的示例,其实可以把每个片段看成是一个窗口,只要保证当前窗口中出现的字符不会出现在其它窗口即可,下面模拟一下这个过程:
第一步:对于第一个字符a
,看它最远出现在如下的位置:
说明当前片段至少是left
到right
之间,那最终是不是还要取决于这个区间其它元素最远出现的位置是不是在当前right
之后,所以要依次遍历当前区间内的元素,直到遍历完为止,发现没有元素超过这个right
的位置,所以得到第一个片段:
第二步:left
后移到right+1
的位置,该位置元素是d
,然后right
移动到第二个d
最远出现的位置,当前区间就是第二个片段至少可能的区间,依然要区间内遍历元素判断:
然后遍历区间内的元素e
,它出现的第二个位置在当前right
后面,right移动到这个位置:
继续遍历其它元素,没有第二次出现超过当前right
的,所以得到第二个片段,长度为right-left+1
接下来就重复上面步骤即可。
三、代码演示
class Solution {
public List<Integer> partitionLabels(String s) {
//计算并存储每个字符在数组中所在的最大索引
int[] c2Index = new int[26];
for (int i=0; i<s.length();i++){
//得到的是最大索引,也就是最远的那个值
c2Index[s.charAt(i)-'a'] = i;
}
//存储最终结果
List<Integer> res = new ArrayList<>();
//维护窗口
int left=0, right=0;
for (int i=0; i<s.length(); i++){
char c = s.charAt(i);
right = Math.max(right, c2Index[c-'a']);
if (i==right){
res.add(right-left+1);
left = right+1;
}
}
return res;
}
}