You are given a string s consisting of lowercase English letters. We want to split the string into as many substrings as possible, while ensuring that each letter appears in at most one substring.
Return a list of integers representing the size of these substrings in the order they appear in the string.
"xyxxy", "zbzbb", "i", "s", "l". No character appears in more than one part.s consists of lowercase English letters only.The key insight: for any character, all of its occurrences must live in the same partition.That means if you've included one 'a', you must include every 'a'.
So as you scan left-to-right, for each character you see, your current partition must extend at least to that character's last occurrence in the string. Once your scan pointer reaches the current partition's end boundary — you're done with that partition.
Think of each character as a rubber band stretched to its last occurrence. Your current partition is the union of all rubber bands of characters you've included so far. When your pointer catches up to the rightmost stretch — that partition snaps closed.
"xyxxyzbzbbisl":x→3, y→4, z→7, b→9, i→10, s→11, l→12'x': end = max(0, 3) = 3'y': end = max(3, 4) = 4'x': end stays 4'y': end stays 4 → i == end → cut! size=5'z': end = max(5, 7) = 7 … i=9 'b': end stays 9 → i == end → cut! size=5'i': end=10 → cut (size=1). Same for 's' and 'l'.For every possible cut position, check whether any character in the left segment also appears in the right segment. If none do, the cut is valid.
Why it's not optimal: For each boundary we scan remaining characters — O(n²). Precomputing last occurrences lets us cut in a single O(n) pass.
def partitionLabels(s): res, start = [], 0 while start < len(s): end = start for j in range(start, len(s)): # extend end to last occurrence of s[j] end = max(end, s.rfind(s[j])) if j == end: break res.append(end - start + 1) start = end + 1 return res
Two passes: first record each character's last index. Then scan left-to-right, extending end to cover the last occurrence of every character seen so far. When i == end, the partition is complete.
last[c] = last index of character c in s.start = end = 0.i: update end = max(end, last[s[i]]).i == end: record size end - start + 1, set start = i + 1.start — after recording a partition, set start = i + 1. Omitting this causes sizes to accumulate incorrectly.i == end, not i >= end.s.length.last map holds at most 26 entries (lowercase letters only) — effectively constant space.
Discussion
…