1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
use std::collections::{HashMap, HashSet, VecDeque};
pub struct Marker {
data: VecDeque<char>,
map: HashMap<char, usize>,
size: usize,
count: usize,
}
impl Marker {
pub fn new(size: usize) -> Self {
Marker {
data: VecDeque::new(),
map: HashMap::new(),
size,
count: 0,
}
}
fn push_insert(&mut self, c: char) {
self.data.push_back(c);
if let Some(count) = self.map.get_mut(&c) {
*count += 1;
} else {
self.map.insert(c, 1);
}
self.count += 1;
}
/// Pushes the character into the marker. Returns `Some(true)` for when there is a duplicate. `None`
/// for when the marker hasn't been filled yet. `Some(false)` for when it is filled and there
/// isn't a duplicate
///
/// For runtime this method on each character costs: `O(hash(c))` since the operations done are
/// `O(1)` for insert into linked list, removal from linked list, grabbing from hashmap,
/// removing from hashmap, inserting into hashmap.
pub fn push(&mut self, c: char) -> Option<bool> {
// println!(
// "c = {} --> {:?} : {:?} : {}",
// c, self.data, self.map, self.count
// );
if self.data.len() < self.size {
self.push_insert(c);
return None;
}
if let Some(old) = self.data.pop_front() {
let mut should_remove = false;
if let Some(count) = self.map.get_mut(&old) {
if *count - 1 == 0 {
should_remove = true;
}
*count -= 1;
self.count -= 1;
}
if should_remove {
self.map.remove(&old);
}
}
self.push_insert(c);
Some(self.map.len() == self.count)
}
}