Lesson 213 of 250
763. Partition Labels
NeetCode: Partition Labels · LeetCode: 763. Partition Labels · Difficulty: Medium
Split the string s into as many parts as possible so that each letter appears in at most one part. Return the sizes of the parts, in order.
Example
Input: s = "xyxxyzbzbbisl" Output: [5, 5, 1, 1, 1] ("xyxxy", "zbzbb", "i", "s", "l")
Input: s = "abcabc" Output: [6]Brute force: rescan for the last occurrence
A part starting at the first unused character must end at or after that character's last occurrence. Walk forward through the part; for every character, find its last occurrence with String.lastIndexOf, which scans from the end of the string and extend the end if it is farther. When the walk reaches the end, cut the part.
import java.util.ArrayList;
import java.util.List;
class Solution {
public List<Integer> partitionLabels(String s) {
List<Integer> parts = new ArrayList<>();
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
end = Math.max(end, s.lastIndexOf(s.charAt(i)));
if (i == end) {
parts.add(end - start + 1);
start = i + 1;
}
}
return parts;
}
}
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.partitionLabels("xyxxyzbzbbisl"));
System.out.println(sol.partitionLabels("abcabc"));
System.out.println(sol.partitionLabels(""));
}
}[5, 5, 1, 1, 1]
[6]
[]Time: O(n^2) (each lastIndexOf may scan the string). Space: O(1) besides the output.
Optimal: precompute last indices
The slow step above is finding the last occurrence, which can be precomputed once in a table of 26 slots. s.charAt(i) - 'a' subtracts two char values as int, giving the letter's position from 0 to 25. The string holds lowercase English letters only. A part may not end before the last occurrence of any letter inside it, so end keeps extending; when the index i reaches end, every letter in the part has all its occurrences inside. Cutting there is the earliest safe cut, which gives the most parts.
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> parts = 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) {
parts.add(end - start + 1);
start = i + 1;
}
}
return parts;
}
}
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.partitionLabels("xyxxyzbzbbisl"));
System.out.println(sol.partitionLabels("abcabc"));
System.out.println(sol.partitionLabels(""));
}
}[5, 5, 1, 1, 1]
[6]
[]Time: O(n). Space: O(1) (26 counters) besides the output.
