Problem describe:
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。
示例 1:
输入: S = “ababcbacadefegdehijhklij”
输出: [9,7,8]
解释:
划分结果为 “ababcbaca”, “defegde”, “hijhklij”。
每个字母最多出现在一个片段中。
像 “ababcbacadefegde”, “hijhklij” 的划分是错误的,因为划分的片段数较少。
注意:
S的长度在[1, 500]之间。
S只包含小写字母’a’到’z’。
问题解法:
问题中描述要尽可能多的划分字母区间,我们要尽量将其划分为长度较短的字符串。中心思想就是贪心选择包含首字母的最短字符串,观察字串可知,字串一定包含与首字母相同的字母,我们在此基础上让其尽量短,如"ababcbaca",我们让其包含a之间所有字母即可,为此我们要知道此片段中的每一个字母的最后一个下标,其中最大的下标就是此字符串的结尾。
设置变量slow,fast和index,index指向首字母,slow依次检查首字母存在的范围内所有字母 ,fast指向这些字母的最后一次出现的字母中下标的最大值。当slow==fast时说明当前指向的字符串是满足题设条件的最短字符串。
代码如下:
class Solution {
public List<Integer> partitionLabels(String S) {
char[] str =S.toCharArray();
List<Integer> ans =new ArrayList<>();
int slow = 0, fast = 0;
int index=0;
while(slow<str.length&&fast<str.length)
{
fast =Math.max(findLastChar(str,slow),fast);
while(fast!=slow)
{
fast =Math.max(findLastChar(str,slow),fast);
slow++;
}
ans.add(slow-index+1);
slow++;fast++;
index=slow;
}
return ans;
}
private int findLastChar(char[] str, int slow){
int fast =0;
for(int i=str.length-1;i>=slow;i--)
{
if(str[i]==str[slow])
{
fast=i;
break;
}
}
return fast;
}
}