Intuition
A part cannot end until every letter it contains has had its last occurrence. Track the farthest last-occurrence as you scan; when the current index reaches it, close the part.
Explanation
The invariant
Record the last index each letter appears at. Scan left to right keeping end = max(end, last[s[i]]) — the farthest position any letter seen so far reaches. The moment i == end, no letter inside the current window appears later, so it's safe to cut here.
Walk-through
last = {each char -> its last index}
start = end = 0
for i, c in enumerate(s):
end = max(end, last[c])
if i == end: emit (end - start + 1); start = i + 1
Worked example
s = "ababcbacadefegdehijhklij" → parts "ababcbaca" (9), "defegde" (7), "hijhklij" (8) → [9,7,8].
Complexity
- Time: O(n).
- Space: O(1) — at most 26 last-occurrence entries.
Implementation
import java.util.ArrayList;
import java.util.List;
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;
}
List<Integer> res = new ArrayList<>();
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
end = Math.max(end, last[s.charAt(i) - 'a']);
if (i == end) {
res.add(end - start + 1);
start = i + 1;
}
}
return res;
}
}