A string S
of lowercase English letters is given. We want to partition this string into as many parts as possible so that each letter appears in at most one part, and return a list of integers representing the size of these parts.
Example 1:
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.
Note:
S
will have length in range[1, 500]
.S
will consist of lowercase English letters ('a'
to'z'
) only.
划分字母区间。题意是给一个字符串,请你将字符串分割,我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。
思路是贪心 + 双指针。首先遍历一次字符串,将每个字符最后一次出现的index记录下来。再遍历一次字符串,这一次需要用到两个指针,start指针一开始在字符串的起始部位,end指针一点点随着i指针往后走,每次看到一个字母,end就更新为当前遍历到的所有字母中间的最后一个出现的位置。如果在某一个i发现这是当前字母最后一次出现的位置,则说明当前 i 位置上这个字母之后再也不可能遇到,可以开始分割input了,(start, i),然后下一个分段则是从i + 1开始。
时间O(n)
空间O(n)
Java实现
1 class Solution { 2 public List<Integer> partitionLabels(String S) { 3 // corner case 4 if (S == null || S.length() == 0) { 5 return new ArrayList<>(); 6 } 7 8 // normal case 9 int[] last = new int[26]; 10 for (int i = 0; i < S.length(); i++) { 11 last[S.charAt(i) - 'a'] = i; 12 } 13 int start = 0; 14 int end = 0; 15 List<Integer> res = new ArrayList<>(); 16 for (int i = 0; i < S.length(); i++) { 17 end = Math.max(end, last[S.charAt(i) - 'a']); 18 if (end == i) { 19 res.add(i - start + 1); 20 start = i + 1; 21 } 22 } 23 return res; 24 } 25 }