题解:
题目的意思是输入一个字符串,将其尽可能地连续地分为多个字符串,且每个字符串彼此之间没有相同的字母。最后返回每个字符串的长度。由题可得,对字符串进行切分之后,相同的字母一定是属于同一字符串的。我们可以利用这个特性,先来确定并保存每个字符串的最后一个字母在原始字符串中的位置。声明now变量,用来遍历整个原始的字符串。partion变量是用来存储切分完字符串的最后一个字母的位置。
假设输入的字符串是”ababcbacadefegdehijhklij”,我们先确定切分完之后,第一个子字符串的最后一个字母的位置。由于我们不知道这个位置,所以我们先假设原始字符串的第一个字母a,是切分完第一个子字符串的最后一个字母,并把partion指向它。如果这个假设为真,则在【0,partion】的字母,不会出现在(partion,N-1】,N为原始字符串的长度。为了验证这个,我们不断的用now指向【0,partion】范围内的每个字母,来与(partion,N-1】的所有字母比较。一旦出现相同的情况,则证明目前partion的值是错误的,更新partion的值为右边相同字母的位置(字母相同则一定属于同一字符串),再继续进行验证。直到now和partion再次指向同一位置时,表明【0,partion】范围内的字母与(partion,N-1】范围内的字母没有重叠的,则确定该位置是切分完第一个子字符串的最后一个字母,将其存到list中。
当找到第一个字符串的最后一个字母的位置后,则原始字符串变为“ababcbaca”和“defegdehijhklij”。我们可以假设前面是不存在的,在“defegdehijhklij”中用同样的操作确定切分完第一个子字符串的最后一个字母的位置,存到list中。这样下去,最后能够找到所有字符串的最后一个字母的位置。然后我们把每个字符串最后一个字母的位置+1减去前一个字符串最后一个字母的位置+1(+1的操作是必须的,因为不这样做,第一个子字符串的长度会出错)。最后再返回。
class Solution {
public List<Integer> partitionLabels(String S) {
List<Integer> list = new ArrayList<>();
int partion = 0, now = 0, N = S.length();
while(now < N) {
int i;
for(i = partion+1; i < N; i++)
if(S.charAt(i) == S.charAt(now)) {
partion = i;
break;
}
if(i == N && now==partion)
list.add(++partion);
now++;
}
for(int i = list.size()-1; i > 0; i--)
list.set(i, list.get(i)-list.get(i-1));
return list;
}
}
下面是Solution里面的答案
class Solution {
public List<Integer> partitionLabels(String S) {
int[] last = new int[26];
for (int i = 0; i < S.length(); ++i)
last[S.charAt(i) - 'a'] = i;
int j = 0, anchor = 0;
List<Integer> ans = new ArrayList();
for (int i = 0; i < S.length(); ++i) {
j = Math.max(j, last[S.charAt(i) - 'a']);
if (i == j) {
ans.add(i - anchor + 1);
anchor = i + 1;
}
}
return ans;
}
}