-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paths0079_word_search.rs
118 lines (106 loc) · 3.09 KB
/
s0079_word_search.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#![allow(unused)]
pub struct Solution {}
const DIRECTIONS: [(i32, i32); 4] = [(0, 1), (1, 0), (0, -1), (-1, 0)];
impl Solution {
// O(N * 3^min(l, N)) N is the number of cells in the board and L
// is the length of the word to be matched.
// For the backtracking function, initially we could have at
// most 4 directions to explore, but further the choices are reduced into 3
// (since we won't go back to where we come from)
// O(L)
pub fn exist(mut board: Vec<Vec<char>>, word: String) -> bool {
let (m, n) = (board.len(), board[0].len());
for r in 0..m {
for c in 0..n {
if Self::backtrack(
r as i32,
c as i32,
&mut board,
m as i32,
n as i32,
word.as_str(),
) {
return true;
}
}
}
false
}
fn backtrack(
row: i32,
col: i32,
board: &mut Vec<Vec<char>>,
m: i32,
n: i32,
word: &str,
) -> bool {
/* Step 1). check the bottom case. */
if word.len() == 0 {
return true;
}
let ori_char = word.chars().next().unwrap();
/* Step 2). Check the boundaries. */
if row < 0
|| col < 0
||row >= m
|| col >= n
|| board[row as usize][col as usize] != ori_char
{
return false;
}
/* Step 3). explore the neighbors in DFS */
// mark the path before the next exploration
board[row as usize][col as usize] = '#';
for di in DIRECTIONS.iter() {
let (can_row, can_col) = (row + di.0, col + di.1);
if Self::backtrack(can_row, can_col, board, m, n, &word[1..]) {
// return without cleanup
return true;
}
}
/* Step 4). clean up and return false. */
board[row as usize][col as usize] = ori_char;
false
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_79() {
assert_eq!(Solution::exist(vec![vec!['A'],], "A".to_string()), true);
assert_eq!(
Solution::exist(
vec![
vec!['A', 'B', 'C', 'E'],
vec!['S', 'F', 'C', 'S'],
vec!['A', 'D', 'E', 'E']
],
"ABCCED".to_string()
),
true
);
assert_eq!(
Solution::exist(
vec![
vec!['A', 'B', 'C', 'E'],
vec!['S', 'F', 'C', 'S'],
vec!['A', 'D', 'E', 'E']
],
"SEE".to_string()
),
true
);
assert_eq!(
Solution::exist(
vec![
vec!['A', 'B', 'C', 'E'],
vec!['S', 'F', 'C', 'S'],
vec!['A', 'D', 'E', 'E']
],
"ABCB".to_string()
),
false
);
}
}