#2030
Hard Algorithms Smallest k length subsequence with occurrences of a letter
String Stack Greedy Monotonic Stack
39.7% acceptance
Mar 1, 2026
512
15
You are given a string s, an integer k, a letter letter, and an integer repetition.
Return the lexicographically smallest subsequence of s of length k that has letter appear at least repetition times.
Solution
Rust
Time O(n²)
Space O(n)
impl Solution {
pub fn smallest_subsequence(s: String, k: i32, letter: char, repetition: i32) -> String {
let k = k as usize;
let rep = repetition as usize;
let letter = letter as u8;
let s = s.as_bytes();
let n = s.len();
let total_letter = s.iter().filter(|&&c| c == letter).count();
let mut stack: Vec<u8> = Vec::new();
let mut letter_count = 0usize; // letters in stack
let mut remaining_letter = total_letter; // letters in s[i..]
for i in 0..n {
let c = s[i];
let remaining = n - i; // chars left including current
// Pop from stack if: current is smaller, we still have enough chars, and letter constraint holds.
while !stack.is_empty() {
let top = *stack.last().unwrap();
if top <= c { break; }
let stack_len = stack.len();
// After pop, need (k - (stack_len-1)) chars from remaining (including current).
if remaining < k - (stack_len - 1) { break; }
// Letter constraint after pop.
let new_letter_count = if top == letter { letter_count - 1 } else { letter_count };
if new_letter_count + remaining_letter < rep { break; }
if top == letter { letter_count -= 1; }
stack.pop();
}
if stack.len() < k {
if c == letter {
stack.push(c);
letter_count += 1;
} else {
// Only push if remaining spots can still be filled with enough letters.
// After this push: spots_remaining = k - stack.len() - 1
// Available letters from s[i+1..] = remaining_letter (c != letter, unchanged).
let spots_remaining = k - stack.len() - 1;
if letter_count + remaining_letter.min(spots_remaining) >= rep {
stack.push(c);
}
}
}
if c == letter {
remaining_letter -= 1;
}
}
String::from_utf8(stack[..k].to_vec()).unwrap()
}
}