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 consisting of the characters 'a', 'b', and 'c' and a non-negative integer k. Each minute, you may take either the leftmost character of s, or the rightmost character of s.
Return the minimum number of minutes needed for you to take at least k of each character, or return -1 if it is not possible to take k of each character.
Example 1:
Input: s = "aabaaaacaabc", k = 2 Output: 8 Explanation: Take three characters from the left of s. You now have two 'a' characters, and one 'b' character. Take five characters from the right of s. You now have four 'a' characters, two 'b' characters, and two 'c' characters. A total of 3 + 5 = 8 minutes is needed. It can be proven that 8 is the minimum number of minutes needed.
Example 2:
Input: s = "a", k = 1 Output: -1 Explanation: It is not possible to take one 'b' or 'c' so return -1.
Constraints:
1 <= s.length <= 105s consists of only the letters 'a', 'b', and 'c'.0 <= k <= s.lengthProblem summary: You are given a string s consisting of the characters 'a', 'b', and 'c' and a non-negative integer k. Each minute, you may take either the leftmost character of s, or the rightmost character of s. Return the minimum number of minutes needed for you to take at least k of each character, or return -1 if it is not possible to take k of each character.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Sliding Window
"aabaaaacaabc" 2
"a" 1
merge-sorted-array)reorder-list)defuse-the-bomb)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2516: Take K of Each Character From Left and Right
class Solution {
public int takeCharacters(String s, int k) {
int[] cnt = new int[3];
int n = s.length();
for (int i = 0; i < n; ++i) {
++cnt[s.charAt(i) - 'a'];
}
for (int x : cnt) {
if (x < k) {
return -1;
}
}
int mx = 0, j = 0;
for (int i = 0; i < n; ++i) {
int c = s.charAt(i) - 'a';
--cnt[c];
while (cnt[c] < k) {
++cnt[s.charAt(j++) - 'a'];
}
mx = Math.max(mx, i - j + 1);
}
return n - mx;
}
}
// Accepted solution for LeetCode #2516: Take K of Each Character From Left and Right
func takeCharacters(s string, k int) int {
cnt := [3]int{}
for _, c := range s {
cnt[c-'a']++
}
for _, x := range cnt {
if x < k {
return -1
}
}
mx, j := 0, 0
for i, c := range s {
c -= 'a'
for cnt[c]--; cnt[c] < k; j++ {
cnt[s[j]-'a']++
}
mx = max(mx, i-j+1)
}
return len(s) - mx
}
# Accepted solution for LeetCode #2516: Take K of Each Character From Left and Right
class Solution:
def takeCharacters(self, s: str, k: int) -> int:
cnt = Counter(s)
if any(cnt[c] < k for c in "abc"):
return -1
mx = j = 0
for i, c in enumerate(s):
cnt[c] -= 1
while cnt[c] < k:
cnt[s[j]] += 1
j += 1
mx = max(mx, i - j + 1)
return len(s) - mx
// Accepted solution for LeetCode #2516: Take K of Each Character From Left and Right
use std::collections::HashMap;
impl Solution {
pub fn take_characters(s: String, k: i32) -> i32 {
let mut cnt: HashMap<char, i32> = HashMap::new();
for c in s.chars() {
*cnt.entry(c).or_insert(0) += 1;
}
if "abc".chars().any(|c| cnt.get(&c).unwrap_or(&0) < &k) {
return -1;
}
let mut mx = 0;
let mut j = 0;
let mut cs = s.chars().collect::<Vec<char>>();
for i in 0..cs.len() {
let c = cs[i];
*cnt.get_mut(&c).unwrap() -= 1;
while cnt.get(&c).unwrap() < &k {
*cnt.get_mut(&cs[j]).unwrap() += 1;
j += 1;
}
mx = mx.max(i - j + 1);
}
(cs.len() as i32) - (mx as i32)
}
}
// Accepted solution for LeetCode #2516: Take K of Each Character From Left and Right
function takeCharacters(s: string, k: number): number {
const idx = (c: string) => c.charCodeAt(0) - 97;
const cnt: number[] = Array(3).fill(0);
for (const c of s) {
++cnt[idx(c)];
}
if (cnt.some(v => v < k)) {
return -1;
}
const n = s.length;
let [mx, j] = [0, 0];
for (let i = 0; i < n; ++i) {
const c = idx(s[i]);
--cnt[c];
while (cnt[c] < k) {
++cnt[idx(s[j++])];
}
mx = Math.max(mx, i - j + 1);
}
return n - mx;
}
Use this to step through a reusable interview workflow for this problem.
For each starting index, scan the next k elements to compute the window aggregate. There are n−k+1 starting positions, each requiring O(k) work, giving O(n × k) total. No extra space since we recompute from scratch each time.
The window expands and contracts as we scan left to right. Each element enters the window at most once and leaves at most once, giving 2n total operations = O(n). Space depends on what we track inside the window (a hash map of at most k distinct elements, or O(1) for a fixed-size window).
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: Using `if` instead of `while` leaves the window invalid for multiple iterations.
Usually fails on: Over-limit windows stay invalid and produce wrong lengths/counts.
Fix: Shrink in a `while` loop until the invariant is valid again.