Compare commits

...

44 Commits

Author SHA1 Message Date
e6a52152ac 20250610 finished. 2025-06-10 11:28:01 +08:00
6d9aecd427 20250609 finished. 2025-06-09 12:38:42 +08:00
7a5716233b 20250608 finished. 2025-06-08 15:38:26 +08:00
f1d54e2540 20250607 finished. 2025-06-07 15:14:43 +08:00
9c5919af38 20250606 finished. 2025-06-06 16:38:46 +08:00
17c17b126f 20250605 finished. 2025-06-05 17:21:15 +08:00
b200c4032e 20250604 finished. 2025-06-04 09:54:22 +08:00
2ce7e6667f 20250603 finished. 2025-06-03 15:26:29 +08:00
fb6224fc12 20250601 finished. 2025-06-01 15:22:35 +08:00
d7f2a5dc1b 20250530 finished. 2025-05-30 16:49:50 +08:00
f91eaffcb3 20250529 finished. 2025-05-29 14:01:23 +08:00
909d89a297 20250528 finished. 2025-05-28 14:15:13 +08:00
26bb74425e 20250527 finished. 2025-05-27 13:36:50 +08:00
1cafc5eca5 20250526 finished. 2025-05-26 15:02:22 +08:00
1a9ecb53eb 20250525 finished. 2025-05-25 17:00:43 +08:00
993535a05b 20250524 finished. 2025-05-24 17:34:51 +08:00
11ef8edf9d 20250523 finished. 2025-05-23 12:17:22 +08:00
9f65089c2d 20250523 finished. 2025-05-23 11:51:46 +08:00
4e6deb7aad 20250521 finished. 2025-05-21 11:01:48 +08:00
a3d73376bb 20250520 finished. 2025-05-20 15:26:01 +08:00
f838767e30 20250519 finished. 2025-05-19 10:22:08 +08:00
69ff07860e 20250518 finished. 2025-05-18 14:14:12 +08:00
1907feaa7a 20250517 finished. 2025-05-17 14:00:52 +08:00
ce641ab871 20250516 finished. 2025-05-16 15:15:41 +08:00
90bdc41ca6 20250515 finished. 2025-05-15 14:41:38 +08:00
fd2924d216 20250514 finished. 2025-05-14 14:27:36 +08:00
7b7d6ca26d 20250513 finished. 2025-05-13 16:02:00 +08:00
9232c689c4 20250512 finished. 2025-05-12 12:29:31 +08:00
ebc48df001 20250511 finished. 2025-05-11 15:49:43 +08:00
62515ef741 20250510 finished. 2025-05-10 14:46:15 +08:00
b8ba1dd234 20250509 finished. 2025-05-09 15:52:24 +08:00
3b7b699f31 20250508 finished. 2025-05-08 11:54:22 +08:00
b52d178f9e 20250507 finished. 2025-05-07 12:05:54 +08:00
8db7360972 20250506 finished. 2025-05-06 13:23:00 +08:00
b94d1bc1e7 20250505 finished. 2025-05-05 20:12:55 +08:00
706700c639 20250504 finished. 2025-05-04 14:59:51 +08:00
0cdca38ad9 20250503 finished. 2025-05-03 14:03:58 +08:00
c2b87c5f09 20250502 finished. 2025-05-02 15:20:42 +08:00
25f8703b39 20250501 finished. 2025-05-01 15:29:57 +08:00
879c2b775e 20250429 finished. 2025-04-29 12:12:33 +08:00
443c8fff12 20250427 finished. 2025-04-27 11:38:16 +08:00
ffa2553a37 20250426 finished. 2025-04-26 15:22:38 +08:00
338f74cb9e add 20250217 commit 2025-04-25 14:12:31 +08:00
5751d9d82e 20250217 finished. 2025-04-25 14:06:46 +08:00
45 changed files with 3057 additions and 0 deletions

View File

@@ -618,3 +618,89 @@ 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;
mod p2444_count_subarrays_with_fixed_bounds;
mod p3392_count_subarrays_of_length_three_with_a_condition;
mod p2302_count_subarrays_with_score_less_than_k;
mod p2962_count_subarrays_where_max_element_appears_at_least_k_times;
mod p2071_maximum_number_of_tasks_you_can_assign;
mod p838_push_dominoes;
mod p1007_minimum_domino_rotations_for_equal_row;
mod p1128_number_of_equivalent_domino_pairs;
mod p790_domino_and_tromino_tiling;
mod p1920_build_array_from_permutation;
mod p3341_find_minimum_time_to_reach_last_room_i;
mod p3342_find_minimum_time_to_reach_last_room_ii;
mod p3343_count_number_of_balanced_permutations;
mod p2918_minimum_equal_sum_of_two_arrays_after_replacing_zeros;
mod p1550_three_consecutive_odds;
mod p2094_finding_3_digit_even_numbers;
mod p3335_total_characters_in_string_after_transformations_i;
mod p3337_total_characters_in_string_after_transformations_ii;
mod p2900_longest_unequal_adjacent_groups_subsequence_i;
mod p2901_longest_unequal_adjacent_groups_subsequence_ii;
mod p75_sort_colors;
mod p1931_painting_a_grid_with_three_different_colors;
mod p3024_type_of_triangle;
mod p3355_zero_array_transformation_i;
mod p3356_zero_array_transformation_ii;
mod p3362_zero_array_transformation_iii;
mod p3068_find_the_maximum_sum_of_node_values;
mod p2942_find_words_containing_character;
mod p2131_longest_palindrome_by_concatenating_two_letter_words;
mod p1857_largest_color_value_in_a_directed_graph;
mod p2894_divisible_and_non_divisible_sums_difference;
mod p3372_maximize_the_number_of_target_nodes_after_connecting_trees_i;
mod p3373_maximize_the_number_of_target_nodes_after_connecting_trees_ii;
mod p2359_find_closest_node_to_given_two_nodes;
mod p2929_distribute_candies_among_children_ii;
mod p1298_maximum_candies_you_can_get_from_boxes;
mod p3403_find_the_lexicographically_largest_string_from_the_box_i;
mod p1061_lexicographically_smallest_equivalent_string;
mod p2434_using_a_robot_to_print_the_lexicographically_smallest_string;
mod p3170_lexicographically_minimum_string_after_removing_stars;
mod p386_lexicographical_numbers;
mod p440_k_th_smallest_in_lexicographical_order;
mod p3442_maximum_difference_between_even_and_odd_frequency_i;

View File

@@ -0,0 +1,63 @@
/**
* [1007] Minimum Domino Rotations For Equal Row
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn min_domino_rotations(tops: Vec<i32>, bottoms: Vec<i32>) -> i32 {
let sequence: Vec<(i32, i32)> = tops.into_iter().zip(bottoms.into_iter()).collect();
// 应该首先确定相同的值是多少
let mut value = 0;
if sequence[1..]
.iter()
.all(|(t, b)| *t == sequence[0].0 || *b == sequence[0].0)
{
value = sequence[0].0;
}
if sequence[1..]
.iter()
.all(|(t, b)| *t == sequence[0].1 || *b == sequence[0].1)
{
value = sequence[0].1;
}
if value == 0 {
return -1;
}
sequence
.iter()
.filter(|(t, b)| *t != value)
.count()
.min(sequence.iter().filter(|(t, b)| *b != value).count()) as i32
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1007() {
assert_eq!(
1,
Solution::min_domino_rotations(
vec![1, 2, 1, 1, 1, 2, 2, 2],
vec![2, 1, 2, 2, 2, 2, 2, 2]
)
);
assert_eq!(
2,
Solution::min_domino_rotations(vec![2, 1, 2, 4, 2, 2], vec![5, 2, 6, 2, 3, 2])
);
assert_eq!(
-1,
Solution::min_domino_rotations(vec![3, 5, 1, 2, 3], vec![3, 6, 3, 3, 4])
);
}
}

View File

@@ -0,0 +1,131 @@
/**
* [1061] Lexicographically Smallest Equivalent String
*/
pub struct Solution {}
// submission codes start here
/// Use union find set for this question
struct EquivalentSet {
parents: Vec<usize>,
min_values: Vec<usize>,
}
impl std::fmt::Debug for EquivalentSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "parents: \n")?;
for (i, &v) in self.parents.iter().enumerate() {
write!(
f,
"{} -> {}\n",
Self::convert_to_char(i),
Self::convert_to_char(v)
)?;
}
writeln!(f, "min_values:")?;
for (i, &v) in self.min_values.iter().enumerate() {
writeln!(
f,
"{} -> {}",
Self::convert_to_char(i),
Self::convert_to_char(v)
)?;
}
Ok(())
}
}
impl EquivalentSet {
fn new() -> Self {
Self {
// Only lower characters
parents: (0..26).collect(),
min_values: (0..26).collect(),
}
}
fn convert_to_char(c: usize) -> char {
(c as u8 + b'a') as char
}
fn find(&mut self, a: usize) -> (usize, usize) {
if self.parents[a] == a {
(a, self.min_values[a])
} else {
let (p, min_value) = self.find(self.parents[a]);
self.parents[a] = p;
self.min_values[a] = min_value;
(p, min_value)
}
}
fn merge(&mut self, a: usize, b: usize) {
let ((a_p, a_min_value), (b_p, b_min_value)) = (self.find(a), self.find(b));
let min_value = a_min_value.min(b_min_value).min(a).min(b);
self.parents[a_p] = b_p;
self.min_values[a_p] = min_value;
self.min_values[b_p] = min_value;
}
}
impl Solution {
pub fn smallest_equivalent_string(s1: String, s2: String, base_str: String) -> String {
let mut set = EquivalentSet::new();
for (a, b) in s1.bytes().zip(s2.bytes()) {
set.merge((a - b'a') as usize, (b - b'a') as usize);
}
String::from_utf8(
base_str
.bytes()
.map(|c| {
let (_, min_value) = set.find((c - b'a') as usize);
min_value as u8 + b'a'
})
.collect(),
)
.unwrap()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1061() {
assert_eq!(
"makkek",
Solution::smallest_equivalent_string(
"parker".to_string(),
"morris".to_string(),
"parser".to_string()
)
);
assert_eq!(
"hdld",
Solution::smallest_equivalent_string(
"hello".to_string(),
"world".to_string(),
"hold".to_string()
)
);
assert_eq!(
"aauaaaaada".to_string(),
Solution::smallest_equivalent_string(
"leetcode".to_string(),
"programs".to_string(),
"sourcecode".to_string()
)
);
}
}

View File

@@ -0,0 +1,58 @@
/**
* [1128] Number of Equivalent Domino Pairs
*/
pub struct Solution {}
// submission codes start here
use std::collections::HashMap;
impl Solution {
pub fn num_equiv_domino_pairs(dominoes: Vec<Vec<i32>>) -> i32 {
let mut map = HashMap::new();
let mut result = 0;
for card in dominoes.iter() {
let sum = card[0] * 10 + card[1];
if let Some(count) = map.get(&sum) {
result += *count;
}
let entry = map.entry(sum).or_insert(0);
*entry += 1;
let reverse_sum = card[1] * 10 + card[0];
if reverse_sum != sum {
let entry = map.entry(card[1] * 10 + card[0]).or_insert(0);
*entry += 1;
}
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1128() {
assert_eq!(
1,
Solution::num_equiv_domino_pairs(vec![vec![1, 2], vec![2, 1], vec![3, 4], vec![5, 6]])
);
assert_eq!(
3,
Solution::num_equiv_domino_pairs(vec![
vec![1, 2],
vec![1, 2],
vec![1, 1],
vec![1, 2],
vec![2, 2]
])
);
}
}

View File

@@ -0,0 +1,47 @@
use std::thread::current;
/**
* [1287] Element Appearing More Than 25% In Sorted Array
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn find_special_integer(arr: Vec<i32>) -> i32 {
let mut last = arr[0];
let mut count = 1;
let threshold = arr.len() / 4;
for &i in arr[1..].iter() {
if last == i {
count += 1;
} else {
last = i;
count = 1;
}
if count > threshold {
return i;
}
}
last
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1287() {
assert_eq!(
6,
Solution::find_special_integer(vec![1, 2, 2, 6, 6, 6, 6, 7, 10])
);
assert_eq!(1, Solution::find_special_integer(vec![1, 1]));
}
}

View File

@@ -0,0 +1,95 @@
/**
* [1298] Maximum Candies You Can Get from Boxes
*/
pub struct Solution {}
// submission codes start here
use std::collections::{HashSet, VecDeque};
use std::iter::FromIterator;
impl Solution {
pub fn max_candies(
status: Vec<i32>,
candies: Vec<i32>,
keys: Vec<Vec<i32>>,
contained_boxes: Vec<Vec<i32>>,
initial_boxes: Vec<i32>,
) -> i32 {
let mut result = 0;
let mut boxes_in_hand: HashSet<usize> =
HashSet::from_iter(initial_boxes.into_iter().map(|x| x as usize));
let mut can_open_boxes: HashSet<usize> =
HashSet::from_iter(status.iter().enumerate().filter_map(|(i, v)| {
if *v == 1 {
Some(i)
} else {
None
}
}));
let mut opened_boxes = HashSet::new();
let mut queue = VecDeque::new();
for &b in boxes_in_hand.iter().filter(|x| status[**x] == 1) {
queue.push_back(b);
opened_boxes.insert(b);
result += candies[b];
}
while let Some(b) = queue.pop_front() {
for &key in keys[b].iter() {
let key = key as usize;
can_open_boxes.insert(key);
if !opened_boxes.contains(&key) && boxes_in_hand.contains(&key) {
queue.push_back(key);
opened_boxes.insert(key);
result += candies[key];
}
}
for &new_box in contained_boxes[b].iter() {
let new_box = new_box as usize;
boxes_in_hand.insert(new_box);
if !opened_boxes.contains(&new_box) && can_open_boxes.contains(&new_box) {
queue.push_back(new_box);
opened_boxes.insert(new_box);
result += candies[new_box];
}
}
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1298() {
assert_eq!(
16,
Solution::max_candies(
vec![1, 0, 1, 0],
vec![7, 5, 4, 1000],
vec![vec![], vec![], vec![1], vec![]],
vec![vec![1, 2], vec![3], vec![], vec![]],
vec![0]
)
);
assert_eq!(
6,
Solution::max_candies(
vec![1, 0, 0, 0, 0, 0],
vec![1, 1, 1, 1, 1, 1],
vec![vec![1, 2, 3, 4, 5], vec![], vec![], vec![], vec![], vec![]],
vec![vec![1, 2, 3, 4, 5], vec![], vec![], vec![], vec![], vec![]],
vec![0]
)
);
}
}

View File

@@ -0,0 +1,42 @@
/**
* [1550] Three Consecutive Odds
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn three_consecutive_odds(arr: Vec<i32>) -> bool {
if arr.len() < 3 {
return false;
}
arr.iter()
.enumerate()
.skip(2)
.filter_map(|(i, &z)| {
if arr[i - 2] % 2 == 1 && arr[i - 1] % 2 == 1 && z % 2 == 1 {
Some(())
} else {
None
}
})
.next()
.is_some()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1550() {
assert!(!Solution::three_consecutive_odds(vec![2, 6, 4, 1]));
assert!(Solution::three_consecutive_odds(vec![
1, 2, 34, 3, 4, 5, 7, 23, 12
]));
}
}

View File

@@ -0,0 +1,98 @@
/**
* [1857] Largest Color Value in a Directed Graph
*/
pub struct Solution {}
// submission codes start here
use std::collections::{HashMap, VecDeque};
use std::iter::FromIterator;
impl Solution {
pub fn largest_path_value(colors: String, edges: Vec<Vec<i32>>) -> i32 {
let colors: Vec<usize> = colors.bytes().map(|x| (x - b'a') as usize).collect();
let mut adjacency_matrix = vec![vec![]; colors.len()];
// 入度节点
let mut in_degrees = vec![0; colors.len()];
for edge in edges.iter() {
let start = edge[0] as usize;
let end = edge[1] as usize;
adjacency_matrix[start].push(end);
in_degrees[end] += 1;
}
// 使用拓扑排序判断是否有环
// 同时获得一个拓扑序列表
let mut queue = VecDeque::from_iter(in_degrees.iter().enumerate().filter_map(|(i, v)| {
if *v == 0 {
Some(i)
} else {
None
}
}));
let mut topology_list = vec![];
while let Some(head) = queue.pop_front() {
topology_list.push(head);
for &next in adjacency_matrix[head].iter() {
in_degrees[next] -= 1;
if in_degrees[next] == 0 {
queue.push_back(next);
}
}
}
if in_degrees.iter().any(|x| *x != 0) {
return -1;
}
// dp[i][c]表示从节点i开始路径上颜色为c的计数
// 颜色只能是小写字母
let mut dp = vec![vec![0; 26]; topology_list.len()];
let mut result = HashMap::new();
for &node in topology_list.iter().rev() {
let c = colors[node];
for &next in adjacency_matrix[node].iter() {
for i in 0..26 {
dp[node][i] = dp[node][i].max(dp[next][i]);
}
dp[node][c] = dp[node][c].max(dp[next][c] + 1);
let entry = result.entry(c).or_insert(0);
*entry = dp[node][c].max(*entry);
}
if adjacency_matrix[node].is_empty() {
dp[node][c] = 1;
}
}
result.values().max().map_or_else(|| 1, |x| *x)
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1857() {
assert_eq!(
3,
Solution::largest_path_value(
"abaca".to_string(),
vec![vec![0, 1], vec![0, 2], vec![2, 3], vec![3, 4]]
)
);
assert_eq!(
-1,
Solution::largest_path_value("a".to_string(), vec![vec![0, 0]])
);
}
}

View File

@@ -0,0 +1,31 @@
/**
* [1920] Build Array from Permutation
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn build_array(nums: Vec<i32>) -> Vec<i32> {
nums.iter().map(|x| nums[*x as usize]).collect()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1920() {
assert_eq!(
vec![0, 1, 2, 4, 5, 3],
Solution::build_array(vec![0, 2, 1, 5, 3, 4])
);
assert_eq!(
vec![4, 5, 0, 1, 2, 3],
Solution::build_array(vec![5, 0, 1, 2, 3, 4])
);
}
}

View File

@@ -0,0 +1,91 @@
/**
* [1931] Painting a Grid With Three Different Colors
*/
pub struct Solution {}
// submission codes start here
use std::collections::HashMap;
const MOD: i32 = 1_000_000_007;
impl Solution {
pub fn color_the_grid(m: i32, n: i32) -> i32 {
let mut mask_count = 3_usize.pow(m as u32);
// 存储一行的所有合法涂色方式
// key表示mask
// value表示实际的涂色数组
let mut valid_masks = HashMap::new();
for mask in 0..mask_count {
let mut color = vec![];
let mut m_mask = mask;
for _ in 0..m {
color.push(m_mask % 3);
m_mask = m_mask / 3;
}
if color.iter().skip(1).zip(color.iter()).all(|(x, y)| x != y) {
valid_masks.insert(mask, color);
}
}
// 预处理相邻行的合法表示
let mut adjacent_valid_masks = HashMap::new();
for (&mask1, color1) in valid_masks.iter() {
for (&mask2, color2) in valid_masks.iter() {
if color1.iter().zip(color2.iter()).all(|(x, y)| x != y) {
let entry = adjacent_valid_masks.entry(mask1).or_insert(vec![]);
entry.push(mask2)
}
}
}
// 滚动的DP数组
let mut dp = vec![0; mask_count];
// 初始化为第一行
for &mask in valid_masks.keys() {
dp[mask] = 1;
}
for _ in 1..n {
let mut next_dp = vec![0; mask_count];
for &next_mask in valid_masks.keys() {
for &mask in adjacent_valid_masks.get(&next_mask).unwrap() {
next_dp[next_mask] += dp[mask];
if next_dp[next_mask] >= MOD {
next_dp[next_mask] -= MOD;
}
}
}
dp = next_dp;
}
dp.into_iter().fold(0, |sum, i| {
if sum + i >= MOD {
sum + i - MOD
} else {
sum + i
}
})
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1931() {
assert_eq!(3, Solution::color_the_grid(1, 1));
assert_eq!(6, Solution::color_the_grid(1, 2));
assert_eq!(580986, Solution::color_the_grid(5, 5));
}
}

View File

@@ -0,0 +1,108 @@
/**
* [2071] Maximum Number of Tasks You Can Assign
*/
pub struct Solution {}
// submission codes start here
use std::collections::VecDeque;
impl Solution {
pub fn max_task_assign(
mut tasks: Vec<i32>,
mut workers: Vec<i32>,
pills: i32,
strength: i32,
) -> i32 {
let (n, m) = (tasks.len(), workers.len());
tasks.sort_unstable();
workers.sort_unstable();
let check = |middle: usize| -> bool {
// 注意middle的溢出问题
if middle < 1 {
return true;
}
let mut p = pills;
let mut worker_queue = VecDeque::new();
let mut ptr = m - 1;
for i in (0..=middle - 1).rev() {
while ptr >= m - middle && workers[ptr] + strength >= tasks[i] {
worker_queue.push_front(workers[ptr]);
if ptr == 0 {
break;
}
ptr -= 1;
}
if worker_queue.is_empty() {
return false;
}
let last = worker_queue.back().unwrap();
if *last >= tasks[i] {
worker_queue.pop_back();
} else {
if p == 0 {
return false;
}
p -= 1;
worker_queue.pop_front();
}
}
return true;
};
let (mut left, mut right) = (1, m.min(n));
let mut result = 0;
while left <= right {
let middle = (left + right) / 2;
if check(middle) {
result = middle;
left = middle + 1;
} else {
right = middle - 1;
}
}
result as i32
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2071() {
assert_eq!(
1,
Solution::max_task_assign(vec![35], vec![83, 20, 4, 66], 3, 41)
);
assert_eq!(
3,
Solution::max_task_assign(vec![3, 2, 1], vec![0, 3, 3], 1, 1)
);
assert_eq!(
1,
Solution::max_task_assign(vec![5, 4], vec![0, 0, 0], 1, 5)
);
assert_eq!(
2,
Solution::max_task_assign(vec![10, 15, 30], vec![0, 10, 10, 10, 10], 3, 10)
);
assert_eq!(
3,
Solution::max_task_assign(vec![5, 9, 8, 5, 9], vec![1, 6, 4, 2, 6], 1, 5)
);
}
}

View File

@@ -0,0 +1,64 @@
/**
* [2094] Finding 3-Digit Even Numbers
*/
pub struct Solution {}
// submission codes start here
use std::collections::HashSet;
impl Solution {
pub fn find_even_numbers(digits: Vec<i32>) -> Vec<i32> {
let mut result = HashSet::new();
for (x, first) in
digits
.iter()
.enumerate()
.filter_map(|(i, &x)| if x != 0 { Some((i, x)) } else { None })
{
for (y, second) in
digits
.iter()
.enumerate()
.filter_map(|(i, &y)| if i != x { Some((i, y)) } else { None })
{
for third in digits.iter().enumerate().filter_map(|(i, &z)| {
if i != x && i != y && z % 2 == 0 {
Some(z)
} else {
None
}
}) {
result.insert(first * 100 + second * 10 + third);
}
}
}
let mut result: Vec<i32> = result.into_iter().collect();
result.sort_unstable();
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2094() {
assert_eq!(
vec![102, 120, 130, 132, 210, 230, 302, 310, 312, 320],
Solution::find_even_numbers(vec![2, 1, 3, 0])
);
assert_eq!(
vec![222, 228, 282, 288, 822, 828, 882],
Solution::find_even_numbers(vec![2, 2, 8, 8, 2])
);
assert_eq!(
Vec::<i32>::new(),
Solution::find_even_numbers(vec![3, 7, 5])
);
}
}

View File

@@ -0,0 +1,84 @@
/**
* [2131] Longest Palindrome by Concatenating Two Letter Words
*/
pub struct Solution {}
// submission codes start here
use std::collections::HashMap;
impl Solution {
pub fn longest_palindrome(words: Vec<String>) -> i32 {
let mut counter = HashMap::new();
let mut same_counter = HashMap::new();
for word in words.iter() {
let mut chars = word.bytes();
let first = (chars.next().unwrap() - b'a') as i32;
let second = (chars.next().unwrap() - b'a') as i32;
if first < second {
let hash = first * 26 + second;
let entry = counter.entry(hash).or_insert((0, 0));
entry.0 += 1;
} else if first > second {
let hash = second * 26 + first;
let entry = counter.entry(hash).or_insert((0, 0));
entry.1 += 1;
} else {
let entry = same_counter.entry(first).or_insert(0);
*entry += 1;
}
}
// 对于两个不同的字符
// 取计数的最小值
let mut result: i32 = counter
.values()
.filter_map(|&(x, y)| Some(x.min(y) * 4))
.sum();
// 对于两个相同的字符
// 如果成对就可以加入答案
result += same_counter
.values()
.filter_map(|&v| Some(v / 2 * 4))
.sum::<i32>();
// 再判断是否有落单的相同字符放在中间
// 注意只能放一次
result += same_counter
.values()
.filter_map(|&v| if v % 2 != 0 { Some(()) } else { None })
.next()
.map_or(0, |()| 2);
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2131() {
assert_eq!(
6,
Solution::longest_palindrome(vec_string!("aa", "aa", "aa"))
);
assert_eq!(
6,
Solution::longest_palindrome(vec_string!["lc", "cl", "gg"])
);
assert_eq!(
8,
Solution::longest_palindrome(vec_string!["ab", "ty", "yt", "lc", "cl", "ab"])
);
assert_eq!(
2,
Solution::longest_palindrome(vec_string!["ll", "cc", "xx"])
);
}
}

View File

@@ -0,0 +1,48 @@
/**
* [2302] Count Subarrays With Score Less Than K
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn count_subarrays(nums: Vec<i32>, k: i64) -> i64 {
let n = nums.len();
let (mut result, mut total_sum) = (0, 0);
let mut left = 0;
for right in 0..n {
total_sum += nums[right] as i64;
while left <= right && total_sum * ((right - left + 1) as i64) >= k {
total_sum -= nums[left] as i64;
left += 1;
}
result += (right as i64 - left as i64) + 1;
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2302() {
assert_eq!(
3,
Solution::count_subarrays(
vec![9, 5, 3, 8, 4, 7, 2, 7, 4, 5, 4, 9, 1, 4, 8, 10, 8, 4, 7],
4
)
);
assert_eq!(6, Solution::count_subarrays(vec![2, 1, 4, 3, 5], 10));
assert_eq!(5, Solution::count_subarrays(vec![1, 1, 1], 5));
}
}

View File

@@ -0,0 +1,73 @@
use std::convert::TryInto;
/**
* [2359] Find Closest Node to Given Two Nodes
*/
pub struct Solution {}
// submission codes start here
use std::collections::{HashSet, VecDeque};
impl Solution {
pub fn closest_meeting_node(edges: Vec<i32>, node1: i32, node2: i32) -> i32 {
let edges: Vec<Option<usize>> = edges.into_iter().map(|x| x.try_into().ok()).collect();
let distances1 = Self::search_distances(&edges, node1 as usize);
let distances2 = Self::search_distances(&edges, node2 as usize);
let mut result: Option<(usize, i32)> = None;
for i in 0..edges.len() {
if distances1[i] == i32::MAX || distances2[i] == i32::MAX {
continue;
}
let distance = distances1[i].max(distances2[i]);
if let Some((pos, d)) = result {
if distance < d {
result = Some((i, distance));
}
} else {
result = Some((i, distance));
}
}
result.map_or(-1, |x| x.0 as i32)
}
fn search_distances(edges: &Vec<Option<usize>>, node: usize) -> Vec<i32> {
let mut distances = vec![i32::MAX; edges.len()];
let mut queue = VecDeque::new();
let mut visited = HashSet::new();
queue.push_back((node, 0));
while let Some((pos, d)) = queue.pop_front() {
if !visited.insert(pos) {
continue;
}
distances[pos] = d;
if let Some(next) = edges[pos] {
queue.push_back((next, d + 1));
}
}
distances
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2359() {
assert_eq!(2, Solution::closest_meeting_node(vec![2, 2, 3, -1], 0, 1));
assert_eq!(2, Solution::closest_meeting_node(vec![1, 2, -1], 0, 2));
}
}

View File

@@ -0,0 +1,59 @@
/**
* [2434] Using a Robot to Print the Lexicographically Smallest String
*/
pub struct Solution {}
// submission codes start here
use std::collections::HashMap;
impl Solution {
pub fn robot_with_string(s: String) -> String {
let s: Vec<u8> = s.bytes().collect();
let mut character_map = HashMap::new();
for &c in s.iter() {
let entry = character_map.entry(c).or_insert(0);
*entry += 1;
}
// The Minimal value in the s.
let mut min_character = b'a';
let mut result = Vec::with_capacity(s.len());
let mut buffer = Vec::with_capacity(s.len());
for &c in s.iter() {
buffer.push(c);
*character_map.get_mut(&c).unwrap() -= 1;
// Find the minimal value in the s.
while min_character != b'z' && character_map.get(&min_character).is_none_or(|x| *x == 0)
{
min_character += 1;
}
while let Some(&head) = buffer.last() {
if head <= min_character {
result.push(head);
buffer.pop();
} else {
break;
}
}
}
String::from_utf8(result).unwrap()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2434() {
assert_eq!("azz", Solution::robot_with_string("zza".to_string()));
assert_eq!("abc", Solution::robot_with_string("bac".to_string()));
}
}

View File

@@ -0,0 +1,56 @@
/**
* [2444] Count Subarrays With Fixed Bounds
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn count_subarrays(nums: Vec<i32>, min_k: i32, max_k: i32) -> i64 {
let mut result = 0;
let (mut border, mut last_min, mut last_max) = (None, None, None);
for i in 0..nums.len() {
if nums[i] < min_k || nums[i] > max_k {
last_max = None;
last_min = None;
border = Some(i);
}
if nums[i] == min_k {
last_min = Some(i);
}
if nums[i] == max_k {
last_max = Some(i);
}
if let Some(last_min) = last_min {
if let Some(last_max) = last_max {
let current = if let Some(border) = border {
last_min.min(last_max) - border
} else {
last_min.min(last_max) + 1
};
result += current as i64
}
}
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2444() {
assert_eq!(2, Solution::count_subarrays(vec![1, 3, 5, 2, 7, 5], 1, 5));
assert_eq!(10, Solution::count_subarrays(vec![1, 1, 1, 1], 1, 1));
}
}

View File

@@ -0,0 +1,31 @@
/**
* [2894] Divisible and Non-divisible Sums Difference
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn difference_of_sums(n: i32, m: i32) -> i32 {
(1..=n)
.filter_map(|x| if x % m != 0 { Some(x) } else { None })
.sum::<i32>()
- (1..=n)
.filter_map(|x| if x % m == 0 { Some(x) } else { None })
.sum::<i32>()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2894() {
assert_eq!(19, Solution::difference_of_sums(10, 3));
assert_eq!(15, Solution::difference_of_sums(5, 6));
assert_eq!(-15, Solution::difference_of_sums(5, 1));
}
}

View File

@@ -0,0 +1,43 @@
/**
* [2900] Longest Unequal Adjacent Groups Subsequence I
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn get_longest_subsequence(words: Vec<String>, groups: Vec<i32>) -> Vec<String> {
let mut result = vec![words[0].clone()];
let mut last_number = groups[0];
for i in 1..groups.len() {
if groups[i] != last_number {
result.push(words[i].clone());
}
last_number = groups[i];
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2900() {
assert_eq!(
vec_string!("e", "b"),
Solution::get_longest_subsequence(vec_string!("e", "a", "b"), vec![0, 0, 1])
);
assert_eq!(
vec_string!("a", "b", "c"),
Solution::get_longest_subsequence(vec_string!("a", "b", "c", "d"), vec![1, 0, 1, 1])
);
}
}

View File

@@ -0,0 +1,87 @@
/**
* [2901] Longest Unequal Adjacent Groups Subsequence II
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn get_words_in_longest_subsequence(words: Vec<String>, groups: Vec<i32>) -> Vec<String> {
let n = words.len();
let mut dp = vec![1; n];
let mut next_pos = vec![None; n];
for i in 1..n {
for j in 0..i {
if groups[i] == groups[j] {
continue;
}
if words[i].len() != words[j].len() {
continue;
}
if Self::calculate_hamming_distance(words[i].as_str(), words[j].as_str()) != 1 {
continue;
}
if dp[j] + 1 > dp[i] {
dp[i] = dp[j] + 1;
next_pos[i] = Some(j);
}
}
}
let max_pos = dp.iter().enumerate().max_by_key(|x| x.1).unwrap();
let mut pos = max_pos.0;
let mut result = vec![words[pos].clone()];
while let Some(p) = next_pos[pos] {
result.push(words[p].clone());
pos = p;
}
result.into_iter().rev().collect()
}
// 计算字符串之间的汉明距
// 两个字符串需要等长
fn calculate_hamming_distance(a: &str, b: &str) -> usize {
a.bytes()
.zip(b.bytes())
.filter_map(|(x, y)| if x == y { None } else { Some(()) })
.count()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2901() {
assert_eq!(
vec_string!("dc", "dd", "da"),
Solution::get_words_in_longest_subsequence(
vec_string!("bad", "dc", "bc", "ccd", "dd", "da", "cad", "dba", "aba"),
vec![9, 7, 1, 2, 6, 8, 3, 7, 2]
)
);
assert_eq!(
vec_string!("bab", "cab"),
Solution::get_words_in_longest_subsequence(
vec_string!("bab", "dab", "cab"),
vec![1, 2, 2]
)
);
assert_eq!(
vec_string!("a", "b", "c", "d"),
Solution::get_words_in_longest_subsequence(
vec_string!("a", "b", "c", "d"),
vec![1, 2, 3, 4]
)
);
}
}

View File

@@ -0,0 +1,47 @@
/**
* [2918] Minimum Equal Sum of Two Arrays After Replacing Zeros
*/
pub struct Solution {}
// submission codes start here
use std::cmp::Ordering;
impl Solution {
pub fn min_sum(nums1: Vec<i32>, nums2: Vec<i32>) -> i64 {
let mut nums1_sum: i64 = nums1.iter().map(|x| *x as i64).sum();
let mut nums2_sum: i64 = nums2.iter().map(|x| *x as i64).sum();
let nums1_zero_count = nums1.iter().filter(|x| **x == 0).count() as i64;
let nums2_zero_count = nums2.iter().filter(|x| **x == 0).count() as i64;
match (nums1_sum + nums1_zero_count).cmp(&(nums2_sum + nums2_zero_count)) {
Ordering::Less => {
if nums1_zero_count == 0 {
-1
} else {
nums2_sum + nums2_zero_count
}
}
Ordering::Greater => {
if nums2_zero_count == 0 {
-1
} else {
nums1_sum + nums1_zero_count
}
}
Ordering::Equal => nums1_sum + nums1_zero_count,
}
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2918() {
assert_eq!(12, Solution::min_sum(vec![3, 2, 0, 1, 0], vec![6, 5, 0]));
assert_eq!(-1, Solution::min_sum(vec![2, 0, 2, 0], vec![1, 4]));
}
}

View File

@@ -0,0 +1,31 @@
/**
* [2929] Distribute Candies Among Children II
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn distribute_candies(n: i32, limit: i32) -> i64 {
// 0 <= i <= min(n, limit)
// 0 <= j <= min(n, limit)
// 0 <= n - i - j <= min(n, limit) -> i + j <= n
let (n, limit) = (n as i64, limit as i64);
(0..=n.min(limit))
.map(|i| (limit.min(n - i) - (n - limit - i).max(0) + 1).max(0))
.sum()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2929() {
assert_eq!(3, Solution::distribute_candies(5, 2));
assert_eq!(10, Solution::distribute_candies(3, 3));
}
}

View File

@@ -0,0 +1,39 @@
/**
* [2942] Find Words Containing Character
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn find_words_containing(words: Vec<String>, x: char) -> Vec<i32> {
words
.iter()
.enumerate()
.filter_map(|(i, v)| if v.contains(x) { Some(i as i32) } else { None })
.collect()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2942() {
assert_eq!(
vec![0, 1],
Solution::find_words_containing(vec_string!("leet", "code"), 'e')
);
assert_eq!(
vec![0, 2],
Solution::find_words_containing(vec_string!("abc", "bcd", "aaaa", "cbc"), 'a')
);
assert_eq!(
Vec::<i32>::new(),
Solution::find_words_containing(vec_string!("abc", "bcd", "aaaa", "cbc"), 'z'),
);
}
}

View File

@@ -0,0 +1,49 @@
/**
* [2962] Count Subarrays Where Max Element Appears at Least K Times
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn count_subarrays(nums: Vec<i32>, k: i32) -> i64 {
let max = *nums.iter().max().unwrap();
let n = nums.len();
let mut result = 0;
let mut count = 0;
let mut left = 0;
for right in 0..n {
count += if nums[right] == max { 1 } else { 0 };
if count >= k {
result += (n - right) as i64;
}
while left <= right && count >= k {
count -= if nums[left] == max { 1 } else { 0 };
if count >= k {
result += (n - right) as i64;
}
left += 1;
}
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2962() {
assert_eq!(6, Solution::count_subarrays(vec![1, 3, 2, 3, 3], 2));
assert_eq!(0, Solution::count_subarrays(vec![1, 4, 2, 1], 3));
}
}

View File

@@ -0,0 +1,40 @@
/**
* [3024] Type of Triangle
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn triangle_type(nums: Vec<i32>) -> String {
if nums[0] + nums[1] <= nums[2]
|| nums[0] + nums[2] <= nums[1]
|| nums[1] + nums[2] <= nums[0]
{
return "none".to_string();
}
if nums[0] == nums[1] || nums[0] == nums[2] || nums[1] == nums[2] {
if nums[0] == nums[1] && nums[1] == nums[2] {
"equilateral".to_string()
} else {
"isosceles".to_string()
}
} else {
"scalene".to_string()
}
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3024() {
assert_eq!("equilateral", Solution::triangle_type(vec![3, 3, 3]));
assert_eq!("scalene", Solution::triangle_type(vec![3, 4, 5]));
}
}

View File

@@ -0,0 +1,53 @@
/**
* [3068] Find the Maximum Sum of Node Values
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn maximum_value_sum(nums: Vec<i32>, k: i32, _: Vec<Vec<i32>>) -> i64 {
let mut result: i64 = nums.iter().map(|x| *x as i64).sum();
let mut difference: Vec<i64> = nums.iter().map(|&x| ((x ^ k) - x) as i64).collect();
difference.sort_unstable_by(|a, b| b.cmp(a));
for pair in difference.chunks(2) {
let sum: i64 = pair.iter().sum();
if pair.len() != 2 || sum < 0 {
break;
}
result += sum;
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3068() {
assert_eq!(
6,
Solution::maximum_value_sum(vec![1, 2, 1], 3, vec![vec![0, 1], vec![0, 2]])
);
assert_eq!(
9,
Solution::maximum_value_sum(vec![2, 3], 7, vec![vec![0, 1]])
);
assert_eq!(
42,
Solution::maximum_value_sum(
vec![7; 6],
3,
vec![vec![0, 1], vec![0, 2], vec![0, 3], vec![0, 4], vec![0, 5]]
)
);
}
}

View File

@@ -0,0 +1,73 @@
/**
* [3170] Lexicographically Minimum String After Removing Stars
*/
pub struct Solution {}
// submission codes start here
use std::cmp::Ordering;
use std::collections::BinaryHeap;
#[derive(Eq, PartialEq)]
struct CharacterPos {
char: u8,
pos: usize,
}
impl Ord for CharacterPos {
fn cmp(&self, other: &Self) -> Ordering {
match other.char.cmp(&self.char) {
Ordering::Equal => self.pos.cmp(&other.pos),
Ordering::Greater => Ordering::Greater,
Ordering::Less => Ordering::Less,
}
}
}
impl PartialOrd for CharacterPos {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Solution {
pub fn clear_stars(s: String) -> String {
// Use the binary head to store the minimal and nearest character.
let mut heap = BinaryHeap::new();
// The array stores the tuple (character, is_removed).
let mut buffer: Vec<(u8, bool)> = s.bytes().map(|x| (x, false)).collect();
for (i, v) in s.bytes().enumerate() {
if v != b'*' {
heap.push(CharacterPos { char: v, pos: i });
} else {
// Remove the star character firstly.
buffer.get_mut(i).unwrap().1 = true;
// Then find the nearest and minimal character.
let head = heap.pop().unwrap();
buffer.get_mut(head.pos).unwrap().1 = true;
}
}
String::from_utf8(
buffer
.into_iter()
.filter_map(|(c, f)| if f { None } else { Some(c) })
.collect(),
)
.unwrap()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3170() {
assert_eq!("aab", Solution::clear_stars("aaba*".to_string()));
assert_eq!("abc", Solution::clear_stars("abc".to_string()));
}
}

View File

@@ -0,0 +1,64 @@
/**
* [3335] Total Characters in String After Transformations I
*/
pub struct Solution {}
// submission codes start here
const MOD: i32 = 1_000_000_007;
impl Solution {
pub fn length_after_transformations(s: String, t: i32) -> i32 {
let mut map = vec![0; 26];
for c in s.bytes() {
map[(c - b'a') as usize] += 1;
}
let mut result = s.bytes().len() as i32;
for _ in 0..t {
let z_count = map[25];
for c in (0..25).rev() {
if map[c] != 0 {
map[c + 1] = (map[c + 1] + map[c]) % MOD;
map[c] = 0;
}
}
if z_count != 0 {
map[0] = (map[0] + z_count) % MOD;
map[1] = (map[1] + z_count) % MOD;
result = (result + z_count) % MOD;
map[25] = (map[25] + MOD - z_count) % MOD;
}
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3335() {
assert_eq!(
7,
Solution::length_after_transformations("abcyy".to_string(), 2)
);
assert_eq!(
5,
Solution::length_after_transformations("azbk".to_string(), 1)
);
assert_eq!(
79033769,
Solution::length_after_transformations("jqktcurgdvlibczdsvnsg".to_string(), 7517)
);
}
}

View File

@@ -0,0 +1,132 @@
/**
* [3337] Total Characters in String After Transformations II
*/
pub struct Solution {}
// submission codes start here
use std::ops::Mul;
const LENGTH: usize = 26;
const MOD: i64 = 1_000_000_007;
#[derive(Debug, Copy, Clone)]
struct Matrix {
array: [[i64; LENGTH]; LENGTH],
}
impl Matrix {
fn new() -> Self {
Self {
array: [[0; LENGTH]; LENGTH],
}
}
fn unit_matrix() -> Self {
let mut matrix = Self::new();
for i in 0..LENGTH {
matrix.array[i][i] = 1;
}
matrix
}
fn quick_multiply(&self, mut y: i64) -> Self {
let mut result = Self::unit_matrix();
let mut current = self.clone();
while y > 0 {
if y & 1 == 1 {
result = result * current;
}
current = current * current;
y >>= 1;
}
result
}
}
impl Mul for Matrix {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
let mut result = Self::new();
for i in 0..LENGTH {
for j in 0..LENGTH {
for k in 0..LENGTH {
result.array[i][j] =
(result.array[i][j] + self.array[i][k] * rhs.array[k][j]) % MOD;
}
}
}
result
}
}
impl Solution {
pub fn length_after_transformations(s: String, t: i32, nums: Vec<i32>) -> i32 {
let mut t_matrix = Matrix::new();
for i in 0..LENGTH {
for j in 1..=nums[i] {
let j = j as usize;
t_matrix.array[(i + j) % LENGTH][i] = 1;
}
}
let transfer_matrix = t_matrix.quick_multiply(t as i64);
let mut result = 0;
let mut chars = [0; LENGTH];
for c in s.bytes() {
chars[(c - b'a') as usize] += 1;
}
for i in 0..LENGTH {
for j in 0..LENGTH {
result = (result + transfer_matrix.array[i][j] * chars[j]) % MOD;
}
}
result as i32
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3337() {
assert_eq!(
5,
Solution::length_after_transformations(
"abcyy".to_owned(),
1,
vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]
)
);
assert_eq!(
7,
Solution::length_after_transformations(
"abcyy".to_owned(),
2,
vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]
)
);
assert_eq!(
8,
Solution::length_after_transformations(
"azbk".to_string(),
1,
vec![2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
)
);
}
}

View File

@@ -0,0 +1,87 @@
/**
* [3341] Find Minimum Time to Reach Last Room I
*/
pub struct Solution {}
// submission codes start here
use std::cmp::Ordering;
use std::collections::BinaryHeap;
const DIRECTIONS: [(isize, isize); 4] = [(0, 1), (1, 0), (-1, 0), (0, -1)];
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord)]
struct State {
x: usize,
y: usize,
distance: i32,
}
impl State {
fn new(x: usize, y: usize, distance: i32) -> Self {
Self { x, y, distance }
}
}
impl PartialOrd for State {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
// BinaryHeap是大顶堆
Some(other.distance.cmp(&self.distance))
}
}
impl Solution {
pub fn min_time_to_reach(move_time: Vec<Vec<i32>>) -> i32 {
let n = move_time.len();
let m = move_time[0].len();
let mut distances = vec![vec![i32::MAX; m]; n];
let mut visited = vec![vec![false; m]; n];
let mut heap = BinaryHeap::new();
distances[0][0] = 0;
heap.push(State::new(0, 0, 0));
while let Some(head) = heap.pop() {
if visited[head.x][head.y] {
continue;
}
visited[head.x][head.y] = true;
for &(dx, dy) in DIRECTIONS.iter() {
let next = head
.x
.checked_add_signed(dx)
.and_then(|x| head.y.checked_add_signed(dy).and_then(|y| Some((x, y))))
.filter(|(x, y)| x < &n && y < &m);
if let Some((x, y)) = next {
let distance = distances[head.x][head.y].max(move_time[x][y]) + 1;
if distances[x][y] > distance {
distances[x][y] = distance;
heap.push(State::new(x, y, distance));
}
}
}
}
distances[n - 1][m - 1]
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3341() {
assert_eq!(6, Solution::min_time_to_reach(vec![vec![0, 4], vec![4, 4]]));
assert_eq!(
3,
Solution::min_time_to_reach(vec![vec![0, 0, 0], vec![0, 0, 0]])
);
assert_eq!(3, Solution::min_time_to_reach(vec![vec![0, 1], vec![1, 2]]));
}
}

View File

@@ -0,0 +1,94 @@
/**
* [3342] Find Minimum Time to Reach Last Room II
*/
pub struct Solution {}
// submission codes start here
use std::cmp::Ordering;
use std::collections::BinaryHeap;
const DIRECTIONS: [(isize, isize); 4] = [(0, 1), (1, 0), (-1, 0), (0, -1)];
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord)]
struct State {
x: usize,
y: usize,
distance: i32,
index: i32,
}
impl State {
fn new(x: usize, y: usize, distance: i32, index: i32) -> Self {
Self {
x,
y,
distance,
index,
}
}
}
impl PartialOrd for State {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
// BinaryHeap是大顶堆
Some(other.distance.cmp(&self.distance))
}
}
impl Solution {
pub fn min_time_to_reach(move_time: Vec<Vec<i32>>) -> i32 {
let n = move_time.len();
let m = move_time[0].len();
let mut distances = vec![vec![i32::MAX; m]; n];
let mut visited = vec![vec![false; m]; n];
let mut heap = BinaryHeap::new();
distances[0][0] = 0;
heap.push(State::new(0, 0, 0, 0));
while let Some(head) = heap.pop() {
if visited[head.x][head.y] {
continue;
}
visited[head.x][head.y] = true;
for &(dx, dy) in DIRECTIONS.iter() {
let next = head
.x
.checked_add_signed(dx)
.and_then(|x| head.y.checked_add_signed(dy).and_then(|y| Some((x, y))))
.filter(|(x, y)| x < &n && y < &m);
if let Some((x, y)) = next {
let distance = distances[head.x][head.y].max(move_time[x][y])
+ if head.index % 2 == 0 { 1 } else { 2 };
if distances[x][y] > distance {
distances[x][y] = distance;
heap.push(State::new(x, y, distance, head.index + 1));
}
}
}
}
distances[n - 1][m - 1]
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3342() {
assert_eq!(7, Solution::min_time_to_reach(vec![vec![0, 4], vec![4, 4]]));
assert_eq!(
6,
Solution::min_time_to_reach(vec![vec![0, 0, 0, 0], vec![0, 0, 0, 0]])
);
assert_eq!(4, Solution::min_time_to_reach(vec![vec![0, 1], vec![1, 2]]));
}
}

View File

@@ -0,0 +1,92 @@
/**
* [3343] Count Number of Balanced Permutations
*/
pub struct Solution {}
// submission codes start here
const MOD: usize = 1_000_000_007;
impl Solution {
pub fn count_balanced_permutations(num: String) -> i32 {
let num_array: Vec<usize> = num.bytes().map(|c| (c - b'0') as usize).collect();
let n = num_array.len();
let sum: usize = num_array.iter().sum();
if sum % 2 != 0 {
return 0;
}
let mut count = vec![0; 10];
for &i in num_array.iter() {
count[i] += 1;
}
let target = sum / 2;
let max_odd_count = (n + 1) / 2;
let mut combinations = vec![vec![0; max_odd_count + 1]; max_odd_count + 1];
let mut dp = vec![vec![0; max_odd_count + 1]; target + 1];
for i in 0..=max_odd_count {
combinations[i][i] = 1;
combinations[i][0] = 1;
for j in 1..i {
combinations[i][j] = (combinations[i - 1][j] + combinations[i - 1][j - 1]) % MOD;
}
}
dp[0][0] = 1;
let mut prefix = 0;
let mut total_sum = 0;
for i in 0..=9 {
prefix += count[i];
total_sum += i * count[i];
for odd in (prefix
.checked_sub(n - max_odd_count)
.or_else(|| Some(0))
.unwrap()..=prefix.min(max_odd_count))
.rev()
{
let even = prefix - odd;
for current in (total_sum.checked_sub(target).or_else(|| Some(0)).unwrap()
..=total_sum.min(target))
.rev()
{
let mut result = 0;
let mut j = count[i].checked_sub(even).or_else(|| Some(0)).unwrap();
while j <= count[i].min(odd) && i * j <= current {
let ways = combinations[odd][j] * combinations[even][count[i] - j] % MOD;
result = (result + ways * dp[current - i * j][odd - j] % MOD) % MOD;
j += 1;
}
dp[current][odd] = result % MOD;
}
}
}
dp[target][max_odd_count] as i32
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3343() {
assert_eq!(2, Solution::count_balanced_permutations("123".to_string()));
assert_eq!(1, Solution::count_balanced_permutations("112".to_string()));
assert_eq!(
0,
Solution::count_balanced_permutations("12345".to_string())
);
}
}

View File

@@ -0,0 +1,50 @@
/**
* [3355] Zero Array Transformation I
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn is_zero_array(nums: Vec<i32>, queries: Vec<Vec<i32>>) -> bool {
let n = nums.len();
let mut difference_array = vec![0; n + 1];
for query in queries {
let left = query[0] as usize;
let right = query[1] as usize;
difference_array[left] += 1;
difference_array[right + 1] -= 1;
}
let mut prefix_sum = difference_array[0];
for i in 1..=n {
if prefix_sum < nums[i - 1] {
return false;
}
prefix_sum += difference_array[i];
}
true
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3355() {
assert!(Solution::is_zero_array(vec![1, 0, 1], vec![vec![0, 2]]));
assert!(!Solution::is_zero_array(
vec![4, 3, 2, 1],
vec![vec![1, 3], vec![0, 2]]
));
}
}

View File

@@ -0,0 +1,71 @@
/**
* [3356] Zero Array Transformation II
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn min_zero_array(nums: Vec<i32>, queries: Vec<Vec<i32>>) -> i32 {
let (mut left, mut right) = (0, queries.len());
if !Self::check(&nums, &queries, right) {
return -1;
}
while left < right {
let k = (left + right) / 2;
if Self::check(&nums, &queries, k) {
right = k;
} else {
left = k + 1;
}
}
left as i32
}
fn check(nums: &Vec<i32>, queries: &Vec<Vec<i32>>, k: usize) -> bool {
let n = nums.len();
let mut difference_array = vec![0; n + 1];
for query in queries[..k].iter() {
difference_array[query[0] as usize] += query[2];
difference_array[query[1] as usize + 1] -= query[2];
}
let mut prefix_sum = difference_array[0];
for (i, &v) in difference_array[1..].iter().enumerate() {
if prefix_sum < nums[i] {
return false;
}
prefix_sum += v;
}
true
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3356() {
assert_eq!(
2,
Solution::min_zero_array(
vec![2, 0, 2],
vec![vec![0, 2, 1], vec![0, 2, 1], vec![1, 1, 3]]
)
);
assert_eq!(
-1,
Solution::min_zero_array(vec![4, 3, 2, 1], vec![vec![1, 3, 2], vec![0, 2, 1]])
);
}
}

View File

@@ -0,0 +1,73 @@
/**
* [3362] Zero Array Transformation III
*/
pub struct Solution {}
// submission codes start here
use std::collections::BinaryHeap;
impl Solution {
pub fn max_removal(nums: Vec<i32>, mut queries: Vec<Vec<i32>>) -> i32 {
queries.sort_unstable_by(|a, b| a[0].cmp(&b[0]));
let mut heap = BinaryHeap::new();
let mut difference_array = vec![0; nums.len() + 1];
let mut prefix_sum = 0;
let mut pos = 0;
for i in 0..nums.len() {
prefix_sum += difference_array[i];
while pos < queries.len() && queries[pos][0] as usize == i {
heap.push(queries[pos][1] as usize);
pos += 1;
}
while prefix_sum < nums[i] {
if let Some(&right) = heap.peek() {
if right >= i {
prefix_sum += 1;
difference_array[right + 1] -= 1;
heap.pop();
} else {
break;
}
} else {
break;
}
}
if prefix_sum < nums[i] {
return -1;
}
}
heap.len() as i32
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3362() {
assert_eq!(
1,
Solution::max_removal(vec![2, 0, 2], vec![vec![0, 2], vec![0, 2], vec![1, 1]])
);
assert_eq!(
2,
Solution::max_removal(
vec![1, 1, 1, 1],
vec![vec![1, 3], vec![0, 2], vec![1, 3], vec![1, 2]]
)
);
assert_eq!(
-1,
Solution::max_removal(vec![1, 2, 3, 4], vec![vec![0, 3]])
);
}
}

View File

@@ -0,0 +1,113 @@
/**
* [3372] Maximize the Number of Target Nodes After Connecting Trees I
*/
pub struct Solution {}
// submission codes start here
use std::collections::VecDeque;
impl Solution {
pub fn max_target_nodes(edges1: Vec<Vec<i32>>, edges2: Vec<Vec<i32>>, k: i32) -> Vec<i32> {
// 首先构建邻接矩阵
let adjacent_matrix1 = Self::construct_adjacent_matrix(&edges1);
let adjacent_matrix2 = Self::construct_adjacent_matrix(&edges2);
let target_pointer_counts1 = Self::calculate_target_pointer_counts(&adjacent_matrix1, k);
let target_pointer_counts2 =
Self::calculate_target_pointer_counts(&adjacent_matrix2, k - 1);
let max_count = *target_pointer_counts2.iter().max().unwrap();
target_pointer_counts1
.iter()
.map(|&c| c + max_count)
.collect()
}
fn construct_adjacent_matrix(edges: &Vec<Vec<i32>>) -> Vec<Vec<usize>> {
let n = edges.len() + 1;
let mut adjacent_matrix = vec![vec![]; n];
for edge in edges.iter() {
let first = edge[0] as usize;
let second = edge[1] as usize;
adjacent_matrix[first].push(second);
adjacent_matrix[second].push(first);
}
adjacent_matrix
}
fn calculate_target_pointer_counts(
adjacent_matrix: &Vec<Vec<usize>>,
distance: i32,
) -> Vec<i32> {
let mut queue = VecDeque::new();
(0..adjacent_matrix.len())
.map(|i| {
let mut count = 0;
queue.clear();
if distance >= 0 {
queue.push_back((i, 0, None));
}
while let Some((pos, c, parent)) = queue.pop_front() {
count += 1;
if c + 1 <= distance {
for &next in adjacent_matrix[pos].iter() {
if parent.filter(|x| x == &next).is_some() {
continue;
}
queue.push_back((next, c + 1, Some(pos)));
}
}
}
count
})
.collect()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3372() {
assert_eq!(
vec![1, 1],
Solution::max_target_nodes(vec![vec![0, 1]], vec![vec![0, 1]], 0)
);
assert_eq!(
vec![9, 7, 9, 8, 8],
Solution::max_target_nodes(
vec![vec![0, 1], vec![0, 2], vec![2, 3], vec![2, 4]],
vec![
vec![0, 1],
vec![0, 2],
vec![0, 3],
vec![2, 7],
vec![1, 4],
vec![4, 5],
vec![4, 6]
],
2
)
);
assert_eq!(
vec![6, 3, 3, 3, 3],
Solution::max_target_nodes(
vec![vec![0, 1], vec![0, 2], vec![0, 3], vec![0, 4]],
vec![vec![0, 1], vec![1, 2], vec![2, 3]],
1
)
);
}
}

View File

@@ -0,0 +1,107 @@
/**
* [3373] Maximize the Number of Target Nodes After Connecting Trees II
*/
pub struct Solution {}
// submission codes start here
use std::collections::VecDeque;
impl Solution {
pub fn max_target_nodes(edges1: Vec<Vec<i32>>, edges2: Vec<Vec<i32>>) -> Vec<i32> {
let adjacent_matrix1 = Self::construct_adjacent_matrix(&edges1);
let adjacent_matrix2 = Self::construct_adjacent_matrix(&edges2);
let (even_count1, odd_count1, color1) =
Self::calculate_target_pointer_counts(&adjacent_matrix1);
let (even_count2, odd_count2, _) = Self::calculate_target_pointer_counts(&adjacent_matrix2);
let max_count = odd_count2.max(even_count2);
(0..adjacent_matrix1.len())
.map(|i| {
if color1[i] {
even_count1 + max_count
} else {
odd_count1 + max_count
}
})
.collect()
}
fn construct_adjacent_matrix(edges: &Vec<Vec<i32>>) -> Vec<Vec<usize>> {
let n = edges.len() + 1;
let mut adjacent_matrix = vec![vec![]; n];
for edge in edges.iter() {
let first = edge[0] as usize;
let second = edge[1] as usize;
adjacent_matrix[first].push(second);
adjacent_matrix[second].push(first);
}
adjacent_matrix
}
fn calculate_target_pointer_counts(adjacent_matrix: &Vec<Vec<usize>>) -> (i32, i32, Vec<bool>) {
let mut queue = VecDeque::new();
// 染色数组
// true表示距离为偶数
// false表示距离为奇数
let mut color = vec![false; adjacent_matrix.len()];
// 距离为偶数的计数
let mut result = 0;
queue.push_back((0, 0, None));
while let Some((pos, c, parent)) = queue.pop_front() {
if c % 2 == 0 {
color[pos] = true;
result += 1;
}
for &next in adjacent_matrix[pos].iter() {
if parent.filter(|x| x == &next).is_some() {
continue;
}
queue.push_back((next, c + 1, Some(pos)));
}
}
(result, adjacent_matrix.len() as i32 - result, color)
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3373() {
assert_eq!(
vec![8, 7, 7, 8, 8],
Solution::max_target_nodes(
vec![vec![0, 1], vec![0, 2], vec![2, 3], vec![2, 4]],
vec![
vec![0, 1],
vec![0, 2],
vec![0, 3],
vec![2, 7],
vec![1, 4],
vec![4, 5],
vec![4, 6]
]
)
);
assert_eq!(
vec![3, 6, 6, 6, 6],
Solution::max_target_nodes(
vec![vec![0, 1], vec![0, 2], vec![0, 3], vec![0, 4]],
vec![vec![0, 1], vec![1, 2], vec![2, 3]]
)
);
}
}

View File

@@ -0,0 +1,35 @@
/**
* [3392] Count Subarrays of Length Three With a Condition
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn count_subarrays(nums: Vec<i32>) -> i32 {
nums.iter()
.enumerate()
.skip(2)
.filter_map(|(i, &v)| {
if (nums[i - 2] + v) * 2 == nums[i - 1] {
Some(())
} else {
None
}
})
.count() as i32
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3392() {
assert_eq!(1, Solution::count_subarrays(vec![1, 2, 1, 4, 1]));
assert_eq!(0, Solution::count_subarrays(vec![1, 1, 1]));
}
}

View File

@@ -0,0 +1,48 @@
/**
* [3403] Find the Lexicographically Largest String From the Box I
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn answer_string(word: String, num_friends: i32) -> String {
// When there is only one person, the word can not be split.
if num_friends == 1 {
return word;
}
let word: Vec<u8> = word.bytes().collect();
let length = word.len() - num_friends as usize + 1;
let mut result: Option<&[u8]> = None;
for i in 0..word.len() {
let end = (i + length).min(word.len());
let w = &word[i..(i + length).min(word.len())];
if let Some(r) = result {
if w > r {
result = Some(w)
}
} else {
result = Some(w);
}
}
String::from_utf8(result.unwrap().into_iter().map(|x| *x).collect()).unwrap()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3403() {
assert_eq!("gh", Solution::answer_string("gh".to_string(), 1));
assert_eq!("dbc", Solution::answer_string("dbca".to_string(), 2));
assert_eq!("g", Solution::answer_string("gggg".to_string(), 4));
}
}

View File

@@ -0,0 +1,44 @@
/**
* [3442] Maximum Difference Between Even and Odd Frequency I
*/
pub struct Solution {}
// submission codes start here
use std::collections::HashMap;
impl Solution {
pub fn max_difference(s: String) -> i32 {
let mut frequency_map = HashMap::new();
for c in s.bytes() {
let entry = frequency_map.entry(c).or_insert(0);
*entry += 1;
}
let mut odd_max = 0;
let mut even_min = i32::MAX;
for &v in frequency_map.values() {
if v % 2 == 0 {
even_min = even_min.min(v);
} else {
odd_max = odd_max.max(v);
}
}
odd_max - even_min
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3442() {
assert_eq!(3, Solution::max_difference("aaaaabbc".to_string()));
assert_eq!(1, Solution::max_difference("abcabcab".to_string()));
}
}

View File

@@ -0,0 +1,50 @@
/**
* [386] Lexicographical Numbers
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn lexical_order(n: i32) -> Vec<i32> {
let mut result = Vec::with_capacity(n as usize);
for i in 1..10 {
Self::search(&mut result, i, n);
}
result
}
fn search(result: &mut Vec<i32>, mut prefix: i32, n: i32) {
if prefix <= n {
result.push(prefix);
}
prefix = prefix * 10;
for i in 0..10 {
if prefix + i > n {
break;
}
Self::search(result, prefix + i, n);
}
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_386() {
assert_eq!(vec![1, 2], Solution::lexical_order(2));
assert_eq!(
vec![1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],
Solution::lexical_order(13)
);
}
}

View File

@@ -0,0 +1,56 @@
/**
* [440] K-th Smallest in Lexicographical Order
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn find_kth_number(n: i32, mut k: i32) -> i32 {
let mut currrent = 1;
let n = n as i64;
k -= 1;
while k > 0 {
let steps = Self::calculate_steps(currrent, n);
// If steps <= k, then the number is in the tree of next current (at least).
if steps <= k {
k -= steps;
currrent += 1;
} else {
// The number is in the current tree.
currrent = currrent * 10;
k -= 1;
}
}
currrent as i32
}
/// Calculate the count of number with prefix current.
fn calculate_steps(current: i64, n: i64) -> i32 {
let mut result = 0;
let (mut first, mut last) = (current, current);
while first <= n {
result += n.min(last) - first + 1;
first = first * 10;
last = last * 10 + 9;
}
result as i32
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_440() {
assert_eq!(10, Solution::find_kth_number(13, 2));
assert_eq!(1, Solution::find_kth_number(1, 1));
}
}

View File

@@ -0,0 +1,53 @@
/**
* [75] Sort Colors
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn sort_colors(nums: &mut Vec<i32>) {
let (mut zero_count, mut one_count, mut two_count) = (0, 0, 0);
for i in nums.iter() {
match i {
&0 => zero_count += 1,
&1 => one_count += 1,
&2 => two_count += 1,
_ => {}
}
}
let mut pos = 0;
for _ in 0..zero_count {
nums[pos] = 0;
pos += 1;
}
for _ in 0..one_count {
nums[pos] = 1;
pos += 1;
}
for _ in 0..two_count {
nums[pos] = 2;
pos += 1;
}
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_75() {
let mut input = vec![2, 0, 2, 1, 1, 0];
Solution::sort_colors(&mut input);
assert_eq!(vec![0, 0, 1, 1, 2, 2], input);
let mut input = vec![2, 0, 1];
Solution::sort_colors(&mut input);
assert_eq!(vec![0, 1, 2], input);
}
}

View File

@@ -0,0 +1,50 @@
/**
* [790] Domino and Tromino Tiling
*/
pub struct Solution {}
// submission codes start here
const MOD: i32 = 1_000_000_007;
impl Solution {
pub fn num_tilings(n: i32) -> i32 {
let n = n as usize;
let mut dp = vec![0; n + 1];
dp[0] = 1;
let mut prefix = 0;
// dp的最后必须是平整的
// dp[n] = dp[n - 1] + dp[n - 2] + for i in 0..=n-3 Sum(dp[i] * 2)
for i in 1..=n {
dp[i] = dp[i - 1] % MOD;
if i >= 2 {
dp[i] = (dp[i] + dp[i - 2]) % MOD;
}
if i >= 3 {
prefix = (prefix + dp[i - 3] * 2 % MOD) % MOD;
dp[i] = (dp[i] + prefix) % MOD;
}
}
dp[n]
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_790() {
assert_eq!(1, Solution::num_tilings(1));
assert_eq!(2, Solution::num_tilings(2));
assert_eq!(5, Solution::num_tilings(3));
assert_eq!(11, Solution::num_tilings(4));
assert_eq!(312342182, Solution::num_tilings(30));
}
}

View File

@@ -0,0 +1,111 @@
/**
* [838] Push Dominoes
*/
pub struct Solution {}
// submission codes start here
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
enum State {
Left,
Right,
Untouched,
}
impl Solution {
pub fn push_dominoes(dominoes: String) -> String {
let mut dominoes: Vec<State> = dominoes
.chars()
.map(|c| match c {
'L' => State::Left,
'R' => State::Right,
'.' => State::Untouched,
_ => unimplemented!(),
})
.collect();
let n = dominoes.len();
// 为双指针插入头尾伪节点
dominoes.insert(0, State::Untouched);
dominoes.push(State::Untouched);
let (mut left, mut right) = (0, 1);
// 不能判断右指针
// 左指针才是遍历完成的信息
while left <= n {
while right <= n && dominoes[right] == State::Untouched {
right += 1;
}
// 找到没有推动的区间(left, right)
if right - left > 1 {
let (mut inner_left, mut inner_right) = (left + 1, right - 1);
match (dominoes[left], dominoes[right]) {
(State::Untouched, State::Left) | (State::Left, State::Left) => {
while inner_left <= inner_right {
dominoes[inner_left] = State::Left;
inner_left += 1;
}
}
(State::Right, State::Untouched) | (State::Right, State::Right) => {
while inner_left <= inner_right {
dominoes[inner_left] = State::Right;
inner_left += 1;
}
}
(State::Right, State::Left) => {
while inner_left < inner_right {
// 注意需要同时修改
let l = Self::between_left_right(&mut dominoes, inner_left);
let r = Self::between_left_right(&mut dominoes, inner_right);
dominoes[inner_left] = l;
dominoes[inner_right] = r;
inner_left += 1;
inner_right -= 1;
}
}
_ => {}
}
}
left = right;
right += 1;
}
dominoes[1..=n]
.iter()
.map(|x| match x {
State::Left => 'L',
State::Right => 'R',
State::Untouched => '.',
})
.collect()
}
fn between_left_right(dominoes: &mut Vec<State>, pos: usize) -> State {
match (dominoes[pos - 1], dominoes[pos + 1]) {
(State::Right, State::Untouched) => State::Right,
(State::Untouched, State::Left) => State::Left,
// 其他情况都不会影响中间的
_ => dominoes[pos],
}
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_838() {
assert_eq!("LL.RR", Solution::push_dominoes(".L.R.".to_owned()));
assert_eq!("RR.L", Solution::push_dominoes("RR.L".to_owned()));
assert_eq!(
"LL.RR.LLRRLL..",
Solution::push_dominoes(".L.R...LR..L..".to_owned())
);
}
}