Skip to content

Commit 5960100

Browse files
committed
feat: implement word search ii solution in rust
1 parent 4dedfe2 commit 5960100

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed

src/hard/word_search_ii.rs

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#![allow(dead_code)]
2+
use std::collections::{HashMap, HashSet};
3+
4+
pub struct TrieNode {
5+
pub children: HashMap<char, TrieNode>,
6+
pub is_word: bool,
7+
}
8+
9+
impl TrieNode {
10+
fn new() -> Self {
11+
TrieNode {
12+
children: HashMap::new(),
13+
is_word: false,
14+
}
15+
}
16+
17+
fn insert(&mut self, word: &str) {
18+
let mut node = self;
19+
20+
for c in word.chars() {
21+
node = node.children.entry(c).or_insert(TrieNode::new());
22+
}
23+
node.is_word = true;
24+
}
25+
}
26+
27+
fn find_words(board: Vec<Vec<char>>, words: Vec<&str>) -> Vec<String> {
28+
let mut root = TrieNode::new();
29+
30+
for word in words {
31+
root.insert(word);
32+
}
33+
34+
let rows = board.len();
35+
let cols = board[0].len();
36+
let mut path = HashSet::new();
37+
let mut res = HashSet::new();
38+
39+
fn dfs(
40+
r: usize,
41+
c: usize,
42+
word: &mut String,
43+
node: &mut TrieNode,
44+
path: &mut HashSet<(usize, usize)>,
45+
res: &mut HashSet<String>,
46+
board: &[Vec<char>],
47+
rows: usize,
48+
cols: usize,
49+
) {
50+
if r >= rows
51+
|| c >= cols
52+
|| !node.children.contains_key(&board[r][c])
53+
|| path.contains(&(r, c))
54+
{
55+
return;
56+
}
57+
58+
path.insert((r, c));
59+
word.push(board[r][c]);
60+
61+
if node.is_word {
62+
res.insert(word.clone());
63+
}
64+
65+
if let Some(child_node) = node.children.get_mut(&board[r][c]) {
66+
if child_node.is_word {
67+
res.insert(word.clone());
68+
}
69+
70+
dfs(r + 1, c, word, child_node, path, res, board, rows, cols);
71+
dfs(
72+
r.saturating_sub(1),
73+
c,
74+
word,
75+
child_node,
76+
path,
77+
res,
78+
board,
79+
rows,
80+
cols,
81+
);
82+
dfs(r, c + 1, word, child_node, path, res, board, rows, cols);
83+
dfs(
84+
r,
85+
c.saturating_sub(1),
86+
word,
87+
child_node,
88+
path,
89+
res,
90+
board,
91+
rows,
92+
cols,
93+
);
94+
}
95+
96+
path.remove(&(r, c));
97+
word.pop();
98+
}
99+
100+
for r in 0..rows {
101+
for c in 0..cols {
102+
let mut word = String::new();
103+
dfs(
104+
r, c, &mut word, &mut root, &mut path, &mut res, &board, rows, cols,
105+
);
106+
}
107+
}
108+
109+
res.into_iter().collect()
110+
}
111+
112+
#[cfg(test)]
113+
mod tests {
114+
use super::*;
115+
116+
fn compare_two_vec_of_string(v1: Vec<String>, v2: Vec<&str>) {
117+
let mut v2 = v2.to_vec();
118+
v2.sort();
119+
let mut v1 = v1;
120+
v1.sort();
121+
assert_eq!(v1, v2);
122+
}
123+
124+
#[test]
125+
fn test_find_words() {
126+
compare_two_vec_of_string(
127+
find_words(
128+
vec![
129+
vec!['o', 'a', 'a', 'n'],
130+
vec!['e', 't', 'a', 'e'],
131+
vec!['i', 'h', 'k', 'r'],
132+
vec!['i', 'f', 'l', 'v'],
133+
],
134+
vec!["oath", "pea", "eat", "rain"],
135+
),
136+
vec!["eat", "oath"],
137+
);
138+
}
139+
}

0 commit comments

Comments
 (0)