Skip to content

Commit 795809b

Browse files
committed
Add problem 3160: Find the Number of Distinct Colors Among the Balls
1 parent 24c1119 commit 795809b

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,6 +2113,7 @@ pub mod problem_3152_special_array_ii;
21132113
pub mod problem_3153_sum_of_digit_differences_of_all_pairs;
21142114
pub mod problem_3158_find_the_xor_of_numbers_which_appear_twice;
21152115
pub mod problem_3159_find_occurrences_of_an_element_in_an_array;
2116+
pub mod problem_3160_find_the_number_of_distinct_colors_among_the_balls;
21162117
pub mod problem_3350_adjacent_increasing_subarrays_detection_ii;
21172118

21182119
#[cfg(test)]
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
pub struct Solution;
2+
3+
// ------------------------------------------------------ snip ------------------------------------------------------ //
4+
5+
use std::collections::HashMap;
6+
use std::collections::hash_map::Entry;
7+
use std::mem;
8+
9+
impl Solution {
10+
fn helper(queries: Vec<Vec<i32>>, mut set_color: impl FnMut(i32, i32) -> i32) -> Vec<i32> {
11+
let mut color_counts = HashMap::new();
12+
13+
queries
14+
.into_iter()
15+
.map(|query| {
16+
let [index, color] = query.try_into().ok().unwrap();
17+
let old_color = set_color(index, color);
18+
19+
if color != old_color {
20+
if let Entry::Occupied(entry) = color_counts.entry(old_color) {
21+
if *entry.get() == 0 {
22+
entry.remove();
23+
} else {
24+
*entry.into_mut() -= 1;
25+
}
26+
}
27+
28+
match color_counts.entry(color) {
29+
Entry::Occupied(occupied_entry) => *occupied_entry.into_mut() += 1,
30+
Entry::Vacant(vacant_entry) => {
31+
vacant_entry.insert(0);
32+
}
33+
}
34+
}
35+
36+
color_counts.len() as _
37+
})
38+
.collect()
39+
}
40+
41+
pub fn query_results(limit: i32, queries: Vec<Vec<i32>>) -> Vec<i32> {
42+
let limit = limit.cast_unsigned() as usize;
43+
44+
if limit < queries.len() {
45+
let mut colors = vec![0; limit + 1].into_boxed_slice();
46+
47+
Self::helper(queries, |index, color| {
48+
mem::replace(&mut colors[index.cast_unsigned() as usize], color)
49+
})
50+
} else {
51+
let mut colors = HashMap::new();
52+
53+
Self::helper(queries, |index, color| colors.insert(index, color).unwrap_or(0))
54+
}
55+
}
56+
}
57+
58+
// ------------------------------------------------------ snip ------------------------------------------------------ //
59+
60+
impl super::Solution for Solution {
61+
fn query_results(limit: i32, queries: Vec<Vec<i32>>) -> Vec<i32> {
62+
Self::query_results(limit, queries)
63+
}
64+
}
65+
66+
#[cfg(test)]
67+
mod tests {
68+
#[test]
69+
fn test_solution() {
70+
super::super::tests::run::<super::Solution>();
71+
}
72+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
pub mod hash_map;
2+
3+
pub trait Solution {
4+
fn query_results(limit: i32, queries: Vec<Vec<i32>>) -> Vec<i32>;
5+
}
6+
7+
#[cfg(test)]
8+
mod tests {
9+
use super::Solution;
10+
11+
pub fn run<S: Solution>() {
12+
let test_cases = [
13+
((4, &[[1, 4], [2, 5], [1, 3], [3, 4]] as &[_]), &[1, 2, 2, 3] as &[_]),
14+
((4, &[[0, 1], [1, 2], [2, 2], [3, 4], [4, 5]]), &[1, 2, 2, 3, 4]),
15+
];
16+
17+
for ((limit, queries), expected) in test_cases {
18+
assert_eq!(
19+
S::query_results(limit, queries.iter().map(Vec::from).collect()),
20+
expected
21+
);
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)