Skip to content

feat: add rust solution to lc problem: No.1197 #1169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions solution/1100-1199/1197.Minimum Knight Moves/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool>> = vec![vec![false; 618]; 618];
// <X, Y, Current Steps>
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<Vec<bool>>, 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 <X, Y> 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 <X, Y> 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<i32, i32> = HashMap::new();
let mut map_from: HashMap<i32, i32> = 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<i32, i32>, map_from: &mut HashMap<i32, i32>, 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
Expand Down
135 changes: 135 additions & 0 deletions solution/1100-1199/1197.Minimum Knight Moves/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool>> = vec![vec![false; 618]; 618];
// <X, Y, Current Steps>
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<Vec<bool>>, 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 <X, Y> 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 <X, Y> 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<i32, i32> = HashMap::new();
let mut map_from: HashMap<i32, i32> = 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<i32, i32>, map_from: &mut HashMap<i32, i32>, 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:
Expand Down
54 changes: 54 additions & 0 deletions solution/1100-1199/1197.Minimum Knight Moves/Solution.rs
Original file line number Diff line number Diff line change
@@ -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<bool>> = vec![vec![false; 618]; 618];
// <X, Y, Current Steps>
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<Vec<bool>>, 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 <X, Y> 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
}
}