diff --git a/solution/1100-1199/1197.Minimum Knight Moves/README.md b/solution/1100-1199/1197.Minimum Knight Moves/README.md index b2401cb977ed2..4f269538f8b3e 100644 --- a/solution/1100-1199/1197.Minimum Knight Moves/README.md +++ b/solution/1100-1199/1197.Minimum Knight Moves/README.md @@ -293,6 +293,141 @@ public: }; ``` +### **Rust** + +```rust +use std::collections::VecDeque; + +const DIR: [(i32, i32); 8] = [(-2, 1), (2, 1), (-1, 2), (1, 2), (2, -1), (-2, -1), (1, -2), (-1, -2)]; + +impl Solution { + #[allow(dead_code)] + pub fn min_knight_moves(x: i32, y: i32) -> i32 { + // The original x, y are from [-300, 300] + // Let's shift them to [0, 600] + let x: i32 = x + 300; + let y: i32 = y + 300; + let mut ret = -1; + let mut vis: Vec> = vec![vec![false; 618]; 618]; + // + let mut q: VecDeque<(i32, i32, i32)> = VecDeque::new(); + + q.push_back((300, 300, 0)); + + while !q.is_empty() { + let (i, j, s) = q.front().unwrap().clone(); + q.pop_front(); + if i == x && j == y { + ret = s; + break; + } + Self::enqueue(&mut vis, &mut q, i, j, s); + } + + ret + } + + #[allow(dead_code)] + fn enqueue(vis: &mut Vec>, q: &mut VecDeque<(i32, i32, i32)>, i: i32, j: i32, cur_step: i32) { + let next_step = cur_step + 1; + for (dx, dy) in DIR { + let x = i + dx; + let y = j + dy; + if Self::check_bounds(x, y) || vis[x as usize][y as usize] { + // This pair is either out of bound, or has been visited before + // Just ignore this pair + continue; + } + // Otherwise, add the pair to the queue + // Also remember to update the vis vector + vis[x as usize][y as usize] = true; + q.push_back((x, y, next_step)); + } + } + + #[allow(dead_code)] + fn check_bounds(i: i32, j: i32) -> bool { + i < 0 || i > 600 || j < 0 || j > 600 + } +} +``` + +双向 BFS: + +```rust +use std::collections::VecDeque; +use std::collections::HashMap; + +const DIR: [(i32, i32); 8] = [(-2, 1), (2, 1), (-1, 2), (1, 2), (2, -1), (-2, -1), (1, -2), (-1, -2)]; + +impl Solution { + #[allow(dead_code)] + pub fn min_knight_moves(x: i32, y: i32) -> i32 { + if x == 0 && y == 0 { + return 0; + } + // Otherwise, let's shift from [-300, 300] -> [0, 600] + let x = x + 300; + let y = y + 300; + let mut ret = -1; + // Initialize the two hash map, used to track if a node has been visited + let mut map_to: HashMap = HashMap::new(); + let mut map_from: HashMap = HashMap::new(); + // Input the original status + map_to.insert(601 * 300 + 300, 0); + map_from.insert(601 * x + y, 0); + let mut q_to: VecDeque<(i32, i32)> = VecDeque::new(); + let mut q_from: VecDeque<(i32, i32)> = VecDeque::new(); + // Initialize the two queue + q_to.push_back((300, 300)); + q_from.push_back((x, y)); + + while !q_to.is_empty() && !q_from.is_empty() { + let step = if q_to.len() < q_from.len() { + Self::extend(&mut map_to, &mut map_from, &mut q_to) + } else { + Self::extend(&mut map_from, &mut map_to, &mut q_from) + }; + if step != -1 { + ret = step; + break; + } + } + + ret + } + + #[allow(dead_code)] + fn extend(map_to: &mut HashMap, map_from: &mut HashMap, cur_q: &mut VecDeque<(i32, i32)>) -> i32 { + let n = cur_q.len(); + for _ in 0..n { + let (i, j) = cur_q.front().unwrap().clone(); + cur_q.pop_front(); + // The cur_step here must exist + let cur_step = map_to.get(&(601 * i + j)).unwrap().clone(); + for (dx, dy) in DIR { + let x = i + dx; + let y = j + dy; + // Check if this node has been visited + if map_to.contains_key(&(601 * x + y)) { + // Just ignore this node + continue; + } + // Check if this node has been visited by the other side + if map_from.contains_key(&(601 * x + y)) { + // We found the node + return cur_step + 1 + map_from.get(&(601 * x + y)).unwrap().clone(); + } + // Otherwise, update map_to and push the new node to queue + map_to.insert(601 * x + y, cur_step + 1); + cur_q.push_back((x, y)); + } + } + -1 + } +} +``` + ### **Go** ```go diff --git a/solution/1100-1199/1197.Minimum Knight Moves/README_EN.md b/solution/1100-1199/1197.Minimum Knight Moves/README_EN.md index 08672639696b5..196f10be7c070 100644 --- a/solution/1100-1199/1197.Minimum Knight Moves/README_EN.md +++ b/solution/1100-1199/1197.Minimum Knight Moves/README_EN.md @@ -272,6 +272,141 @@ public: }; ``` +### **Rust** + +```rust +use std::collections::VecDeque; + +const DIR: [(i32, i32); 8] = [(-2, 1), (2, 1), (-1, 2), (1, 2), (2, -1), (-2, -1), (1, -2), (-1, -2)]; + +impl Solution { + #[allow(dead_code)] + pub fn min_knight_moves(x: i32, y: i32) -> i32 { + // The original x, y are from [-300, 300] + // Let's shift them to [0, 600] + let x: i32 = x + 300; + let y: i32 = y + 300; + let mut ret = -1; + let mut vis: Vec> = vec![vec![false; 618]; 618]; + // + let mut q: VecDeque<(i32, i32, i32)> = VecDeque::new(); + + q.push_back((300, 300, 0)); + + while !q.is_empty() { + let (i, j, s) = q.front().unwrap().clone(); + q.pop_front(); + if i == x && j == y { + ret = s; + break; + } + Self::enqueue(&mut vis, &mut q, i, j, s); + } + + ret + } + + #[allow(dead_code)] + fn enqueue(vis: &mut Vec>, q: &mut VecDeque<(i32, i32, i32)>, i: i32, j: i32, cur_step: i32) { + let next_step = cur_step + 1; + for (dx, dy) in DIR { + let x = i + dx; + let y = j + dy; + if Self::check_bounds(x, y) || vis[x as usize][y as usize] { + // This pair is either out of bound, or has been visited before + // Just ignore this pair + continue; + } + // Otherwise, add the pair to the queue + // Also remember to update the vis vector + vis[x as usize][y as usize] = true; + q.push_back((x, y, next_step)); + } + } + + #[allow(dead_code)] + fn check_bounds(i: i32, j: i32) -> bool { + i < 0 || i > 600 || j < 0 || j > 600 + } +} +``` + +Two-end BFS: + +```rust +use std::collections::VecDeque; +use std::collections::HashMap; + +const DIR: [(i32, i32); 8] = [(-2, 1), (2, 1), (-1, 2), (1, 2), (2, -1), (-2, -1), (1, -2), (-1, -2)]; + +impl Solution { + #[allow(dead_code)] + pub fn min_knight_moves(x: i32, y: i32) -> i32 { + if x == 0 && y == 0 { + return 0; + } + // Otherwise, let's shift from [-300, 300] -> [0, 600] + let x = x + 300; + let y = y + 300; + let mut ret = -1; + // Initialize the two hash map, used to track if a node has been visited + let mut map_to: HashMap = HashMap::new(); + let mut map_from: HashMap = HashMap::new(); + // Input the original status + map_to.insert(601 * 300 + 300, 0); + map_from.insert(601 * x + y, 0); + let mut q_to: VecDeque<(i32, i32)> = VecDeque::new(); + let mut q_from: VecDeque<(i32, i32)> = VecDeque::new(); + // Initialize the two queue + q_to.push_back((300, 300)); + q_from.push_back((x, y)); + + while !q_to.is_empty() && !q_from.is_empty() { + let step = if q_to.len() < q_from.len() { + Self::extend(&mut map_to, &mut map_from, &mut q_to) + } else { + Self::extend(&mut map_from, &mut map_to, &mut q_from) + }; + if step != -1 { + ret = step; + break; + } + } + + ret + } + + #[allow(dead_code)] + fn extend(map_to: &mut HashMap, map_from: &mut HashMap, cur_q: &mut VecDeque<(i32, i32)>) -> i32 { + let n = cur_q.len(); + for _ in 0..n { + let (i, j) = cur_q.front().unwrap().clone(); + cur_q.pop_front(); + // The cur_step here must exist + let cur_step = map_to.get(&(601 * i + j)).unwrap().clone(); + for (dx, dy) in DIR { + let x = i + dx; + let y = j + dy; + // Check if this node has been visited + if map_to.contains_key(&(601 * x + y)) { + // Just ignore this node + continue; + } + // Check if this node has been visited by the other side + if map_from.contains_key(&(601 * x + y)) { + // We found the node + return cur_step + 1 + map_from.get(&(601 * x + y)).unwrap().clone(); + } + // Otherwise, update map_to and push the new node to queue + map_to.insert(601 * x + y, cur_step + 1); + cur_q.push_back((x, y)); + } + } + -1 + } +} +``` + ### **Go** Two-end BFS: diff --git a/solution/1100-1199/1197.Minimum Knight Moves/Solution.rs b/solution/1100-1199/1197.Minimum Knight Moves/Solution.rs new file mode 100644 index 0000000000000..2eb8c1ead0fa3 --- /dev/null +++ b/solution/1100-1199/1197.Minimum Knight Moves/Solution.rs @@ -0,0 +1,54 @@ +use std::collections::VecDeque; + +const DIR: [(i32, i32); 8] = [(-2, 1), (2, 1), (-1, 2), (1, 2), (2, -1), (-2, -1), (1, -2), (-1, -2)]; + +impl Solution { + #[allow(dead_code)] + pub fn min_knight_moves(x: i32, y: i32) -> i32 { + // The original x, y are from [-300, 300] + // Let's shift them to [0, 600] + let x: i32 = x + 300; + let y: i32 = y + 300; + let mut ret = -1; + let mut vis: Vec> = vec![vec![false; 618]; 618]; + // + let mut q: VecDeque<(i32, i32, i32)> = VecDeque::new(); + + q.push_back((300, 300, 0)); + + while !q.is_empty() { + let (i, j, s) = q.front().unwrap().clone(); + q.pop_front(); + if i == x && j == y { + ret = s; + break; + } + Self::enqueue(&mut vis, &mut q, i, j, s); + } + + ret + } + + #[allow(dead_code)] + fn enqueue(vis: &mut Vec>, q: &mut VecDeque<(i32, i32, i32)>, i: i32, j: i32, cur_step: i32) { + let next_step = cur_step + 1; + for (dx, dy) in DIR { + let x = i + dx; + let y = j + dy; + if Self::check_bounds(x, y) || vis[x as usize][y as usize] { + // This pair is either out of bound, or has been visited before + // Just ignore this pair + continue; + } + // Otherwise, add the pair to the queue + // Also remember to update the vis vector + vis[x as usize][y as usize] = true; + q.push_back((x, y, next_step)); + } + } + + #[allow(dead_code)] + fn check_bounds(i: i32, j: i32) -> bool { + i < 0 || i > 600 || j < 0 || j > 600 + } +} \ No newline at end of file