diff --git a/src/problem/mod.rs b/src/problem/mod.rs index 93599e8..960d5c8 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -491,4 +491,132 @@ mod p1706_where_will_the_ball_fall; mod p1299_replace_elements_with_greatest_element_on_right_side; +mod p2080_range_frequency_queries; + +mod p624_maximum_distance_in_arrays; + +mod p2595_number_of_even_and_odd_bits; + +mod p2209_minimum_white_tiles_after_covering_with_carpets; + +mod p2506_count_pairs_of_similar_strings; + +mod p1206_design_skiplist; + +mod p1656_design_an_ordered_stream; + +mod p2502_design_memory_allocator; + +mod p1472_design_browser_history; + +mod p2353_design_a_food_rating_system; + +mod p131_palindrome_partitioning; + +mod p132_palindrome_partitioning_ii; + +mod p1278_palindrome_partitioning_iii; + +mod p1745_palindrome_partitioning_iv; + +mod p1328_break_a_palindrome; + +mod p2588_count_the_number_of_beautiful_subarrays; + +mod p2597_the_number_of_beautiful_subsets; + +mod p2234_maximum_total_beauty_of_the_gardens; + +mod p2070_most_beautiful_item_for_each_query; + +mod p2269_find_the_k_beauty_of_a_number; + +mod p2012_sum_of_beauty_in_the_array; + +mod p3305_count_of_substrings_containing_every_vowel_and_k_consonants_i; + +mod p3306_count_of_substrings_containing_every_vowel_and_k_consonants_ii; + +mod p3340_check_balanced_string; + +mod p3110_score_of_a_string; + +mod p2272_substring_with_largest_variance; + +mod p1963_minimum_number_of_swaps_to_make_the_string_balanced; + +mod p2614_prime_in_diagonal; + +mod p2610_convert_an_array_into_a_2d_array_with_conditions; + +mod p2612_minimum_reverse_operations; + +mod p2680_maximum_or; + +mod p2643_row_with_maximum_ones; + +mod p2116_check_if_a_parentheses_string_can_be_valid; + +mod p2255_count_prefixes_of_a_given_string; + +mod p2711_difference_of_number_of_distinct_values_on_diagonals; + +mod p2829_determine_the_minimum_sum_of_a_k_avoiding_array; + +mod p2712_minimum_cost_to_make_all_characters_equal; + +mod p2716_minimize_string_length; + +mod p2360_longest_cycle_in_a_graph; + +mod p2109_adding_spaces_to_a_string; + +mod p2278_percentage_of_letter_in_string; + +mod p2140_solving_questions_with_brainpower; + +mod p2873_maximum_value_of_an_ordered_triplet_i; + +mod p2874_maximum_value_of_an_ordered_triplet_ii; + +mod p1123_lowest_common_ancestor_of_deepest_leaves; + +mod p1863_sum_of_all_subset_xor_totals; + +mod p368_largest_divisible_subset; + +mod p416_partition_equal_subset_sum; + +mod p3396_minimum_number_of_operations_to_make_elements_in_array_distinct; + +mod p2999_count_the_number_of_powerful_integers; +mod p3375_minimum_operations_to_make_array_values_equal_to_k; + +mod p2843_count_symmetric_integers; + +mod p3272_find_the_count_of_good_integers; + +mod p1922_count_good_numbers; + +mod p1534_count_good_triplets; + +mod p2179_count_good_triplets_in_an_array; + +mod p2537_count_the_number_of_good_subarrays; + +mod p2176_count_equal_and_divisible_pairs_in_an_array; + +mod p2364_count_number_of_bad_pairs; + +mod p2563_count_the_number_of_fair_pairs; + +mod p781_rabbits_in_forest; + +mod p2145_count_the_hidden_sequences; + +mod p1399_count_largest_group; +mod p2338_count_the_number_of_ideal_arrays; + +mod p2845_count_of_interesting_subarrays; + mod p1287_element_appearing_more_than_25_in_sorted_array; \ No newline at end of file diff --git a/src/problem/p1123_lowest_common_ancestor_of_deepest_leaves.rs b/src/problem/p1123_lowest_common_ancestor_of_deepest_leaves.rs new file mode 100644 index 0000000..17d2921 --- /dev/null +++ b/src/problem/p1123_lowest_common_ancestor_of_deepest_leaves.rs @@ -0,0 +1,98 @@ +/** + * [1123] Lowest Common Ancestor of Deepest Leaves + */ +pub struct Solution {} + +use crate::util::tree::{to_tree, TreeNode}; + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::cell::RefCell; +use std::cmp::Ordering; +use std::rc::Rc; + +impl Solution { + pub fn lca_deepest_leaves( + root: Option>>, + ) -> Option>> { + if let Some(root) = root { + Self::search(&root).1 + } else { + None + } + } + + // (子树的深度,lca) + fn search(node: &Rc>) -> (i32, Option>>) { + let (left_deep, left_lca) = if let Some(left) = node.borrow().left.as_ref() { + Self::search(left) + } else { + (0, None) + }; + + let (right_deep, right_lca) = if let Some(right) = node.borrow().right.as_ref() { + Self::search(right) + } else { + (0, None) + }; + + match left_deep.cmp(&right_deep) { + Ordering::Greater => (left_deep + 1, left_lca), + Ordering::Less => (right_deep + 1, right_lca), + Ordering::Equal => (left_deep + 1, Some(node.clone())), + } + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1123() { + let node = Solution::lca_deepest_leaves(to_tree(vec![ + Some(3), + Some(5), + Some(1), + Some(6), + Some(2), + Some(0), + Some(8), + None, + None, + Some(7), + Some(4), + ])); + + assert_eq!(to_tree(vec![Some(2), Some(7), Some(4)]), node); + + assert_eq!( + to_tree(vec![Some(1)]), + Solution::lca_deepest_leaves(to_tree(vec![Some(1)])) + ); + assert_eq!( + to_tree(vec![Some(2)]), + Solution::lca_deepest_leaves(to_tree(vec![Some(0), Some(1), Some(3), None, Some(2)])) + ); + } +} diff --git a/src/problem/p1206_design_skiplist.rs b/src/problem/p1206_design_skiplist.rs new file mode 100644 index 0000000..ff35cf4 --- /dev/null +++ b/src/problem/p1206_design_skiplist.rs @@ -0,0 +1,189 @@ +/** + * [1206] Design Skiplist + */ +pub struct Solution {} + +// submission codes start here +use rand::Rng; +use std::cell::RefCell; +use std::rc::Rc; + +struct SkiplistNode { + right: Option>>, + down: Option>>, + value: i32, +} + +type NodeCell = Rc>; + +struct Skiplist { + head: Rc>, + random_engine: rand::rngs::ThreadRng, +} + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl Skiplist { + fn create_node(value: i32) -> NodeCell { + Rc::new(RefCell::new(SkiplistNode { + right: None, + down: None, + value, + })) + } + + fn new() -> Self { + Self { + head: Self::create_node(-1), + random_engine: rand::thread_rng(), + } + } + + fn search(&self, target: i32) -> bool { + let mut node = Some(self.head.clone()); + let mut queue = vec![]; + + while let Some(real_node) = node { + node = if real_node + .borrow() + .right + .clone() + .filter(|x| x.borrow().value <= target) + .is_some() + { + real_node.borrow().right.clone() + } else { + queue.push(real_node.clone()); + real_node.borrow().down.clone() + }; + } + + queue + .last() + .filter(|x| x.borrow().value == target) + .is_some() + } + + fn add(&mut self, num: i32) { + let mut path = vec![]; + let mut node = Some(self.head.clone()); + + // 找链表中所有小于num的节点 + while let Some(real_node) = node { + node = if real_node + .borrow() + .right + .as_ref() + .filter(|x| x.borrow().value <= num) + .is_some() + { + real_node.borrow().right.clone() + } else { + path.push(real_node.clone()); + real_node.borrow().down.as_ref().map(|x| x.clone()) + }; + } + + let mut insert = true; + let mut down_node = None; + + while insert && !path.is_empty() { + if let Some(insert_node) = path.pop() { + // 添加新的节点 + let right_node = insert_node.borrow_mut().right.take(); + insert_node.borrow_mut().right = Some(Rc::new(RefCell::new(SkiplistNode { + right: right_node, + down: down_node.take(), + value: num, + }))); + + down_node = insert_node.borrow().right.as_ref().map(|x| x.clone()); + // 50%的概率决定是否添加下一级索引 + insert = self.random_engine.gen_bool(0.5); + } else { + break; + } + } + + // 新增头结点 + // 这里新增一层 + if insert { + let node = Skiplist::create_node(-1); + node.borrow_mut().down = Some(self.head.clone()); + self.head = node; + } + } + + fn erase(&self, num: i32) -> bool { + let mut deleted = false; + let mut node = Some(self.head.clone()); + + while let Some(mut real_node) = node { + node = if real_node + .borrow() + .right + .as_ref() + .filter(|x| x.borrow().value < num) + .is_some() + { + real_node.borrow().right.clone() + } else { + real_node.borrow().down.clone() + }; + + if real_node + .borrow() + .right + .as_ref() + .filter(|x| x.borrow().value == num) + .is_some() + { + deleted = true; + let right = real_node + .borrow_mut() + .right + .as_ref() + .unwrap() + .borrow() + .right + .as_ref() + .map(|x| x.clone()); + real_node.borrow_mut().right = right; + } + } + + deleted + } +} + +/** + * Your Skiplist object will be instantiated and called as such: + * let obj = Skiplist::new(); + * let ret_1: bool = obj.search(target); + * obj.add(num); + * let ret_3: bool = obj.erase(num); + */ + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1206() { + let mut list = Skiplist::new(); + + list.add(1); + list.add(2); + list.add(3); + assert!(!list.search(0)); + list.add(4); + assert!(list.search(1)); + assert!(!list.erase(0)); + assert!(list.erase(1)); + assert!(!list.search(1)); + } +} diff --git a/src/problem/p1278_palindrome_partitioning_iii.rs b/src/problem/p1278_palindrome_partitioning_iii.rs new file mode 100644 index 0000000..acf7ada --- /dev/null +++ b/src/problem/p1278_palindrome_partitioning_iii.rs @@ -0,0 +1,60 @@ +/** + * [1278] Palindrome Partitioning III + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn palindrome_partition(s: String, k: i32) -> i32 { + let s: Vec = s.chars().collect(); + let length = s.len(); + + // cost[i][j] + // 将 s[i..=j] 修改为回文串需要的修改次数 + let mut cost = vec![vec![0; length]; length]; + + for span in 2..=length { + for i in 0..=length - span { + let j = i + span - 1; + + cost[i][j] = cost[i + 1][j - 1] + if s[i] == s[j] { 0 } else { 1 }; + } + } + + let k = k as usize; + // dp[i][j] + // 将s[..i]分割为j个回文串需要的修改次数 + let mut dp = vec![vec![i32::MAX; k + 1]; length + 1]; + + for i in 1..=length { + for j in 1..=i.min(k) { + if j == 1 { + dp[i][j] = cost[0][i - 1]; + } else { + // 这里k从j - 1开始枚举是因为前面需要进行j - 1次分割时 + // 字符串的长度必须大于等于j - 1 + for k in j - 1..i { + dp[i][j] = dp[i][j].min(dp[k][j - 1] + cost[k][i - 1]); + } + } + } + } + + dp[length][k] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1278() { + assert_eq!(1, Solution::palindrome_partition("abc".to_owned(), 2)); + assert_eq!(0, Solution::palindrome_partition("aabbc".to_owned(), 3)); + assert_eq!(0, Solution::palindrome_partition("leetcode".to_owned(), 8)); + } +} diff --git a/src/problem/p131_palindrome_partitioning.rs b/src/problem/p131_palindrome_partitioning.rs new file mode 100644 index 0000000..d782026 --- /dev/null +++ b/src/problem/p131_palindrome_partitioning.rs @@ -0,0 +1,63 @@ +/** + * [131] Palindrome Partitioning + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn partition(s: String) -> Vec> { + let s: Vec = s.chars().collect(); + let length = s.len(); + + let mut result = vec![]; + let mut current: Vec = vec![]; + let mut dp = vec![vec![true; length]; length]; + + for i in (0..length).rev() { + for j in i + 1..length { + dp[i][j] = (s[i] == s[j]) && dp[i + 1][j - 1]; + } + } + + Self::dfs(&s, 0, &mut dp, &mut current, &mut result); + + result + } + + fn dfs( + s: &Vec, + pos: usize, + dp: &mut Vec>, + current: &mut Vec, + result: &mut Vec>, + ) { + if pos >= s.len() { + result.push(current.clone()); + return; + } + + for i in pos..s.len() { + if dp[pos][i] { + current.push(s[pos..i + 1].iter().collect()); + Self::dfs(s, i + 1, dp, current, result); + current.pop(); + } + } + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_131() { + assert_eq!( + vec![vec_string!("a", "a", "b"), vec_string!("aa", "b")], + Solution::partition("aab".to_owned()) + ); + } +} diff --git a/src/problem/p1328_break_a_palindrome.rs b/src/problem/p1328_break_a_palindrome.rs new file mode 100644 index 0000000..f78f3a6 --- /dev/null +++ b/src/problem/p1328_break_a_palindrome.rs @@ -0,0 +1,50 @@ +/** + * [1328] Break a Palindrome + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn break_palindrome(palindrome: String) -> String { + if palindrome.len() == 1 { + return "".to_owned(); + } + + let mut s: Vec = palindrome.chars().collect(); + + let mut flag = false; + for i in 0..s.len() / 2 { + if s[i] != 'a' { + s[i] = 'a'; + flag = true; + break; + } + } + + // 说明s的前半段全部都是a + // 直接把最后一个字符改成b + if !flag { + let pos = s.len() - 1; + s[pos] = 'b'; + } + + s.into_iter().collect() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1328() { + assert_eq!("aabab", Solution::break_palindrome("aabaa".to_owned())); + assert_eq!("ab", Solution::break_palindrome("aa".to_owned())); + assert_eq!("ab", Solution::break_palindrome("bb".to_owned())); + assert_eq!("aaccba", Solution::break_palindrome("abccba".to_owned())); + assert_eq!("", Solution::break_palindrome("a".to_owned())); + } +} diff --git a/src/problem/p132_palindrome_partitioning_ii.rs b/src/problem/p132_palindrome_partitioning_ii.rs new file mode 100644 index 0000000..1e7ba50 --- /dev/null +++ b/src/problem/p132_palindrome_partitioning_ii.rs @@ -0,0 +1,51 @@ +/** + * [132] Palindrome Partitioning II + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn min_cut(s: String) -> i32 { + let s: Vec = s.chars().collect(); + let length = s.len(); + + let mut palindorme = vec![vec![true; length]; length]; + + for i in (0..length).rev() { + for j in i + 1..length { + palindorme[i][j] = (s[i] == s[j]) && palindorme[i + 1][j - 1] + } + } + + let mut dp = vec![i32::MAX; length]; + + for i in 0..length { + if palindorme[0][i] { + dp[i] = 0; + } else { + for j in 0..i { + if palindorme[j + 1][i] { + dp[i] = dp[i].min(dp[j] + 1); + } + } + } + } + + dp[length - 1] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_132() { + assert_eq!(1, Solution::min_cut("aab".to_owned())); + assert_eq!(0, Solution::min_cut("a".to_owned())); + assert_eq!(1, Solution::min_cut("ab".to_owned())); + } +} diff --git a/src/problem/p1399_count_largest_group.rs b/src/problem/p1399_count_largest_group.rs new file mode 100644 index 0000000..d5e5573 --- /dev/null +++ b/src/problem/p1399_count_largest_group.rs @@ -0,0 +1,49 @@ +/** + * [1399] Count Largest Group + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn count_largest_group(n: i32) -> i32 { + let mut map = HashMap::new(); + (1..=n) + .into_iter() + .map(|mut x| { + let mut result = 0; + + while x > 0 { + result += x % 10; + x = x / 10; + } + + result + }) + .fold(&mut map, |map, i| { + let entry = map.entry(i).or_insert(0); + *entry += 1; + + map + }); + + let max_count = map.values().max().unwrap(); + map.values().filter(|x| x == &max_count).count() as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1399() { + assert_eq!(4, Solution::count_largest_group(13)); + assert_eq!(2, Solution::count_largest_group(2)); + assert_eq!(6, Solution::count_largest_group(15)); + assert_eq!(5, Solution::count_largest_group(24)); + } +} diff --git a/src/problem/p1472_design_browser_history.rs b/src/problem/p1472_design_browser_history.rs new file mode 100644 index 0000000..b8d09a5 --- /dev/null +++ b/src/problem/p1472_design_browser_history.rs @@ -0,0 +1,87 @@ +/** + * [1472] Design Browser History + */ +pub struct Solution {} + +// submission codes start here + +struct BrowserHistory { + history: Vec, + pos: usize, +} + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl BrowserHistory { + fn new(homepage: String) -> Self { + Self { + history: vec![homepage], + pos: 0, + } + } + + fn visit(&mut self, url: String) { + // 删除前向的所有网站 + for _ in self.pos + 1..self.history.len() { + self.history.pop(); + } + + self.history.push(url); + self.pos += 1; + } + + fn back(&mut self, steps: i32) -> String { + let steps = steps as usize; + if steps > self.pos { + self.pos = 0; + } else { + self.pos -= steps; + } + + self.history[self.pos].clone() + } + + fn forward(&mut self, steps: i32) -> String { + let steps = steps as usize; + if steps + self.pos >= self.history.len() { + self.pos = self.history.len() - 1; + } else { + self.pos += steps; + } + + self.history[self.pos].clone() + } +} + +/** + * Your BrowserHistory object will be instantiated and called as such: + * let obj = BrowserHistory::new(homepage); + * obj.visit(url); + * let ret_2: String = obj.back(steps); + * let ret_3: String = obj.forward(steps); + */ + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1472() { + let mut history = BrowserHistory::new("leetcode.com".to_owned()); + + history.visit("google.com".to_owned()); + history.visit("facebook.com".to_owned()); + history.visit("youtube.com".to_owned()); + assert_eq!("facebook.com", history.back(1)); + assert_eq!("google.com", history.back(1)); + assert_eq!("facebook.com", history.forward(1)); + history.visit("linkedin.com".to_owned()); + assert_eq!("linkedin.com", history.forward(2)); + assert_eq!("google.com", history.back(2)); + assert_eq!("leetcode.com", history.back(7)); + } +} diff --git a/src/problem/p1534_count_good_triplets.rs b/src/problem/p1534_count_good_triplets.rs new file mode 100644 index 0000000..2d02d72 --- /dev/null +++ b/src/problem/p1534_count_good_triplets.rs @@ -0,0 +1,54 @@ +/** + * [1534] Count Good Triplets + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn count_good_triplets(arr: Vec, a: i32, b: i32, c: i32) -> i32 { + let mut result = 0; + let (a, b, c) = (a as u32, b as u32, c as u32); + + for i in 0..arr.len() { + for j in i + 1..arr.len() { + for k in j + 1..arr.len() { + if arr[i].abs_diff(arr[j]) > a { + continue; + } + + if arr[j].abs_diff(arr[k]) > b { + continue; + } + + if arr[i].abs_diff(arr[k]) > c { + continue; + } + + result += 1; + } + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1534() { + assert_eq!( + 4, + Solution::count_good_triplets(vec![3, 0, 1, 1, 9, 7], 7, 2, 3) + ); + assert_eq!( + 0, + Solution::count_good_triplets(vec![1, 1, 2, 2, 3], 0, 0, 1) + ); + } +} diff --git a/src/problem/p1656_design_an_ordered_stream.rs b/src/problem/p1656_design_an_ordered_stream.rs new file mode 100644 index 0000000..8b0c350 --- /dev/null +++ b/src/problem/p1656_design_an_ordered_stream.rs @@ -0,0 +1,71 @@ +/** + * [1656] Design an Ordered Stream + */ +pub struct Solution {} + +// submission codes start here + +struct OrderedStream { + array: Vec>, + pointer: usize, +} + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl OrderedStream { + fn new(n: i32) -> Self { + let n = n as usize; + + Self { + array: vec![None; n], + pointer: 1, + } + } + + fn insert(&mut self, id_key: i32, value: String) -> Vec { + let id = id_key as usize - 1; + + self.array[id] = Some(value); + + let mut result = vec![]; + let mut pointer = self.pointer; + + while pointer <= self.array.len() { + if let Some(item) = &self.array[pointer - 1] { + result.push(item.clone()); + pointer += 1; + } else { + break; + } + } + self.pointer = pointer; + + result + } +} + +/** + * Your OrderedStream object will be instantiated and called as such: + * let obj = OrderedStream::new(n); + * let ret_1: Vec = obj.insert(idKey, value); + */ + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1656() { + let mut stream = OrderedStream::new(5); + + assert_eq!(Vec::<&str>::new(), stream.insert(3, "ccccc".to_owned())); + assert_eq!(vec!["aaaaa"], stream.insert(1, "aaaaa".to_owned())); + assert_eq!(vec!["bbbbb", "ccccc"], stream.insert(2, "bbbbb".to_owned())); + assert_eq!(Vec::<&str>::new(), stream.insert(5, "eeeee".to_owned())); + assert_eq!(vec!["ddddd", "eeeee"], stream.insert(4, "ddddd".to_owned())); + } +} diff --git a/src/problem/p1745_palindrome_partitioning_iv.rs b/src/problem/p1745_palindrome_partitioning_iv.rs new file mode 100644 index 0000000..c2abb55 --- /dev/null +++ b/src/problem/p1745_palindrome_partitioning_iv.rs @@ -0,0 +1,46 @@ +/** + * [1745] Palindrome Partitioning IV + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn check_partitioning(s: String) -> bool { + let s = s.as_bytes(); + let length = s.len(); + + let mut palindrome = vec![vec![true; length]; length]; + + for span in 2..=length { + for i in 0..=length - span { + let j = i + span - 1; + palindrome[i][j] = palindrome[i + 1][j - 1] && (s[i] == s[j]) + } + } + + for i in 0..length - 2 { + // 所有字符串都必须是非空的 + for j in i + 2..length { + if palindrome[0][i] && palindrome[i + 1][j - 1] && palindrome[j][length - 1] { + return true; + } + } + } + + false + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1745() { + assert!(Solution::check_partitioning("abcbdd".to_owned())); + assert!(!Solution::check_partitioning("bcbddxy".to_owned())); + } +} diff --git a/src/problem/p1863_sum_of_all_subset_xor_totals.rs b/src/problem/p1863_sum_of_all_subset_xor_totals.rs new file mode 100644 index 0000000..cae7070 --- /dev/null +++ b/src/problem/p1863_sum_of_all_subset_xor_totals.rs @@ -0,0 +1,43 @@ +/** + * [1863] Sum of All Subset XOR Totals + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn subset_xor_sum(nums: Vec) -> i32 { + let mut result = 0; + + Self::search(0, 0, &nums, &mut result); + + result + } + + fn search(mut sum: i32, i: usize, nums: &Vec, result: &mut i32) { + if i == nums.len() { + return; + } + + // 不选择i + Self::search(sum, i + 1, nums, result); + // 选择i + sum = sum ^ nums[i]; + *result += sum; + Self::search(sum, i + 1, nums, result); + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1863() { + assert_eq!(6, Solution::subset_xor_sum(vec![1, 3])); + assert_eq!(28, Solution::subset_xor_sum(vec![5, 1, 6])); + assert_eq!(480, Solution::subset_xor_sum(vec![3, 4, 5, 6, 7, 8])); + } +} diff --git a/src/problem/p1922_count_good_numbers.rs b/src/problem/p1922_count_good_numbers.rs new file mode 100644 index 0000000..b629939 --- /dev/null +++ b/src/problem/p1922_count_good_numbers.rs @@ -0,0 +1,49 @@ +/** + * [1922] Count Good Numbers + */ +pub struct Solution {} + +// submission codes start here + +const MOD: i64 = 1_000_000_000 + 7; + +impl Solution { + pub fn count_good_numbers(n: i64) -> i32 { + let mut result = Self::quick_power(20, n / 2); + + if n % 2 == 1 { + result = result * 5 % MOD; + } + + result as i32 + } + + fn quick_power(mut m: i64, mut n: i64) -> i64 { + let mut result = 1; + + while n > 0 { + if n & 1 == 1 { + result = result * m % MOD; + } + + m = m * m % MOD; + n = n >> 1; + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1922() { + assert_eq!(5, Solution::count_good_numbers(1)); + assert_eq!(400, Solution::count_good_numbers(4)); + assert_eq!(564_908_303, Solution::count_good_numbers(50)); + } +} diff --git a/src/problem/p1963_minimum_number_of_swaps_to_make_the_string_balanced.rs b/src/problem/p1963_minimum_number_of_swaps_to_make_the_string_balanced.rs new file mode 100644 index 0000000..e3bc98d --- /dev/null +++ b/src/problem/p1963_minimum_number_of_swaps_to_make_the_string_balanced.rs @@ -0,0 +1,40 @@ +/** + * [1963] Minimum Number of Swaps to Make the String Balanced + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn min_swaps(s: String) -> i32 { + let mut count = 0; + let mut min_count = 0; + + for c in s.chars() { + match c { + '[' => count += 1, + ']' => { + count -= 1; + min_count = min_count.min(count) + } + _ => {} + } + } + + (-min_count + 1) / 2 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1963() { + assert_eq!(1, Solution::min_swaps("][][".to_owned())); + assert_eq!(2, Solution::min_swaps("]]][[[".to_owned())); + assert_eq!(0, Solution::min_swaps("[]".to_owned())); + } +} diff --git a/src/problem/p2012_sum_of_beauty_in_the_array.rs b/src/problem/p2012_sum_of_beauty_in_the_array.rs new file mode 100644 index 0000000..3634a0b --- /dev/null +++ b/src/problem/p2012_sum_of_beauty_in_the_array.rs @@ -0,0 +1,48 @@ +/** + * [2012] Sum of Beauty in the Array + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn sum_of_beauties(nums: Vec) -> i32 { + let n = nums.len(); + let mut prefix = vec![0; n]; + let mut suffix = vec![i32::MAX; n]; + + for i in 0..n { + if i > 0 { + prefix[i] = prefix[i - 1].max(nums[i - 1]); + suffix[n - i - 1] = suffix[n - i].min(nums[n - i]); + } + } + + (1..n - 1) + .into_iter() + .map(|x| { + if nums[x] > prefix[x] && nums[x] < suffix[x] { + 2 + } else if nums[x] > nums[x - 1] && nums[x] < nums[x + 1] { + 1 + } else { + 0 + } + }) + .sum() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2012() { + assert_eq!(1, Solution::sum_of_beauties(vec![2, 4, 6, 4])); + assert_eq!(2, Solution::sum_of_beauties(vec![1, 2, 3])); + assert_eq!(0, Solution::sum_of_beauties(vec![3, 2, 1])); + } +} diff --git a/src/problem/p2070_most_beautiful_item_for_each_query.rs b/src/problem/p2070_most_beautiful_item_for_each_query.rs new file mode 100644 index 0000000..5f4d777 --- /dev/null +++ b/src/problem/p2070_most_beautiful_item_for_each_query.rs @@ -0,0 +1,72 @@ +/** + * [2070] Most Beautiful Item for Each Query + */ +pub struct Solution {} + +// submission codes start here +use std::collections::BTreeMap; + +impl Solution { + pub fn maximum_beauty(items: Vec>, queries: Vec) -> Vec { + let mut price_map = BTreeMap::new(); + + for item in items.iter() { + let entry = price_map.entry(item[0] as usize).or_insert(0); + *entry = (*entry).max(item[1]); + } + + let mut query_map: BTreeMap = BTreeMap::new(); + let mut result = Vec::with_capacity(queries.len()); + + for price in queries { + let price = price as usize; + let (min_price, mut min_result) = match query_map.range(..=price).last() { + Some((&p, &r)) => (p, r), + None => (0, 0), + }; + + if min_price == price { + result.push(min_result); + continue; + } + + for (&p, &r) in price_map.range(min_price + 1..=price) { + min_result = min_result.max(r); + query_map.insert(p, min_result); + } + + result.push(min_result); + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2070() { + assert_eq!( + vec![2, 4, 5, 5, 6, 6], + Solution::maximum_beauty( + vec![vec![1, 2], vec![3, 2], vec![2, 4], vec![5, 6], vec![3, 5]], + vec![1, 2, 3, 4, 5, 6] + ) + ); + assert_eq!( + vec![4], + Solution::maximum_beauty( + vec![vec![1, 2], vec![1, 2], vec![1, 3], vec![1, 4]], + vec![1] + ) + ); + assert_eq!( + vec![0], + Solution::maximum_beauty(vec![vec![10, 1000]], vec![5]) + ); + } +} diff --git a/src/problem/p2080_range_frequency_queries.rs b/src/problem/p2080_range_frequency_queries.rs new file mode 100644 index 0000000..aa32b2a --- /dev/null +++ b/src/problem/p2080_range_frequency_queries.rs @@ -0,0 +1,85 @@ +/** + * [2080] Range Frequency Queries + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +struct RangeFreqQuery { + frequency_map: HashMap>, +} + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl RangeFreqQuery { + fn new(arr: Vec) -> Self { + let mut frequency_map = HashMap::new(); + + for (i, v) in arr.into_iter().enumerate() { + let entry = frequency_map.entry(v).or_insert(vec![]); + entry.push(i); + } + + Self { frequency_map } + } + + fn query(&self, left: i32, right: i32, value: i32) -> i32 { + let (left, right) = (left as usize, right as usize); + + if let Some(index) = self.frequency_map.get(&value) { + let l = index.binary_search(&left); + let r = index.binary_search(&right); + + let result = match l { + Ok(l_ok) => match r { + Ok(r_ok) => r_ok - l_ok + 1, + Err(r_err) => r_err - l_ok, + }, + Err(l_err) => match r { + Ok(r_ok) => r_ok - l_err + 1, + Err(r_err) => r_err - l_err, + }, + }; + + result as i32 + } else { + 0 + } + } +} + +/** + * Your RangeFreqQuery object will be instantiated and called as such: + * let obj = RangeFreqQuery::new(arr); + * let ret_1: i32 = obj.query(left, right, value); + */ + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2080() { + let query = RangeFreqQuery::new(vec![12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]); + + assert_eq!(1, query.query(1, 2, 4)); + assert_eq!(2, query.query(0, 11, 33)); + + let query = RangeFreqQuery::new(vec![2, 2, 1, 2, 2]); + + // [2] + assert_eq!(1, query.query(2, 4, 1)); + assert_eq!(1, query.query(1, 3, 1)); + assert_eq!(1, query.query(0, 2, 1)); + + let query = RangeFreqQuery::new(vec![1, 1, 1, 2, 2]); + + // [0, 1, 2] + assert_eq!(1, query.query(2, 2, 1)); + } +} diff --git a/src/problem/p2109_adding_spaces_to_a_string.rs b/src/problem/p2109_adding_spaces_to_a_string.rs new file mode 100644 index 0000000..1a412e1 --- /dev/null +++ b/src/problem/p2109_adding_spaces_to_a_string.rs @@ -0,0 +1,50 @@ +/** + * [2109] Adding Spaces to a String + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn add_spaces(s: String, spaces: Vec) -> String { + let s: Vec = s.chars().collect(); + let mut result = Vec::with_capacity(s.len() + spaces.len()); + let mut iter = spaces.into_iter().peekable(); + + for (i, v) in s.into_iter().enumerate() { + if let Some(&pos) = iter.peek() { + if i == pos as usize { + iter.next(); + result.push(' '); + } + } + + result.push(v); + } + + result.into_iter().collect() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2109() { + assert_eq!( + "Leetcode Helps Me Learn", + Solution::add_spaces("LeetcodeHelpsMeLearn".to_owned(), vec![8, 13, 15]) + ); + assert_eq!( + "i code in py thon", + Solution::add_spaces("icodeinpython".to_owned(), vec![1, 5, 7, 9]) + ); + assert_eq!( + " s p a c i n g", + Solution::add_spaces("spacing".to_owned(), vec![0, 1, 2, 3, 4, 5, 6]) + ); + } +} diff --git a/src/problem/p2116_check_if_a_parentheses_string_can_be_valid.rs b/src/problem/p2116_check_if_a_parentheses_string_can_be_valid.rs new file mode 100644 index 0000000..69529a7 --- /dev/null +++ b/src/problem/p2116_check_if_a_parentheses_string_can_be_valid.rs @@ -0,0 +1,80 @@ +/** + * [2116] Check if a Parentheses String Can Be Valid + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn can_be_valid(s: String, locked: String) -> bool { + let s: Vec = s.bytes().collect(); + let locked: Vec = locked + .bytes() + .map(|x| if x == b'0' { false } else { true }) + .collect(); + + if s.len() % 2 != 0 { + return false; + } + + let mut locked_left = vec![]; + let mut unlocked_pos = vec![]; + + for (i, &v) in s.iter().enumerate() { + if !locked[i] { + unlocked_pos.push(i); + } else { + if v == b'(' { + locked_left.push(i); + } else { + // 首先使用锁定的左括号匹配 + if locked_left.pop().is_none() { + // 然后使用未锁定的位置修改 + if unlocked_pos.pop().is_none() { + return false; + } + } + } + } + } + + // 判断剩余的未锁定位置和锁定的左括号是否匹配 + while let Some(left_pos) = locked_left.pop() { + if let Some(unlock_pos) = unlocked_pos.pop() { + if left_pos > unlock_pos { + return false; + } + } else { + return false; + } + } + + // 剩余的未锁定括号必须是偶数个 + unlocked_pos.len() % 2 == 0 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2116() { + assert!(!Solution::can_be_valid( + "(((())".to_owned(), + "111111".to_owned() + )); + assert!(Solution::can_be_valid( + "))()))".to_owned(), + "010100".to_owned() + )); + assert!(Solution::can_be_valid("()()".to_owned(), "0000".to_owned())); + assert!(!Solution::can_be_valid(")".to_owned(), "0".to_owned())); + assert!(Solution::can_be_valid( + "(((())(((())".to_owned(), + "111111010111".to_owned() + )); + } +} diff --git a/src/problem/p2140_solving_questions_with_brainpower.rs b/src/problem/p2140_solving_questions_with_brainpower.rs new file mode 100644 index 0000000..b5d5570 --- /dev/null +++ b/src/problem/p2140_solving_questions_with_brainpower.rs @@ -0,0 +1,56 @@ +/** + * [2140] Solving Questions With Brainpower + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn most_points(questions: Vec>) -> i64 { + let questions: Vec<(i64, usize)> = questions + .into_iter() + .map(|a| (a[0] as i64, a[1] as usize)) + .collect(); + let n = questions.len(); + let mut dp = vec![0; n]; + + for i in (0..n).rev() { + let (score, brain_power) = questions[i]; + dp[i] = if i == n - 1 { 0 } else { dp[i + 1] }; + + // 选择做i题就需要跳过brian_power道题 + if i + brain_power + 1 < n { + dp[i] = dp[i].max(dp[i + brain_power + 1] + score); + } else { + dp[i] = dp[i].max(score); + } + } + + dp[0] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2140() { + assert_eq!( + 5, + Solution::most_points(vec![vec![3, 2], vec![4, 3], vec![4, 4], vec![2, 5]]) + ); + assert_eq!( + 7, + Solution::most_points(vec![ + vec![1, 1], + vec![2, 2], + vec![3, 3], + vec![4, 4], + vec![5, 5] + ]) + ); + } +} diff --git a/src/problem/p2145_count_the_hidden_sequences.rs b/src/problem/p2145_count_the_hidden_sequences.rs new file mode 100644 index 0000000..90aa035 --- /dev/null +++ b/src/problem/p2145_count_the_hidden_sequences.rs @@ -0,0 +1,45 @@ +/** + * [2145] Count the Hidden Sequences + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn number_of_arrays(differences: Vec, lower: i32, upper: i32) -> i32 { + let mut min_value = 0i64; + let mut max_value = 0i64; + let mut last_value = 0i64; + + for i in differences.into_iter() { + let value = last_value + i as i64; + min_value = min_value.min(value); + max_value = max_value.max(value); + last_value = value; + } + + let range = max_value - min_value; + + let result = (upper - lower + 1) as i64 - range; + if result > 0 { + result as i32 + } else { + 0 + } + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2145() { + assert_eq!(60, Solution::number_of_arrays(vec![-40], -46, 53)); + assert_eq!(2, Solution::number_of_arrays(vec![1, -3, 4], 1, 6)); + assert_eq!(4, Solution::number_of_arrays(vec![3, -4, 5, 1, -2], -4, 5)); + assert_eq!(0, Solution::number_of_arrays(vec![4, -7, 2], 3, 6)); + } +} diff --git a/src/problem/p2176_count_equal_and_divisible_pairs_in_an_array.rs b/src/problem/p2176_count_equal_and_divisible_pairs_in_an_array.rs new file mode 100644 index 0000000..151f4e4 --- /dev/null +++ b/src/problem/p2176_count_equal_and_divisible_pairs_in_an_array.rs @@ -0,0 +1,39 @@ +/** + * [2176] Count Equal and Divisible Pairs in an Array + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn count_pairs(nums: Vec, k: i32) -> i32 { + let k = k as usize; + let n = nums.len(); + + (0..n) + .into_iter() + .map(|x| (x + 1..n).into_iter().map(move |y| (x, y))) + .flatten() + .filter_map(|(i, j)| { + if nums[i] == nums[j] && i * j % k == 0 { + Some(()) + } else { + None + } + }) + .count() as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2176() { + assert_eq!(4, Solution::count_pairs(vec![3, 1, 2, 2, 2, 1, 3], 2)); + assert_eq!(0, Solution::count_pairs(vec![1, 2, 3, 4], 1)); + } +} diff --git a/src/problem/p2179_count_good_triplets_in_an_array.rs b/src/problem/p2179_count_good_triplets_in_an_array.rs new file mode 100644 index 0000000..119e7fe --- /dev/null +++ b/src/problem/p2179_count_good_triplets_in_an_array.rs @@ -0,0 +1,99 @@ +/** + * [2179] Count Good Triplets in an Array + */ +pub struct Solution {} + +// submission codes start here + +struct FenwickTree { + tree: Vec, +} + +impl FenwickTree { + fn new(size: usize) -> Self { + Self { + tree: vec![0; size + 1], + } + } + + fn update(&mut self, mut index: usize, delta: i64) { + index += 1; + + while index < self.tree.len() { + self.tree[index] += delta; + + index += Self::low_bit(index) + } + } + + fn query(&self, mut index: usize) -> i64 { + index += 1; + let mut result = 0; + + while index > 0 { + result += self.tree[index]; + index -= Self::low_bit(index) + } + + result + } + + // 二进制最低位1以及后面的0组成的数 + fn low_bit(i: usize) -> usize { + i & (!i + 1) + } +} + +impl Solution { + pub fn good_triplets(nums1: Vec, nums2: Vec) -> i64 { + let n = nums1.len(); + // nums2中各个值到下标的映射数组 + let mut pos2 = vec![0; n]; + // index_mapping 是nums1中一个数在nums2中的下标 + // reverse_index_mapping是该下标同nums1中数字下标的对应关系 + let mut reversed_index_mapping = vec![0; n]; + + for (i, v) in nums2.iter().enumerate() { + pos2[*v as usize] = i; + } + + for i in 0..n { + // nums1中的一个值在nums2中的下标到该值在nums1中的下标的映射 + reversed_index_mapping[pos2[nums1[i] as usize]] = i; + } + + let mut tree = FenwickTree::new(n); + + let mut result = 0; + + // 枚举num1s中的一个值在nums2中的下标 + for j in 0..n { + let pos = reversed_index_mapping[j]; + let left = tree.query(pos); + tree.update(pos, 1); + let right = ((n - 1 - pos) - (j - left as usize)) as i64; + result += left * right; + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2179() { + assert_eq!( + 1, + Solution::good_triplets(vec![2, 0, 1, 3], vec![0, 1, 2, 3]) + ); + assert_eq!( + 4, + Solution::good_triplets(vec![4, 0, 1, 3, 2], vec![4, 1, 0, 2, 3]) + ); + } +} diff --git a/src/problem/p2209_minimum_white_tiles_after_covering_with_carpets.rs b/src/problem/p2209_minimum_white_tiles_after_covering_with_carpets.rs new file mode 100644 index 0000000..cb4852b --- /dev/null +++ b/src/problem/p2209_minimum_white_tiles_after_covering_with_carpets.rs @@ -0,0 +1,68 @@ +use std::ffi::FromVecWithNulError; + +/** + * [2209] Minimum White Tiles After Covering With Carpets + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn minimum_white_tiles(floor: String, num_carpets: i32, carpet_len: i32) -> i32 { + let carpets_num = num_carpets as usize; + let carpet_length = carpet_len as usize; + let floor: Vec = floor + .chars() + .into_iter() + .map(|x| if x == '0' { true } else { false }) + .collect(); + + // dp[i][j] 表示 + // 当使用j块地毯时 + // [i..] 还有多少白色的地砖没有被覆盖 + let mut dp = vec![vec![0; carpets_num + 1]; floor.len()]; + + // 初始化dp[i][0] + let mut white_count = 0; + for i in (0..floor.len()).rev() { + if !floor[i] { + white_count += 1; + } + dp[i][0] = white_count; + } + + for i in (0..floor.len() - 1).rev() { + for j in 1..=carpets_num { + // 在floor[i]处不放置地毯 + let a = dp[i + 1][j] + if !floor[i] { 1 } else { 0 }; + // 在floor[i]处放置地毯 + // 如果放置的长度超过地板的总长 + // 则剩余的白色地砖数量必然为0 + let b = if i + carpet_length >= floor.len() { + 0 + } else { + dp[i + carpet_length][j - 1] + }; + dp[i][j] = a.min(b); + } + } + + dp[0][carpets_num] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2209() { + assert_eq!(0, Solution::minimum_white_tiles("11111".to_owned(), 2, 3)); + assert_eq!( + 2, + Solution::minimum_white_tiles("10110101".to_owned(), 2, 2) + ); + } +} diff --git a/src/problem/p2234_maximum_total_beauty_of_the_gardens.rs b/src/problem/p2234_maximum_total_beauty_of_the_gardens.rs new file mode 100644 index 0000000..e41f6ac --- /dev/null +++ b/src/problem/p2234_maximum_total_beauty_of_the_gardens.rs @@ -0,0 +1,78 @@ +/** + * [2234] Maximum Total Beauty of the Gardens + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn maximum_beauty( + mut flowers: Vec, + new_flowers: i64, + target: i32, + full: i32, + partial: i32, + ) -> i64 { + let n = flowers.len(); + let target = target as i64; + let full = full as i64; + let partial = partial as i64; + + let mut flowers: Vec = flowers + .into_iter() + .map(|x| (x as i64).min(target)) + .collect(); + + flowers.sort_unstable_by(|a, b| b.cmp(a)); + + let mut result = 0; + let mut sum: i64 = flowers.iter().map(|x| *x).sum(); + if target * n as i64 - sum <= new_flowers { + result += full * n as i64; + } + + let mut prefix = 0; + let mut ptr = 0; + + for i in 0..n { + if i != 0 { + prefix += flowers[i - 1]; + } + + if flowers[i] == target { + continue; + } + + let mut rest = new_flowers - (target * i as i64 - prefix); + if rest < 0 { + break; + } + + while !(ptr >= i && flowers[ptr] * (n - ptr) as i64 - sum <= rest) { + sum -= flowers[ptr]; + ptr += 1; + } + + rest -= flowers[ptr] * (n - ptr) as i64 - sum; + result = result.max( + full * i as i64 + + partial * (flowers[ptr] + rest / (n - ptr) as i64).min(target - 1), + ); + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2234() { + assert_eq!(14, Solution::maximum_beauty(vec![1, 3, 1, 1], 7, 6, 12, 1)); + assert_eq!(30, Solution::maximum_beauty(vec![2, 4, 5, 3], 10, 5, 2, 6)); + } +} diff --git a/src/problem/p2255_count_prefixes_of_a_given_string.rs b/src/problem/p2255_count_prefixes_of_a_given_string.rs new file mode 100644 index 0000000..c8b0a02 --- /dev/null +++ b/src/problem/p2255_count_prefixes_of_a_given_string.rs @@ -0,0 +1,34 @@ +/** + * [2255] Count Prefixes of a Given String + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn count_prefixes(words: Vec, s: String) -> i32 { + words.iter().filter(|i| s.starts_with(i.as_str())).count() as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2255() { + assert_eq!( + 3, + Solution::count_prefixes( + vec_string!("a", "b", "c", "ab", "bc", "abc"), + "abc".to_owned() + ) + ); + assert_eq!( + 2, + Solution::count_prefixes(vec_string!("a", "a"), "aa".to_owned()) + ); + } +} diff --git a/src/problem/p2269_find_the_k_beauty_of_a_number.rs b/src/problem/p2269_find_the_k_beauty_of_a_number.rs new file mode 100644 index 0000000..68a5e66 --- /dev/null +++ b/src/problem/p2269_find_the_k_beauty_of_a_number.rs @@ -0,0 +1,36 @@ +/** + * [2269] Find the K-Beauty of a Number + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn divisor_substrings(num: i32, k: i32) -> i32 { + let k = k as usize; + let num_str: Vec = num.to_string().chars().collect(); + + (0..=num_str.len() - k) + .into_iter() + .map(|i| { + (&num_str[i..i + k]) + .iter() + .fold(0i32, |v, c| v * 10 + c.to_digit(10).unwrap() as i32) + }) + .filter(|&v| v != 0 && num % v == 0) + .count() as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2269() { + assert_eq!(2, Solution::divisor_substrings(240, 2)); + assert_eq!(2, Solution::divisor_substrings(430043, 2)); + } +} diff --git a/src/problem/p2272_substring_with_largest_variance.rs b/src/problem/p2272_substring_with_largest_variance.rs new file mode 100644 index 0000000..7ac1570 --- /dev/null +++ b/src/problem/p2272_substring_with_largest_variance.rs @@ -0,0 +1,58 @@ +/** + * [2272] Substring With Largest Variance + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn largest_variance(s: String) -> i32 { + let word: Vec = s.chars().collect(); + let mut pos_map = HashMap::new(); + + for (i, c) in word.into_iter().enumerate() { + let entry = pos_map.entry(c).or_insert(vec![]); + entry.push(i); + } + + let mut result = 0; + + for (c0, pos0) in pos_map.iter() { + for (c1, pos1) in pos_map.iter() { + if c0 != c1 { + let (mut i, mut j) = (0, 0); + let (mut f, mut g) = (0, i32::MIN); + + // 这里的算法类似于合并两个有序列表 + while i < pos0.len() || j < pos1.len() { + if j == pos1.len() || (i < pos0.len() && pos0[i] < pos1[j]) { + (f, g) = (f.max(0) + 1, g + 1); + i += 1; + } else { + (f, g) = (f.max(0) - 1, f.max(g).max(0) - 1); + j += 1; + } + + result = result.max(g); + } + } + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2272() { + assert_eq!(3, Solution::largest_variance("aababbb".to_owned())); + assert_eq!(0, Solution::largest_variance("abcde".to_owned())); + } +} diff --git a/src/problem/p2278_percentage_of_letter_in_string.rs b/src/problem/p2278_percentage_of_letter_in_string.rs new file mode 100644 index 0000000..5b27b71 --- /dev/null +++ b/src/problem/p2278_percentage_of_letter_in_string.rs @@ -0,0 +1,25 @@ +/** + * [2278] Percentage of Letter in String + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn percentage_letter(s: String, letter: char) -> i32 { + (s.chars().filter(|c| *c == letter).count() * 100 / s.len()) as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2278() { + assert_eq!(33, Solution::percentage_letter("foobar".to_owned(), 'o')); + assert_eq!(0, Solution::percentage_letter("jjjj".to_owned(), 'k')); + } +} diff --git a/src/problem/p2338_count_the_number_of_ideal_arrays.rs b/src/problem/p2338_count_the_number_of_ideal_arrays.rs new file mode 100644 index 0000000..0960c00 --- /dev/null +++ b/src/problem/p2338_count_the_number_of_ideal_arrays.rs @@ -0,0 +1,81 @@ +/** + * [2338] Count the Number of Ideal Arrays + */ +pub struct Solution {} + +// submission codes start here + +const MOD: usize = 1_000_000_007; +const MAX_N: usize = 10010; +const MAX_P: usize = 15; + +impl Solution { + pub fn ideal_arrays(n: i32, max_value: i32) -> i32 { + let mut result = 0usize; + let n = n as usize; + let (prime_sieves, dp) = Self::calculate_dp_array(); + + for x in 1..=max_value { + let mut current = 1; + for &p in prime_sieves[x as usize].iter() { + current = current * dp[n + p - 1][p] % MOD; + } + result = (result + current) % MOD; + } + + result as i32 + } + + fn calculate_dp_array() -> (Vec>, Vec>) { + // 最小质因数列表 + let mut sieves = vec![0; MAX_N]; + + for i in 2..MAX_N { + if sieves[i] == 0 { + for j in (i..MAX_N).step_by(i) { + sieves[j] = i; + } + } + } + + let mut prime_sieves = vec![vec![]; MAX_N]; + for i in 2..MAX_N { + let mut x = i; + + while x > 1 { + let p = sieves[x]; + let mut current = 0; + while x % p == 0 { + x /= p; + current += 1; + } + + prime_sieves[i].push(current); + } + } + + let mut dp = vec![vec![0usize; MAX_P + 1]; MAX_N + MAX_P]; + dp[0][0] = 1; + for i in 1..(MAX_N + MAX_P) { + dp[i][0] = 1; + for j in 1..(i.min(MAX_P) + 1) { + dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1]) % MOD; + } + } + + (prime_sieves, dp) + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2338() { + assert_eq!(10, Solution::ideal_arrays(2, 5)); + assert_eq!(11, Solution::ideal_arrays(5, 3)); + } +} diff --git a/src/problem/p2353_design_a_food_rating_system.rs b/src/problem/p2353_design_a_food_rating_system.rs new file mode 100644 index 0000000..4587f89 --- /dev/null +++ b/src/problem/p2353_design_a_food_rating_system.rs @@ -0,0 +1,137 @@ +/** + * [2353] Design a Food Rating System + */ +pub struct Solution {} + +// submission codes start here +use std::cmp::Ordering; +use std::collections::{BinaryHeap, HashMap}; + +#[derive(Debug, Clone, Eq, PartialEq)] +struct Food { + name: String, + cuisine: String, + rating: i32, +} + +impl Food { + fn new(name: String, cuisine: String, rating: i32) -> Self { + Self { + name, + cuisine, + rating, + } + } + + fn update_rating(&self, new_rating: i32) -> Self { + Self { + name: self.name.clone(), + cuisine: self.cuisine.clone(), + rating: new_rating, + } + } +} + +impl Ord for Food { + fn cmp(&self, other: &Self) -> Ordering { + match self.rating.cmp(&other.rating) { + Ordering::Equal => other.name.cmp(&self.name), + a => a, + } + } +} + +impl PartialOrd for Food { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +struct FoodRatings { + food_map: HashMap, + cuisine_heap: HashMap>, +} + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl FoodRatings { + fn new(foods: Vec, cuisines: Vec, ratings: Vec) -> Self { + let mut food_map = HashMap::new(); + let mut cuisine_heap = HashMap::new(); + + for ((name, cuisine), &rating) in foods.iter().zip(cuisines.iter()).zip(ratings.iter()) { + food_map.insert( + name.clone(), + Food::new(name.clone(), cuisine.clone(), rating), + ); + + let heap = cuisine_heap + .entry(cuisine.clone()) + .or_insert(BinaryHeap::new()); + heap.push(Food::new(name.clone(), cuisine.clone(), rating.clone())); + } + + Self { + food_map, + cuisine_heap, + } + } + + fn change_rating(&mut self, food: String, new_rating: i32) { + let food_entry = self.food_map.get_mut(&food).unwrap(); + food_entry.rating = new_rating; + + let heap = self.cuisine_heap.get_mut(&food_entry.cuisine).unwrap(); + heap.push(food_entry.update_rating(new_rating)); + } + + fn highest_rated(&mut self, cuisine: String) -> String { + let heap = self.cuisine_heap.get_mut(&cuisine).unwrap(); + + while let Some(head) = heap.peek() { + let food_entry = self.food_map.get(&head.name).unwrap(); + + if head.rating == food_entry.rating { + return food_entry.name.clone(); + } + + heap.pop(); + } + + "".to_owned() + } +} + +/** + * Your FoodRatings object will be instantiated and called as such: + * let obj = FoodRatings::new(foods, cuisines, ratings); + * obj.change_rating(food, newRating); + * let ret_2: String = obj.highest_rated(cuisine); + */ + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2353() { + let mut ratings = FoodRatings::new( + vec_string!("kimchi", "miso", "sushi", "moussaka", "ramen", "bulgogi"), + vec_string!("korean", "japanese", "japanese", "greek", "japanese", "korean"), + vec![9, 12, 8, 15, 14, 7], + ); + + assert_eq!("kimchi", ratings.highest_rated("korean".to_owned())); + assert_eq!("ramen", ratings.highest_rated("japanese".to_owned())); + + ratings.change_rating("sushi".to_owned(), 16); + assert_eq!("sushi", ratings.highest_rated("japanese".to_owned())); + + ratings.change_rating("ramen".to_owned(), 16); + assert_eq!("ramen", ratings.highest_rated("japanese".to_owned())); + } +} diff --git a/src/problem/p2360_longest_cycle_in_a_graph.rs b/src/problem/p2360_longest_cycle_in_a_graph.rs new file mode 100644 index 0000000..1b175af --- /dev/null +++ b/src/problem/p2360_longest_cycle_in_a_graph.rs @@ -0,0 +1,55 @@ +/** + * [2360] Longest Cycle in a Graph + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn longest_cycle(edges: Vec) -> i32 { + let n = edges.len(); + let mut labels = vec![0; n]; + + let mut current_label = 0; + let mut result = -1; + + for i in 0..n { + if labels[i] != 0 { + continue; + } + + let mut pos = i as i32; + let start_label = current_label; + + while pos != -1 { + current_label += 1; + // 遇到已经遍历过的节点 + let real_pos = pos as usize; + if labels[real_pos] != 0 { + if labels[real_pos] > start_label { + result = result.max(current_label - labels[real_pos]); + } + break; + } + + labels[real_pos] = current_label; + pos = edges[real_pos]; + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2360() { + assert_eq!(3, Solution::longest_cycle(vec![3, 3, 4, 2, 3])); + assert_eq!(-1, Solution::longest_cycle(vec![2, -1, 3, 1])); + } +} diff --git a/src/problem/p2364_count_number_of_bad_pairs.rs b/src/problem/p2364_count_number_of_bad_pairs.rs new file mode 100644 index 0000000..f390541 --- /dev/null +++ b/src/problem/p2364_count_number_of_bad_pairs.rs @@ -0,0 +1,41 @@ +/** + * [2364] Count Number of Bad Pairs + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn count_bad_pairs(nums: Vec) -> i64 { + let n = nums.len() as i64; + let mut map = HashMap::new(); + + for (i, v) in nums.into_iter().enumerate() { + let delta = v - i as i32; + let mut entry = map.entry(delta).or_insert(0); + *entry += 1; + } + + // 反过来计算好数对的数量 + let good_pair_count = map + .values() + .filter_map(|&v| if v >= 2 { Some(v * (v - 1) / 2) } else { None }) + .sum::(); + + n * (n - 1) / 2 - good_pair_count + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2364() { + assert_eq!(5, Solution::count_bad_pairs(vec![4, 1, 3, 3])); + assert_eq!(0, Solution::count_bad_pairs(vec![1, 2, 3, 4, 5])); + } +} diff --git a/src/problem/p2502_design_memory_allocator.rs b/src/problem/p2502_design_memory_allocator.rs new file mode 100644 index 0000000..9f73961 --- /dev/null +++ b/src/problem/p2502_design_memory_allocator.rs @@ -0,0 +1,105 @@ +/** + * [2502] Design Memory Allocator + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +struct Allocator { + memory: Vec, + id_map: HashMap>, +} + +/** + * `&self` means the method takes an immutable reference. + * If you need a mutable reference, change it to `&mut self` instead. + */ +impl Allocator { + fn new(n: i32) -> Self { + let n = n as usize; + Self { + memory: vec![false; n], + id_map: HashMap::new(), + } + } + + fn allocate(&mut self, size: i32, m_id: i32) -> i32 { + let size = size as usize; + let mut start = 0; + + while start < self.memory.len() { + let mut pos = start; + while pos < self.memory.len() && !self.memory[pos] { + if pos - start + 1 == size { + for i in start..=pos { + self.memory[i] = true; + } + + let entry = self.id_map.entry(m_id).or_insert(vec![]); + entry.push((start, pos)); + return start as i32; + } + + pos += 1; + } + + // 到达这里只能说明找到的空间不足 + start = pos + 1; + } + + -1 + } + + fn free_memory(&mut self, m_id: i32) -> i32 { + if let Some(array) = self.id_map.get(&m_id) { + let mut length = 0; + + for &(start, end) in array.iter() { + for i in start..=end { + self.memory[i] = false; + } + length += (end - start + 1) as i32; + } + + self.id_map.remove(&m_id); + length + } else { + 0 + } + } +} + +/** + * Your Allocator object will be instantiated and called as such: + * let obj = Allocator::new(n); + * let ret_1: i32 = obj.allocate(size, mID); + * let ret_2: i32 = obj.free_memory(mID); + */ + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2502() { + let mut allocator = Allocator::new(10); + + assert_eq!(0, allocator.allocate(1, 1)); + assert_eq!(1, allocator.allocate(1, 2)); + assert_eq!(2, allocator.allocate(1, 3)); + + assert_eq!(1, allocator.free_memory(2)); + + assert_eq!(3, allocator.allocate(3, 4)); + assert_eq!(1, allocator.allocate(1, 1)); + assert_eq!(6, allocator.allocate(1, 1)); + + assert_eq!(3, allocator.free_memory(1)); + + assert_eq!(-1, allocator.allocate(10, 2)); + assert_eq!(0, allocator.free_memory(7)); + } +} diff --git a/src/problem/p2506_count_pairs_of_similar_strings.rs b/src/problem/p2506_count_pairs_of_similar_strings.rs new file mode 100644 index 0000000..029cb20 --- /dev/null +++ b/src/problem/p2506_count_pairs_of_similar_strings.rs @@ -0,0 +1,50 @@ +/** + * [2506] Count Pairs Of Similar Strings + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn similar_pairs(words: Vec) -> i32 { + let mut map = HashMap::new(); + + for word in words.iter() { + let mut bits = 0; + + for c in word.chars() { + bits = bits | (1 << (c as u8 - 'a' as u8)) + } + + let entry = map.entry(bits).or_insert(0); + *entry += 1; + } + + let mut result = 0; + + for &v in map.values() { + // C(n, 2) + result += v * (v - 1) / 2; + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2506() { + assert_eq!( + 2, + Solution::similar_pairs(vec_string!("aba", "aabb", "abcd", "bac", "aabc")) + ); + assert_eq!(3, Solution::similar_pairs(vec_string!("aabb", "ab", "ba"))); + assert_eq!(0, Solution::similar_pairs(vec_string!("nba", "cba", "dba"))); + } +} diff --git a/src/problem/p2537_count_the_number_of_good_subarrays.rs b/src/problem/p2537_count_the_number_of_good_subarrays.rs new file mode 100644 index 0000000..de19f69 --- /dev/null +++ b/src/problem/p2537_count_the_number_of_good_subarrays.rs @@ -0,0 +1,58 @@ +/** + * [2537] Count the Number of Good Subarrays + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn count_good(nums: Vec, k: i32) -> i64 { + let mut map = HashMap::new(); + let n = nums.len(); + + let mut result = 0i64; + let mut count = 0; + let (mut left, mut right) = (0, 0); + + while left < n { + while right < n && count < k { + let entry = map.entry(nums[right]).or_insert(0); + count += *entry; + *entry += 1; + + right += 1; + } + + if count < k && right >= n { + // 拼尽全力无法战胜 + break; + } + + // 此时已经遇到了一个合格的序列 + // 注意序列可以多余的包含右侧的所有元素 + result += (n - right) as i64 + 1; + + // 右移left + let entry = map.entry(nums[left]).or_insert(0); + count -= *entry - 1; + *entry -= 1; + left += 1; + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2537() { + assert_eq!(4, Solution::count_good(vec![3, 1, 4, 3, 2, 2, 4], 2)); + assert_eq!(1, Solution::count_good(vec![1, 1, 1, 1, 1], 10)); + } +} diff --git a/src/problem/p2563_count_the_number_of_fair_pairs.rs b/src/problem/p2563_count_the_number_of_fair_pairs.rs new file mode 100644 index 0000000..22cc2c1 --- /dev/null +++ b/src/problem/p2563_count_the_number_of_fair_pairs.rs @@ -0,0 +1,35 @@ +/** + * [2563] Count the Number of Fair Pairs + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn count_fair_pairs(mut nums: Vec, lower: i32, upper: i32) -> i64 { + nums.sort_unstable(); + let mut result = 0; + + for i in 0..nums.len() { + let l = nums[0..i].partition_point(|&x| x + nums[i] < lower); + let r = nums[0..i].partition_point(|&x| x + nums[i] <= upper); + + result += r - l; + } + + result as i64 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2563() { + assert_eq!(6, Solution::count_fair_pairs(vec![0, 1, 7, 4, 4, 5], 3, 6)); + assert_eq!(1, Solution::count_fair_pairs(vec![1, 7, 9, 2, 5], 11, 11)); + } +} diff --git a/src/problem/p2588_count_the_number_of_beautiful_subarrays.rs b/src/problem/p2588_count_the_number_of_beautiful_subarrays.rs new file mode 100644 index 0000000..dfe2573 --- /dev/null +++ b/src/problem/p2588_count_the_number_of_beautiful_subarrays.rs @@ -0,0 +1,45 @@ +/** + * [2588] Count the Number of Beautiful Subarrays + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn beautiful_subarrays(nums: Vec) -> i64 { + let n = nums.len(); + let mut prefix = vec![0; n + 1]; + + for i in 0..n { + prefix[i + 1] = prefix[i] ^ nums[i]; + } + + let mut map = HashMap::new(); + + let mut result = 0; + for i in 0..=n { + if let Some(count) = map.get(&prefix[i]) { + result += count; + } + + let entry = map.entry(prefix[i] ^ 0).or_insert(0); + *entry += 1; + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2588() { + assert_eq!(2, Solution::beautiful_subarrays(vec![4, 3, 1, 2, 4])); + assert_eq!(0, Solution::beautiful_subarrays(vec![1, 10, 4])); + } +} diff --git a/src/problem/p2595_number_of_even_and_odd_bits.rs b/src/problem/p2595_number_of_even_and_odd_bits.rs new file mode 100644 index 0000000..4bb710b --- /dev/null +++ b/src/problem/p2595_number_of_even_and_odd_bits.rs @@ -0,0 +1,43 @@ +/** + * [2595] Number of Even and Odd Bits + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn even_odd_bit(mut n: i32) -> Vec { + let mut is_even = true; + let mut even_count = 0; + let mut odd_count = 0; + + while n > 0 { + let bit = n % 2; + if bit == 1 { + if is_even { + even_count += 1; + } else { + odd_count += 1; + } + } + + is_even = !is_even; + n = n / 2; + } + + vec![even_count, odd_count] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2595() { + assert_eq!(vec![1, 2], Solution::even_odd_bit(50)); + assert_eq!(vec![0, 1], Solution::even_odd_bit(2)); + } +} diff --git a/src/problem/p2597_the_number_of_beautiful_subsets.rs b/src/problem/p2597_the_number_of_beautiful_subsets.rs new file mode 100644 index 0000000..599ff33 --- /dev/null +++ b/src/problem/p2597_the_number_of_beautiful_subsets.rs @@ -0,0 +1,64 @@ +/** + * [2597] The Number of Beautiful Subsets + */ +pub struct Solution {} + +// submission codes start here +use std::collections::{BTreeMap, HashMap}; + +impl Solution { + pub fn beautiful_subsets(nums: Vec, k: i32) -> i32 { + let mut map = HashMap::new(); + + for i in nums { + let value = i % k; + let entry = map.entry(value).or_insert(BTreeMap::new()); + let group_entry = entry.entry(i).or_insert(0); + *group_entry += 1; + } + + let mut result = 1; + + for group in map.values() { + let n = group.len(); + // (x, y) x表示不选择第i个数 + // y表示选择第i个数 + let mut dp = vec![(0, 0); n]; + // 懒得用迭代器移来移去 + // 直接复制到数组开干 + let array: Vec<(i32, i32)> = group.iter().map(|(x, y)| (*x, *y)).collect(); + + for (i, &(key, count)) in array.iter().enumerate() { + if i == 0 { + dp[0].0 = 1; + dp[0].1 = (1 << count) - 1; + } else { + dp[i].0 = dp[i - 1].0 + dp[i - 1].1; + + if key - array[i - 1].0 == k { + dp[i].1 = dp[i - 1].0 * ((1 << count) - 1); + } else { + dp[i].1 = (dp[i - 1].0 + dp[i - 1].1) * ((1 << count) - 1); + } + } + } + + result *= dp[n - 1].0 + dp[n - 1].1; + } + + result - 1 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2597() { + assert_eq!(4, Solution::beautiful_subsets(vec![2, 4, 6], 2)); + assert_eq!(1, Solution::beautiful_subsets(vec![1], 1)); + } +} diff --git a/src/problem/p2610_convert_an_array_into_a_2d_array_with_conditions.rs b/src/problem/p2610_convert_an_array_into_a_2d_array_with_conditions.rs new file mode 100644 index 0000000..b97f46c --- /dev/null +++ b/src/problem/p2610_convert_an_array_into_a_2d_array_with_conditions.rs @@ -0,0 +1,47 @@ +/** + * [2610] Convert an Array Into a 2D Array With Conditions + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn find_matrix(nums: Vec) -> Vec> { + let mut result = vec![]; + let mut map = HashMap::new(); + + for i in nums { + let entry = map.entry(i).or_insert(0); + *entry += 1; + } + + while !map.is_empty() { + let mut row = Vec::with_capacity(map.len()); + for (k, v) in map.iter_mut() { + row.push(*k); + *v -= 1; + } + + map.retain(|_, &mut x| x != 0); + result.push(row); + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2610() { + assert_inner_array_unorder_equal!( + vec![vec![1, 3, 4, 2], vec![1, 3], vec![1]], + Solution::find_matrix(vec![1, 3, 4, 1, 2, 3, 1]), + ); + } +} diff --git a/src/problem/p2612_minimum_reverse_operations.rs b/src/problem/p2612_minimum_reverse_operations.rs new file mode 100644 index 0000000..dcaf5b3 --- /dev/null +++ b/src/problem/p2612_minimum_reverse_operations.rs @@ -0,0 +1,89 @@ +/** + * [2612] Minimum Reverse Operations + */ +pub struct Solution {} + +// submission codes start here +use std::collections::{BTreeSet, HashSet, VecDeque}; +use std::iter::FromIterator; + +impl Solution { + pub fn min_reverse_operations(n: i32, p: i32, banned: Vec, k: i32) -> Vec { + let (n, p) = (n as usize, p as usize); + let mut ban_pos: HashSet = + HashSet::from_iter(banned.into_iter().map(|x| x as usize)); + // 奇数下标和偶数下标是分别连续的 + // 使用两个二叉树维护 + let mut odd_pos = BTreeSet::new(); + let mut even_pos = BTreeSet::new(); + + for i in 0..n { + if i != p && !ban_pos.contains(&i) { + if i % 2 == 0 { + even_pos.insert(i); + } else { + odd_pos.insert(i); + } + } + } + + let mut result = vec![-1; n]; + let mut queue = VecDeque::new(); + queue.push_back(p); + result[p] = 0; + + while let Some(front) = queue.pop_front() { + // 为了防止usize溢出的诡异类型转换 + let min_pos = (front as i32 - k + 1).max(k - front as i32 - 1) as usize; + let max_pos = (front as i32 + k - 1).min(n as i32 * 2 - k - front as i32 - 1) as usize; + + let mut iter = if max_pos % 2 == 0 { + even_pos.range(min_pos..) + } else { + odd_pos.range(min_pos..) + }; + + while let Some(&value) = iter.next() { + if value > max_pos { + break; + } + + result[value] = result[front] + 1; + queue.push_back(value); + + iter = if min_pos % 2 == 0 { + even_pos.remove(&value); + even_pos.range(value + 1..) + } else { + odd_pos.remove(&value); + odd_pos.range(value + 1..) + } + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2612() { + assert_eq!( + vec![0, -1, -1, 1], + Solution::min_reverse_operations(4, 0, vec![1, 2], 4) + ); + assert_eq!( + vec![0, -1, -1, -1, -1], + Solution::min_reverse_operations(5, 0, vec![2, 4], 3) + ); + assert_eq!( + vec![-1, -1, 0, -1], + Solution::min_reverse_operations(4, 2, vec![0, 1, 3], 1) + ); + } +} diff --git a/src/problem/p2614_prime_in_diagonal.rs b/src/problem/p2614_prime_in_diagonal.rs new file mode 100644 index 0000000..80efa88 --- /dev/null +++ b/src/problem/p2614_prime_in_diagonal.rs @@ -0,0 +1,52 @@ +/** + * [2614] Prime In Diagonal + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn diagonal_prime(nums: Vec>) -> i32 { + let n = nums.len(); + let mut result = 0; + + for i in 0..n { + if Self::is_prime(nums[i][i]) { + result = result.max(nums[i][i]); + } + + if Self::is_prime(nums[i][n - i - 1]) { + result = result.max(nums[i][n - i - 1]); + } + } + + result + } + + fn is_prime(num: i32) -> bool { + if num == 1 { + return false; + } + + !(2..=num.isqrt()).any(|x| num % x == 0) + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2614() { + assert_eq!( + 11, + Solution::diagonal_prime(vec![vec![1, 2, 3], vec![5, 6, 7], vec![9, 10, 11]]) + ); + assert_eq!( + 17, + Solution::diagonal_prime(vec![vec![1, 2, 3], vec![5, 17, 7], vec![9, 10, 11]]) + ); + } +} diff --git a/src/problem/p2643_row_with_maximum_ones.rs b/src/problem/p2643_row_with_maximum_ones.rs new file mode 100644 index 0000000..b16058f --- /dev/null +++ b/src/problem/p2643_row_with_maximum_ones.rs @@ -0,0 +1,48 @@ +/** + * [2643] Row With Maximum Ones + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn row_and_maximum_ones(mat: Vec>) -> Vec { + let r = mat.iter().enumerate().rev().fold( + (mat.len() - 1, 0), + |(r_line, r_count), (line, row)| { + let c = row.iter().filter(|x| **x == 1).count(); + + if c >= r_count { + (line, c) + } else { + (r_line, r_count) + } + }, + ); + + vec![r.0 as i32, r.1 as i32] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2643() { + assert_eq!( + vec![0, 1], + Solution::row_and_maximum_ones(vec![vec![0, 1], vec![1, 0]]) + ); + assert_eq!( + vec![1, 2], + Solution::row_and_maximum_ones(vec![vec![0, 0, 0], vec![0, 1, 1]]) + ); + assert_eq!( + vec![1, 2], + Solution::row_and_maximum_ones(vec![vec![0, 0], vec![1, 1], vec![0, 0]]) + ); + } +} diff --git a/src/problem/p2680_maximum_or.rs b/src/problem/p2680_maximum_or.rs new file mode 100644 index 0000000..f9b940a --- /dev/null +++ b/src/problem/p2680_maximum_or.rs @@ -0,0 +1,46 @@ +/** + * [2680] Maximum OR + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn maximum_or(nums: Vec, k: i32) -> i64 { + let n = nums.len(); + let k = k as i64; + let mut prefix = vec![0; n]; + let mut suffix = vec![0; n]; + + for i in 0..n { + if i == 0 { + prefix[i] = 0; + suffix[n - i - 1] = 0; + } else { + prefix[i] = prefix[i - 1] | nums[i - 1] as i64; + suffix[n - i - 1] = suffix[n - i] | nums[n - i] as i64; + } + } + + let mut result = 0; + + for (i, &v) in nums.iter().enumerate() { + result = result.max(prefix[i] | ((v as i64) << k) | suffix[i]); + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2680() { + assert_eq!(30, Solution::maximum_or(vec![12, 9], 1)); + assert_eq!(35, Solution::maximum_or(vec![8, 1, 2], 2)); + } +} diff --git a/src/problem/p2711_difference_of_number_of_distinct_values_on_diagonals.rs b/src/problem/p2711_difference_of_number_of_distinct_values_on_diagonals.rs new file mode 100644 index 0000000..5cc4e9f --- /dev/null +++ b/src/problem/p2711_difference_of_number_of_distinct_values_on_diagonals.rs @@ -0,0 +1,95 @@ +/** + * [2711] Difference of Number of Distinct Values on Diagonals + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; +use std::collections::HashSet; + +impl Solution { + pub fn difference_of_distinct_values(grid: Vec>) -> Vec> { + let m = grid.len(); + let n = grid[0].len(); + let mut result = vec![vec![0; n]; m]; + + Self::iterate_diagonal(&grid, &mut result, (0..m).rev().map(|i| (i, 0))); + Self::iterate_diagonal(&grid, &mut result, (0..n).rev().map(|i| (0, i))); + + result + } + + fn iterate_diagonal(grid: &Vec>, result: &mut Vec>, iter: T) + where + T: Iterator, + { + let m = grid.len(); + let n = grid[0].len(); + let max_length = m.min(n); + + let mut length = 1; + for (i, j) in iter { + let mut left_set = HashSet::with_capacity(length); + // 右下对角线因为涉及到添加和删除 + // 使用哈希表存储对应数字的出现次数 + let mut right_set = HashMap::with_capacity(length); + + // 首先遍历右下 + let (mut x, mut y) = (i + 1, j + 1); + + for _ in 1..length { + let entry = right_set.entry(grid[x][y]).or_insert(0); + *entry += 1; + + x += 1; + y += 1; + } + + // 然后开始遍历 + let (mut x, mut y) = (i, j); + + for k in 0..length { + // 删除右下对角线 + if k != 0 { + let entry = right_set.get_mut(&grid[x][y]).unwrap(); + *entry -= 1; + if *entry == 0 { + right_set.remove(&grid[x][y]); + } + } + + result[x][y] = left_set.len().abs_diff(right_set.len()) as i32; + + // 插入左上对角线 + left_set.insert(grid[x][y]); + x += 1; + y += 1; + } + + length = max_length.min(length + 1); + } + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2711() { + assert_eq!( + vec![vec![1, 1, 0], vec![1, 0, 1], vec![0, 1, 1]], + Solution::difference_of_distinct_values(vec![ + vec![1, 2, 3], + vec![3, 1, 5], + vec![3, 2, 1] + ]) + ); + assert_eq!( + vec![vec![0]], + Solution::difference_of_distinct_values(vec![vec![1]]) + ); + } +} diff --git a/src/problem/p2712_minimum_cost_to_make_all_characters_equal.rs b/src/problem/p2712_minimum_cost_to_make_all_characters_equal.rs new file mode 100644 index 0000000..496739c --- /dev/null +++ b/src/problem/p2712_minimum_cost_to_make_all_characters_equal.rs @@ -0,0 +1,34 @@ +/** + * [2712] Minimum Cost to Make All Characters Equal + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn minimum_cost(s: String) -> i64 { + let mut result = 0; + let s: Vec = s.bytes().collect(); + + for i in 1..s.len() { + if s[i] != s[i - 1] { + result += i.min(s.len() - i) as i64; + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2712() { + assert_eq!(2, Solution::minimum_cost("0011".to_owned())); + assert_eq!(9, Solution::minimum_cost("010101".to_owned())); + } +} diff --git a/src/problem/p2716_minimize_string_length.rs b/src/problem/p2716_minimize_string_length.rs new file mode 100644 index 0000000..acfe9b3 --- /dev/null +++ b/src/problem/p2716_minimize_string_length.rs @@ -0,0 +1,30 @@ +/** + * [2716] Minimize String Length + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashSet; +use std::iter::FromIterator; + +impl Solution { + pub fn minimized_string_length(s: String) -> i32 { + let set: HashSet = HashSet::from_iter(s.bytes()); + + set.len() as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2716() { + assert_eq!(3, Solution::minimized_string_length("aaabc".to_owned())); + assert_eq!(3, Solution::minimized_string_length("cbbd".to_owned())); + assert_eq!(2, Solution::minimized_string_length("dddaaa".to_owned())); + } +} diff --git a/src/problem/p2829_determine_the_minimum_sum_of_a_k_avoiding_array.rs b/src/problem/p2829_determine_the_minimum_sum_of_a_k_avoiding_array.rs new file mode 100644 index 0000000..d27344d --- /dev/null +++ b/src/problem/p2829_determine_the_minimum_sum_of_a_k_avoiding_array.rs @@ -0,0 +1,43 @@ +/** + * [2829] Determine the Minimum Sum of a k-avoiding Array + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashSet; + +impl Solution { + pub fn minimum_sum(n: i32, k: i32) -> i32 { + let mut avoid_set = HashSet::new(); + + let mut result = 0; + let mut num = 1; + + for _ in 0..n { + while avoid_set.contains(&num) { + num += 1; + } + + result += num; + if k - num > 0 { + avoid_set.insert(k - num); + } + num += 1; + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2829() { + assert_eq!(18, Solution::minimum_sum(5, 4)); + assert_eq!(3, Solution::minimum_sum(2, 6)); + } +} diff --git a/src/problem/p2843_count_symmetric_integers.rs b/src/problem/p2843_count_symmetric_integers.rs new file mode 100644 index 0000000..6789533 --- /dev/null +++ b/src/problem/p2843_count_symmetric_integers.rs @@ -0,0 +1,42 @@ +/** + * [2843] Count Symmetric Integers + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn count_symmetric_integers(low: i32, high: i32) -> i32 { + // 10 -> 99 1000 -> 9999 + (low..=high) + .filter_map(|i| { + if i >= 10 && i <= 99 { + if i / 10 == i % 10 { + return Some(()); + } + } + + if i >= 1000 && i <= 9999 { + if i / 1000 + (i / 100) % 10 == (i / 10) % 10 + i % 10 { + return Some(()); + } + } + + None + }) + .count() as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2843() { + assert_eq!(9, Solution::count_symmetric_integers(1, 99)); + assert_eq!(4, Solution::count_symmetric_integers(1200, 1230)); + } +} diff --git a/src/problem/p2845_count_of_interesting_subarrays.rs b/src/problem/p2845_count_of_interesting_subarrays.rs new file mode 100644 index 0000000..d66fc25 --- /dev/null +++ b/src/problem/p2845_count_of_interesting_subarrays.rs @@ -0,0 +1,53 @@ +/** + * [2845] Count of Interesting Subarrays + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn count_interesting_subarrays(nums: Vec, modulo: i32, k: i32) -> i64 { + let n = nums.len(); + let mut count = vec![0; n + 1]; + for (i, &v) in nums.iter().enumerate() { + count[i + 1] = count[i] + if v % modulo == k { 1 } else { 0 }; + } + + let mut map = HashMap::new(); + let mut result = 0; + + // 类似于两数之和 + for i in 0..=n { + let target = (count[i] + modulo - k) % modulo; + + if let Some(&v) = map.get(&target) { + result += v; + } + + let entry = map.entry(count[i] % modulo).or_insert(0); + *entry += 1; + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2845() { + assert_eq!( + 3, + Solution::count_interesting_subarrays(vec![3, 2, 4], 2, 1) + ); + assert_eq!( + 2, + Solution::count_interesting_subarrays(vec![3, 1, 9, 6], 3, 0) + ); + } +} diff --git a/src/problem/p2873_maximum_value_of_an_ordered_triplet_i.rs b/src/problem/p2873_maximum_value_of_an_ordered_triplet_i.rs new file mode 100644 index 0000000..3ae4ef0 --- /dev/null +++ b/src/problem/p2873_maximum_value_of_an_ordered_triplet_i.rs @@ -0,0 +1,39 @@ +/** + * [2873] Maximum Value of an Ordered Triplet I + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn maximum_triplet_value(nums: Vec) -> i64 { + let nums: Vec = nums.into_iter().map(|x| x as i64).collect(); + + let mut result = 0; + let n = nums.len(); + + for i in 0..n { + for j in i + 1..n { + for k in j + 1..n { + result = result.max((nums[i] - nums[j]) * nums[k]) + } + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2873() { + assert_eq!(77, Solution::maximum_triplet_value(vec![12, 6, 1, 2, 7])); + assert_eq!(133, Solution::maximum_triplet_value(vec![1, 10, 3, 4, 19])); + assert_eq!(0, Solution::maximum_triplet_value(vec![1, 2, 3])); + } +} diff --git a/src/problem/p2874_maximum_value_of_an_ordered_triplet_ii.rs b/src/problem/p2874_maximum_value_of_an_ordered_triplet_ii.rs new file mode 100644 index 0000000..b2c8e0a --- /dev/null +++ b/src/problem/p2874_maximum_value_of_an_ordered_triplet_ii.rs @@ -0,0 +1,47 @@ +/** + * [2874] Maximum Value of an Ordered Triplet II + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn maximum_triplet_value(nums: Vec) -> i64 { + let nums: Vec = nums.into_iter().map(|x| x as i64).collect(); + let n = nums.len(); + // max num from nums[0] to nums[i] + let mut prefix = vec![0; n]; + // max num from nums[i] to nums[n - 1] + let mut suffix = vec![0; n]; + + prefix[0] = nums[0]; + suffix[n - 1] = nums[n - 1]; + + for i in 1..n { + prefix[i] = nums[i].max(prefix[i - 1]); + suffix[n - i - 1] = nums[n - i - 1].max(suffix[n - i]); + } + + let mut result = 0; + + for j in 1..n - 1 { + result = result.max((prefix[j - 1] - nums[j]) * suffix[j + 1]); + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2874() { + assert_eq!(77, Solution::maximum_triplet_value(vec![12, 6, 1, 2, 7])); + assert_eq!(133, Solution::maximum_triplet_value(vec![1, 10, 3, 4, 19])); + assert_eq!(0, Solution::maximum_triplet_value(vec![1, 2, 3])); + } +} diff --git a/src/problem/p2999_count_the_number_of_powerful_integers.rs b/src/problem/p2999_count_the_number_of_powerful_integers.rs new file mode 100644 index 0000000..17b6c43 --- /dev/null +++ b/src/problem/p2999_count_the_number_of_powerful_integers.rs @@ -0,0 +1,111 @@ +/** + * [2999] Count the Number of Powerful Integers + */ +pub struct Solution {} + +// submission codes start here +use std::str::FromStr; + +struct Searcher { + low: Vec, + high: Vec, + suffix: Vec, + memory: Vec, + limit: u8, +} + +impl Searcher { + fn new(start: i64, finish: i64, limit: i32, s: String) -> Self { + let mut low: Vec = start.to_string().bytes().map(|x| x - b'0').collect(); + let high: Vec = finish.to_string().bytes().map(|x| x - b'0').collect(); + + // 对齐low和high的数位 + for _ in 0..high.len() - low.len() { + low.insert(0, 0); + } + + let suffix = s.bytes().map(|x| x - b'0').collect(); + let n = high.len(); + + Self { + low, + high, + suffix, + memory: vec![-1; n], + limit: limit as u8, + } + } + + fn search(&mut self, i: usize, limit_low: bool, limit_high: bool) -> i64 { + if i == self.low.len() { + return 1; + } + + if !limit_low && !limit_high && self.memory[i] != -1 { + return self.memory[i]; + } + + let low = if limit_low { self.low[i] } else { 0 }; + + let high = if limit_high { self.high[i] } else { 9 }; + + let mut result = 0; + + let prefix_len = self.low.len() - self.suffix.len(); + if i < prefix_len { + for digit in low..=high.min(self.limit) { + result += self.search( + i + 1, + limit_low && digit == low, + limit_high && digit == high, + ); + } + } else { + let digit = self.suffix[i - prefix_len]; + if digit >= low && digit <= high.min(self.limit) { + result = self.search( + i + 1, + limit_low && digit == low, + limit_high && digit == high, + ); + } + } + + if !limit_low && !limit_high { + self.memory[i] = result; + } + + result + } +} + +impl Solution { + pub fn number_of_powerful_int(start: i64, finish: i64, limit: i32, s: String) -> i64 { + let mut searcher = Searcher::new(start, finish, limit, s); + + searcher.search(0, true, true) + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2999() { + assert_eq!( + 5, + Solution::number_of_powerful_int(1, 6000, 4, "123".to_owned()) + ); + assert_eq!( + 2, + Solution::number_of_powerful_int(15, 215, 6, "10".to_owned()) + ); + assert_eq!( + 0, + Solution::number_of_powerful_int(1000, 2000, 4, "3000".to_owned()) + ); + } +} diff --git a/src/problem/p3110_score_of_a_string.rs b/src/problem/p3110_score_of_a_string.rs new file mode 100644 index 0000000..4bf6921 --- /dev/null +++ b/src/problem/p3110_score_of_a_string.rs @@ -0,0 +1,28 @@ +/** + * [3110] Score of a String + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn score_of_string(s: String) -> i32 { + s.bytes() + .zip(s.bytes().skip(1)) + .map(|(first, second)| first.abs_diff(second) as i32) + .sum::() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3110() { + assert_eq!(13, Solution::score_of_string("hello".to_owned())); + assert_eq!(50, Solution::score_of_string("zaz".to_owned())); + } +} diff --git a/src/problem/p3272_find_the_count_of_good_integers.rs b/src/problem/p3272_find_the_count_of_good_integers.rs new file mode 100644 index 0000000..35b3b53 --- /dev/null +++ b/src/problem/p3272_find_the_count_of_good_integers.rs @@ -0,0 +1,81 @@ +/** + * [3272] Find the Count of Good Integers + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashSet; + +impl Solution { + pub fn count_good_integers(n: i32, k: i32) -> i64 { + let n = n as usize; + let k = k as i64; + let base_value = 10i64.pow((n as u32 - 1) / 2); + let length = (n + 1) / 2; + let mut dict = HashSet::new(); + + // 枚举n个数位的回文数 + for mut i in base_value..base_value * 10 { + let mut s = Vec::with_capacity(length); + + while i != 0 { + s.push(i % 10); + i = i / 10; + } + + // 这里拼接回文字符串有点困难 + // 因为上面存数字字符存的是倒序 + // 即 123 -> 3 2 1 + // 所以 12321 -> 1 2 3 2 1 + let mut real_str: Vec = s + .iter() + .rev() + .chain(s.iter().skip(n & 1)) + .map(|x| *x) + .collect(); + + let number = real_str.iter().fold(0, |v, i| v * 10 + *i); + if number % k == 0 { + real_str.sort_unstable(); + dict.insert(real_str); + } + } + + let mut factorial = Vec::with_capacity(n + 1); + factorial.push(1); + for i in 1..=n { + factorial.push(factorial[i - 1] * i as i64); + } + + let mut result = 0; + + for str in dict.into_iter() { + let mut counts = [0; 10]; + for i in str { + counts[i as usize] += 1; + } + + let mut total = (n - counts[0]) as i64 * factorial[n - 1]; + for x in counts { + total /= factorial[x] + } + result += total; + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3272() { + assert_eq!(27, Solution::count_good_integers(3, 5)); + assert_eq!(2, Solution::count_good_integers(1, 4)); + assert_eq!(2468, Solution::count_good_integers(5, 6)); + } +} diff --git a/src/problem/p3305_count_of_substrings_containing_every_vowel_and_k_consonants_i.rs b/src/problem/p3305_count_of_substrings_containing_every_vowel_and_k_consonants_i.rs new file mode 100644 index 0000000..458d327 --- /dev/null +++ b/src/problem/p3305_count_of_substrings_containing_every_vowel_and_k_consonants_i.rs @@ -0,0 +1,71 @@ +/** + * [3305] Count of Substrings Containing Every Vowel and K Consonants I + */ +pub struct Solution {} + +// submission codes start here +use std::collections::{HashMap, HashSet}; + +impl Solution { + pub fn count_of_substrings(word: String, k: i32) -> i32 { + let word: Vec = word.chars().collect(); + let vowel_set = HashSet::from(['a', 'e', 'i', 'o', 'u']); + + let count = |m| -> i32 { + let mut consonants = 0; + let mut result = 0; + let mut occurence = HashMap::new(); + + let mut right = 0; + for left in 0..word.len() { + while right < word.len() && (consonants < m || occurence.len() < vowel_set.len()) { + if vowel_set.contains(&word[right]) { + let entry = occurence.entry(word[right]).or_insert(0); + *entry += 1; + } else { + consonants += 1; + } + right += 1; + } + + if consonants >= m && occurence.len() == vowel_set.len() { + result += (word.len() - right + 1) as i32; + } + + if vowel_set.contains(&word[left]) { + let v = occurence.get_mut(&word[left]).unwrap(); + *v -= 1; + if *v == 0 { + occurence.remove(&word[left]); + } + } else { + consonants -= 1; + } + } + + result + }; + + count(k) - count(k + 1) + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3305() { + assert_eq!(3, Solution::count_of_substrings("auieoui".to_owned(), 0)); + assert_eq!(2, Solution::count_of_substrings("ieiaoud".to_owned(), 0)); + assert_eq!(3, Solution::count_of_substrings("iqeaouqi".to_owned(), 2)); + assert_eq!( + 3, + Solution::count_of_substrings("ieaouqqieaouqq".to_owned(), 1) + ); + assert_eq!(0, Solution::count_of_substrings("aeioqq".to_owned(), 1)); + assert_eq!(1, Solution::count_of_substrings("aeiou".to_owned(), 0)); + } +} diff --git a/src/problem/p3306_count_of_substrings_containing_every_vowel_and_k_consonants_ii.rs b/src/problem/p3306_count_of_substrings_containing_every_vowel_and_k_consonants_ii.rs new file mode 100644 index 0000000..ef5604f --- /dev/null +++ b/src/problem/p3306_count_of_substrings_containing_every_vowel_and_k_consonants_ii.rs @@ -0,0 +1,63 @@ +/** + * [3306] Count of Substrings Containing Every Vowel and K Consonants II + */ +pub struct Solution {} + +// submission codes start here +use std::collections::{HashMap, HashSet}; + +impl Solution { + pub fn count_of_substrings(word: String, k: i32) -> i64 { + let word: Vec = word.chars().collect(); + let vowel_set = HashSet::from(['a', 'e', 'i', 'o', 'u']); + + let count = |m| -> i64 { + let mut consonants = 0; + let mut result = 0; + let mut occurence = HashMap::new(); + + let mut right = 0; + for left in 0..word.len() { + while right < word.len() && (consonants < m || occurence.len() < vowel_set.len()) { + if vowel_set.contains(&word[right]) { + let entry = occurence.entry(word[right]).or_insert(0i64); + *entry += 1; + } else { + consonants += 1; + } + right += 1; + } + + if consonants >= m && occurence.len() == vowel_set.len() { + result += (word.len() - right + 1) as i64; + } + + if vowel_set.contains(&word[left]) { + let v = occurence.get_mut(&word[left]).unwrap(); + *v -= 1; + if *v == 0 { + occurence.remove(&word[left]); + } + } else { + consonants -= 1; + } + } + + result + }; + + count(k) - count(k + 1) + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3306() { + assert_eq!(0, Solution::count_of_substrings("aeioqq".to_owned(), 1)); + } +} diff --git a/src/problem/p3340_check_balanced_string.rs b/src/problem/p3340_check_balanced_string.rs new file mode 100644 index 0000000..cbc54e7 --- /dev/null +++ b/src/problem/p3340_check_balanced_string.rs @@ -0,0 +1,27 @@ +/** + * [3340] Check Balanced String + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn is_balanced(num: String) -> bool { + let num: Vec = num.bytes().map(|x| (x - b'0') as i32).collect(); + + num.iter().step_by(2).sum::() == num.iter().skip(1).step_by(2).sum::() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3340() { + assert!(!Solution::is_balanced("1234".to_owned())); + assert!(Solution::is_balanced("24123".to_owned())); + } +} diff --git a/src/problem/p3375_minimum_operations_to_make_array_values_equal_to_k.rs b/src/problem/p3375_minimum_operations_to_make_array_values_equal_to_k.rs new file mode 100644 index 0000000..5c7dd70 --- /dev/null +++ b/src/problem/p3375_minimum_operations_to_make_array_values_equal_to_k.rs @@ -0,0 +1,41 @@ +/** + * [3375] Minimum Operations to Make Array Values Equal to K + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashSet; + +impl Solution { + pub fn min_operations(nums: Vec, k: i32) -> i32 { + let set: HashSet = nums.into_iter().collect(); + + let mut result = 0; + + for &i in set.iter() { + if i < k { + return -1; + } + + if i > k { + result += 1; + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3375() { + assert_eq!(2, Solution::min_operations(vec![5, 2, 5, 4, 5], 2)); + assert_eq!(-1, Solution::min_operations(vec![2, 1, 2], 2)); + assert_eq!(4, Solution::min_operations(vec![9, 7, 5, 3], 1)); + } +} diff --git a/src/problem/p3396_minimum_number_of_operations_to_make_elements_in_array_distinct.rs b/src/problem/p3396_minimum_number_of_operations_to_make_elements_in_array_distinct.rs new file mode 100644 index 0000000..121a003 --- /dev/null +++ b/src/problem/p3396_minimum_number_of_operations_to_make_elements_in_array_distinct.rs @@ -0,0 +1,57 @@ +/** + * [3396] Minimum Number of Operations to Make Elements in Array Distinct + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn minimum_operations(nums: Vec) -> i32 { + let mut map = HashMap::new(); + + for &i in nums.iter() { + let mut entry = map.entry(i).or_insert(0); + *entry += 1; + } + + let mut result = 0; + let mut pos = 0; + + while pos < nums.len() { + if map.values().all(|i| *i == 1) { + break; + } + + for p in pos..(pos + 3).min(nums.len()) { + pos = p; + let value = map.get_mut(&nums[pos]).unwrap(); + *value -= 1; + } + pos += 1; + + result += 1; + map.retain(|_, v| *v != 0); + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3396() { + assert_eq!(2, Solution::minimum_operations(vec![5, 7, 11, 12, 12])); + assert_eq!( + 2, + Solution::minimum_operations(vec![1, 2, 3, 4, 2, 3, 3, 5, 7]) + ); + assert_eq!(2, Solution::minimum_operations(vec![4, 5, 6, 4, 4])); + assert_eq!(0, Solution::minimum_operations(vec![6, 7, 8, 9])); + } +} diff --git a/src/problem/p368_largest_divisible_subset.rs b/src/problem/p368_largest_divisible_subset.rs new file mode 100644 index 0000000..2748396 --- /dev/null +++ b/src/problem/p368_largest_divisible_subset.rs @@ -0,0 +1,72 @@ +/** + * [368] Largest Divisible Subset + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn largest_divisible_subset(mut nums: Vec) -> Vec { + nums.sort_unstable(); + let n = nums.len(); + + let mut dp = vec![1; n]; + let mut max_size = 1; + let mut max_value = nums[0]; + + for i in 1..n { + for j in 0..i { + if nums[i] % nums[j] == 0 { + dp[i] = dp[i].max(dp[j] + 1); + } + } + + if dp[i] > max_size { + max_size = dp[i]; + max_value = nums[i]; + } + } + + // 获得求得的最大子集 + let mut result = vec![]; + + if max_size == 1 { + result.push(nums[0]); + return result; + } + + for i in (0..n).rev() { + if dp[i] == max_size && max_value % nums[i] == 0 { + result.push(nums[i]); + max_value = nums[i]; + max_size -= 1; + } + + if max_size <= 0 { + break; + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_368() { + assert_array_unorder_equal!(vec![1], Solution::largest_divisible_subset(vec![1])); + assert_array_unorder_equal!( + vec![1, 2], + Solution::largest_divisible_subset(vec![1, 2, 3]) + ); + assert_array_unorder_equal!( + vec![1, 2, 4, 8], + Solution::largest_divisible_subset(vec![1, 2, 4, 8]) + ); + } +} diff --git a/src/problem/p416_partition_equal_subset_sum.rs b/src/problem/p416_partition_equal_subset_sum.rs new file mode 100644 index 0000000..bac94e1 --- /dev/null +++ b/src/problem/p416_partition_equal_subset_sum.rs @@ -0,0 +1,58 @@ +/** + * [416] Partition Equal Subset Sum + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn can_partition(nums: Vec) -> bool { + let n = nums.len(); + if n < 2 { + return false; + } + + let nums: Vec = nums.into_iter().map(|x| x as usize).collect(); + let sum: usize = nums.iter().sum(); + + if sum % 2 != 0 { + return false; + } + + let middle = sum / 2; + let mut dp = vec![vec![false; middle + 1]; n]; + + // 初始化dp + for i in 0..n { + dp[i][0] = true; + } + if nums[0] <= middle { + dp[0][nums[0]] = true; + } + + for i in 1..n { + for j in 1..=middle { + if j < nums[i] { + dp[i][j] = dp[i - 1][j]; + } else { + dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]]; + } + } + } + + dp[n - 1][middle] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_416() { + assert!(Solution::can_partition(vec![1, 5, 11, 5])); + assert!(!Solution::can_partition(vec![1, 2, 3, 5])); + } +} diff --git a/src/problem/p624_maximum_distance_in_arrays.rs b/src/problem/p624_maximum_distance_in_arrays.rs new file mode 100644 index 0000000..50c59a9 --- /dev/null +++ b/src/problem/p624_maximum_distance_in_arrays.rs @@ -0,0 +1,43 @@ +use std::thread::available_parallelism; + +/** + * [624] Maximum Distance in Arrays + */ +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn max_distance(arrays: Vec>) -> i32 { + let mut result = 0; + // -10e4 <= array[i][j] <= 10e4 + let (mut min, mut max) = (10_000 + 1, -10_000 - 1); + + for array in arrays { + result = result + .max(*array.last().unwrap() - min) + .max(max - *array.first().unwrap()); + + min = min.min(*array.first().unwrap()); + max = max.max(*array.last().unwrap()); + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_624() { + assert_eq!( + 4, + Solution::max_distance(vec![vec![1, 2, 3], vec![4, 5], vec![1, 2, 3]]) + ); + assert_eq!(0, Solution::max_distance(vec![vec![1], vec![1]])); + } +} diff --git a/src/problem/p781_rabbits_in_forest.rs b/src/problem/p781_rabbits_in_forest.rs new file mode 100644 index 0000000..e521e3e --- /dev/null +++ b/src/problem/p781_rabbits_in_forest.rs @@ -0,0 +1,46 @@ +/** + * [781] Rabbits in Forest + */ +pub struct Solution {} + +// submission codes start here +use std::collections::HashMap; + +impl Solution { + pub fn num_rabbits(answers: Vec) -> i32 { + let mut map = HashMap::new(); + + for i in answers.into_iter() { + let entry = map.entry(i).or_insert(0); + *entry += 1; + } + + let mut result = 0; + + for (k, mut v) in map.into_iter() { + // 同种颜色兔子最多有k + 1个 + let max_count = k + 1; + + while v > 0 { + result += max_count; + v -= max_count; + } + } + + result + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_781() { + assert_eq!(5, Solution::num_rabbits(vec![1, 0, 1, 0, 0])); + assert_eq!(5, Solution::num_rabbits(vec![1, 1, 2])); + assert_eq!(11, Solution::num_rabbits(vec![10, 10, 10])) + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 5a3e574..393b4ec 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -6,3 +6,5 @@ pub mod vec_string; pub mod tree; #[macro_use] pub mod point; +#[macro_use] +pub mod vec_equal; diff --git a/src/util/vec_equal.rs b/src/util/vec_equal.rs new file mode 100644 index 0000000..b84fc69 --- /dev/null +++ b/src/util/vec_equal.rs @@ -0,0 +1,51 @@ +use std::collections::HashSet; +use std::hash::Hash; +use std::iter::FromIterator; + +pub fn assert_array_unorder_equal(a: &Vec, b: &Vec) +where + T: Eq, + T: Hash, +{ + assert_eq!(a.len(), b.len()); + + let set: HashSet<&T> = HashSet::from_iter(a.into_iter()); + + for i in b.iter() { + assert!(set.contains(i)); + } +} + +#[macro_export] +macro_rules! assert_array_unorder_equal { + ($left:expr, $right:expr $(,)?) => { + match (&$left, &$right) { + (left_value, right_value) => { + $crate::util::vec_equal::assert_array_unorder_equal(left_value, right_value); + } + } + }; +} + +pub fn assert_inner_array_unorder_equal(a: &Vec>, b: &Vec>) +where + T: Eq, + T: Hash, +{ + assert_eq!(a.len(), b.len()); + + for (i, j) in a.iter().zip(b.iter()) { + assert_array_unorder_equal(i, j); + } +} + +#[macro_export] +macro_rules! assert_inner_array_unorder_equal { + ($left:expr, $right:expr $(,)?) => { + match (&$left, &$right) { + (left_value, right_value) => { + $crate::util::vec_equal::assert_inner_array_unorder_equal(left_value, right_value); + } + } + }; +}