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 }

 

LeetCode 题目总结