Problem

A string S of lowercase 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 letters ('a' to 'z') only.

Solution

Solution 0 - preferred

using char array is so much faster

class Solution {
    public List<Integer> partitionLabels(String S) {
        List<Integer> res = new ArrayList<>();
        int[] dict = new int[26];
        char[] str = S.toCharArray();
        for (char ch: str) {
            dict[ch-'a']++;
        }
        int i = 0, j = 0, count = 0;
        Set<Character> set = new HashSet<>();
        while (j < S.length()) {
            char ch = str[j];
            if (!set.contains(ch)) {
                set.add(ch);
                count++;
            }
            dict[ch-'a']--;
            j++;
            
            if (dict[ch-'a'] == 0) {
                count--;
                set.remove(ch);
            }
            
            if (count == 0) {
                res.add(j-i);
                i = j;
            }
        }
        return res;
    }
}

Solution 1

class Solution {
    public List<Integer> partitionLabels(String S) {
        List<Integer> res = new ArrayList<>();
        int[] index = new int[26];
        for (int i = 0; i < S.length(); i++) {
            index[S.charAt(i) - 'a'] = i;
        }
        int start = 0;
        int end = 0;
        for (int i = 0; i < S.length(); i++) {
            int c = S.charAt(i) - 'a';
            if (index[c] != i) {
                if (index[c] > end) {
                    end = index[c];
                }
            } else if (i == end){
                res.add(i - start + 1);
                start = i + 1;
                end = i + 1;
            }
        }
        return res;
    }
}

Solution 2 - Sliding Window + 2 HashMap

class Solution {
    public List<Integer> partitionLabels(String S) {
        List<Integer> res = new ArrayList<>();
        if (S == null || S.length() == 0) return res;
        
        Map<Character, Integer> map = new HashMap<>();
        for (char ch: S.toCharArray()) {
            map.put(ch, map.getOrDefault(ch, 0)+1);
        }
        
        Map<Character, Integer> record = new HashMap<>();
        int start = 0, end = 0;
        while (end < S.length()) {
            char ch = S.charAt(end);
            if (!record.containsKey(ch)) record.put(ch, map.get(ch));
            record.put(ch, record.get(ch)-1);
            if (record.get(ch) == 0) record.remove(ch);
            if (record.keySet().size() == 0) {
                res.add(end-start+1);
                start = end+1;
            }
            end++;
        }
        
        return res;
    }
}

linspiration
161 声望53 粉丝