Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
You are given a string s. We want to partition the string into as many parts as possible so that each letter appears in at most one part. For example, the string "ababcc" can be partitioned into ["abab", "cc"], but partitions such as ["aba", "bcc"] or ["ab", "ab", "cc"] are invalid.
Note that the partition is done so that after concatenating all the parts in order, the resultant string should be s.
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.
Example 2:
Input: s = "eccbbbbdec" Output: [10]
Constraints:
1 <= s.length <= 500s consists of lowercase English letters.Problem summary: You are given a string s. We want to partition the string into as many parts as possible so that each letter appears in at most one part. For example, the string "ababcc" can be partitioned into ["abab", "cc"], but partitions such as ["aba", "bcc"] or ["ab", "ab", "cc"] are invalid. Note that the partition is done so that after concatenating all the parts in order, the resultant string should be s. Return a list of integers representing the size of these parts.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Two Pointers · Greedy
"ababcbacadefegdehijhklij"
"eccbbbbdec"
merge-intervals)optimal-partition-of-string)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #763: Partition Labels
class Solution {
public List<Integer> partitionLabels(String s) {
int[] last = new int[26];
int n = s.length();
for (int i = 0; i < n; ++i) {
last[s.charAt(i) - 'a'] = i;
}
List<Integer> ans = new ArrayList<>();
int mx = 0, j = 0;
for (int i = 0; i < n; ++i) {
mx = Math.max(mx, last[s.charAt(i) - 'a']);
if (mx == i) {
ans.add(i - j + 1);
j = i + 1;
}
}
return ans;
}
}
// Accepted solution for LeetCode #763: Partition Labels
func partitionLabels(s string) (ans []int) {
last := [26]int{}
for i, c := range s {
last[c-'a'] = i
}
var mx, j int
for i, c := range s {
mx = max(mx, last[c-'a'])
if mx == i {
ans = append(ans, i-j+1)
j = i + 1
}
}
return
}
# Accepted solution for LeetCode #763: Partition Labels
class Solution:
def partitionLabels(self, s: str) -> List[int]:
last = {c: i for i, c in enumerate(s)}
mx = j = 0
ans = []
for i, c in enumerate(s):
mx = max(mx, last[c])
if mx == i:
ans.append(i - j + 1)
j = i + 1
return ans
// Accepted solution for LeetCode #763: Partition Labels
impl Solution {
pub fn partition_labels(s: String) -> Vec<i32> {
let n = s.len();
let bytes = s.as_bytes();
let mut last = [0; 26];
for i in 0..n {
last[(bytes[i] - b'a') as usize] = i;
}
let mut ans = vec![];
let mut j = 0;
let mut mx = 0;
for i in 0..n {
mx = mx.max(last[(bytes[i] - b'a') as usize]);
if mx == i {
ans.push((i - j + 1) as i32);
j = i + 1;
}
}
ans
}
}
// Accepted solution for LeetCode #763: Partition Labels
function partitionLabels(s: string): number[] {
const last: number[] = Array(26).fill(0);
const idx = (c: string) => c.charCodeAt(0) - 'a'.charCodeAt(0);
const n = s.length;
for (let i = 0; i < n; ++i) {
last[idx(s[i])] = i;
}
const ans: number[] = [];
for (let i = 0, j = 0, mx = 0; i < n; ++i) {
mx = Math.max(mx, last[idx(s[i])]);
if (mx === i) {
ans.push(i - j + 1);
j = i + 1;
}
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair of elements. The outer loop picks one element, the inner loop scans the rest. For n elements that is n × (n−1)/2 comparisons = O(n²). No extra memory — just two loop variables.
Each pointer traverses the array at most once. With two pointers moving inward (or both moving right), the total number of steps is bounded by n. Each comparison is O(1), giving O(n) overall. No auxiliary data structures are needed — just two index variables.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Advancing both pointers shrinks the search space too aggressively and skips candidates.
Usually fails on: A valid pair can be skipped when only one side should move.
Fix: Move exactly one pointer per decision branch based on invariant.
Wrong move: Locally optimal choices may fail globally.
Usually fails on: Counterexamples appear on crafted input orderings.
Fix: Verify with exchange argument or monotonic objective before committing.