分隔字符串使同种字符出现在一起
763. Partition Labels (Medium)
Input: S = "ababcbacadefegdehijhklij"
Output: [9,7,8]
Explanation:
The partition is "ababcbaca", "defegde", "hijhklij".
This is a partition so that each letter appears in at most one part.
A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits S into less parts.
题目描述:
这道题给了我们一个字符串s,然后将其尽可能多的分割为子字符串,条件是每种字符最多只能出现在一个子串中,这道题的难点在于如何找到字符串的断点,即拆分为子串的位置,我们仔细观察题目中的例子,可以发现一旦某个字母多次出现了,那么其最后一个出现位置必须要在当前子串中,字母a,e和j分别是三个子串的结束字母。所以我们关注的是每个字母最后出现的位置,我们可以使用map保存每个字母和其最后一次出现的位置。
建立好映射后,我们遍历字符串s,我们维护一个start变量,是当前子串的起始位置,还有一个last变量,是当前子串的结束位置,每当我们遍历到一个字母时,我们从map中提取其出现的最后一个位置,因为一个字符串一旦包含一个字母,就要包含所有相同的字母,所以我们要不停的用当前字母的最后一个下标来更新last变量,只有当i和last相等的时候,就是当前子串该断开的地方。
代码:
class Solution {
public List<Integer> partitionLabels(String S) {
List<Integer>res=new ArrayList<>();
if(S==null||S.length()==0)
return res;
int []map=new int [26]; //记录每个字母出现的最后一个下标
for(int i=0;i<S.length();i++){
map[S.charAt(i)-'a']=i;
}
int start=0;
int last=0;
while(start<S.length()){
int i=start;
while(i<S.length()){
last=Math.max(last,map[S.charAt(i)-'a']);//取访问到的字母的最大最后一个坐标更新last
if(last==i){
res.add(i-start+1);
start=i+1;
break;
}
i++;
}
}
return res;
}
}