Skip to content

Commit 850614b

Browse files
authored
weekly-83 (#4)
some weekly
1 parent dd60b5d commit 850614b

File tree

12 files changed

+1342
-33
lines changed

12 files changed

+1342
-33
lines changed

Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
.PHONY: clean coverage
22

33
clean:
4-
cargo clean
4+
@cargo clean; \
5+
rm *.profraw
56
test:
6-
cargo test
7+
@cargo test
78
coverage: test
8-
grcov target/coverage/grcov.profraw --branch --ignore-not-existing --binary-path ./target/debug/ -s . -t lcov --ignore \"/*\" -o target/coverage/lcov.info
9+
@grcov target/coverage/grcov.profraw --branch --ignore-not-existing --binary-path ./target/debug/ -s . -t lcov --ignore \"/*\" -o target/coverage/lcov.info
910
lint:
10-
cargo fix --allow-dirty --allow-staged
11+
@cargo fix --allow-dirty --allow-staged

ReadMe.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
- [LeetCode][leetcode]
1818
- 语言: [Rust][rust]
1919
- IDE: [我的 IDE 配置][我的ide 配置]
20+
- 一些辅助工具
21+
- [LaTeX公式编辑器](https://www.latexlive.com/##)
2022

2123
### 内容
2224

src/array/ext/disjoint.rs

Lines changed: 197 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ impl UnionFind {
4040
}
4141
root
4242
}
43+
4344
pub fn is_connected(&self, p: usize, q: usize) -> bool {
4445
self.find(p) == self.find(q)
4546
}
@@ -74,7 +75,7 @@ pub fn find_circle_num(is_connected: Vec<Vec<i32>>) -> i32 {
7475

7576
/// [684. 冗余连接](https://leetcode.cn/problems/redundant-connection/)
7677
pub fn find_redundant_connection(edges: Vec<Vec<i32>>) -> Vec<i32> {
77-
let mut uf = UnionFind::new(edges.len()+1);
78+
let mut uf = UnionFind::new(edges.len() + 1);
7879
let mut curr_count = uf.count();
7980
let mut last_edge = vec![];
8081

@@ -90,11 +91,206 @@ pub fn find_redundant_connection(edges: Vec<Vec<i32>>) -> Vec<i32> {
9091
last_edge
9192
}
9293

94+
/// [990. 等式方程的可满足性](https://leetcode.cn/problems/satisfiability-of-equality-equations/)
95+
pub fn equations_possible(equations: Vec<String>) -> bool {
96+
let mut uf = UnionFind::new(26);
97+
98+
let mut not_equal = vec![]; // 暂存
99+
100+
for e in equations {
101+
let s = e.as_bytes();
102+
let (a, b, eq) = (s[0] - b'a', s[3] - b'a', s[1] == b'=');
103+
if eq {
104+
uf.connect(a as usize, b as usize);
105+
} else {
106+
not_equal.push((a as usize, b as usize));
107+
}
108+
}
109+
110+
for (a, b) in not_equal {
111+
if uf.is_connected(a, b) {
112+
return false;
113+
}
114+
}
115+
true
116+
}
117+
118+
/// [839. 相似字符串组](https://leetcode.cn/problems/similar-string-groups/)
119+
pub fn num_similar_groups(strs: Vec<String>) -> i32 {
120+
fn is_similar(s1: &str, s2: &str) -> bool {
121+
s1.chars().zip(s2.chars()).filter(|(a, b)| !a.eq(b)).count() <= 2
122+
}
123+
let mut uf = UnionFind::new(strs.len());
124+
125+
for i in 0..strs.len() {
126+
let s1 = strs.get(i).unwrap();
127+
for j in i + 1..strs.len() {
128+
if uf.is_connected(i, j) {
129+
continue;
130+
}
131+
132+
let s2 = strs.get(j).unwrap();
133+
if is_similar(s1, s2) {
134+
uf.connect(i, j);
135+
}
136+
}
137+
}
138+
uf.count() as i32
139+
}
140+
141+
/// [841. 钥匙和房间](https://leetcode.cn/problems/keys-and-rooms/)
142+
///
143+
/// 关键信息: 除 `0` 号房间外的其余所有房间都被锁住
144+
///
145+
/// 解法1: bfs
146+
/// ```
147+
/// pub fn can_visit_all_rooms(rooms: Vec<Vec<i32>>) -> bool {
148+
/// use std::collections::HashSet;
149+
/// use std::collections::VecDeque;
150+
///
151+
/// let mut queue = VecDeque::new();
152+
/// let mut visited = HashSet::new();
153+
///
154+
/// queue.push_back(0);
155+
/// visited.insert(0);
156+
/// while let Some(n) = queue.pop_front() {
157+
/// let room = rooms.get(n).unwrap();
158+
/// for &r in room.iter(){
159+
/// if !visited.insert(r) {
160+
/// continue;
161+
/// }
162+
/// queue.push_back(r as usize)
163+
/// }
164+
/// }
165+
/// visited.len() == rooms.len()
166+
/// }
167+
/// ```
168+
///
169+
/// 解法二: 并查集
170+
///
171+
/// 由于 `HashSet` 这里也只是用了 `insert` 和 `contain` 两个方法, 因此换成 并查集判定也是OK的.
172+
/// 甚至内存表现上, 并查集更优.
173+
pub fn can_visit_all_rooms(rooms: Vec<Vec<i32>>) -> bool {
174+
use std::collections::VecDeque;
175+
let mut uf = UnionFind::new(rooms.len());
176+
177+
let mut queue = VecDeque::new();
178+
179+
queue.push_back(0);
180+
while let Some(curr) = queue.pop_front() {
181+
let room = rooms.get(curr).unwrap();
182+
for &r in room.iter() {
183+
if uf.is_connected(curr, r as usize) {
184+
continue;
185+
}
186+
uf.connect(curr, r as usize);
187+
queue.push_back(r as usize);
188+
}
189+
}
190+
uf.count() == 1
191+
}
192+
93193
#[cfg(test)]
94194
mod test {
95195
use super::*;
96196
use crate::vec2;
97197

198+
#[test]
199+
fn test_can_visit_all_rooms() {
200+
struct Testcase {
201+
rooms: Vec<Vec<i32>>,
202+
expect: bool,
203+
}
204+
205+
vec![
206+
Testcase {
207+
rooms: vec2![[1], [2], [3], []],
208+
expect: true,
209+
},
210+
Testcase {
211+
rooms: vec2![[1, 3], [3, 0, 1], [2], [0]],
212+
expect: false,
213+
},
214+
Testcase {
215+
rooms: vec2![[1], [], [0, 3], [1]],
216+
expect: false,
217+
},
218+
]
219+
.into_iter()
220+
.enumerate()
221+
.for_each(|(idx, testcase)| {
222+
let Testcase { rooms, expect } = testcase;
223+
let actual = can_visit_all_rooms(rooms);
224+
assert_eq!(expect, actual, "case {} failed", idx);
225+
});
226+
}
227+
228+
#[test]
229+
fn test_num_similar_groups() {
230+
struct TestCase {
231+
strs: Vec<&'static str>,
232+
expect: i32,
233+
}
234+
235+
vec![
236+
TestCase {
237+
strs: vec!["tars", "rats", "arts", "star"],
238+
expect: 2,
239+
},
240+
TestCase {
241+
strs: vec!["omv", "ovm"],
242+
expect: 1,
243+
},
244+
]
245+
.into_iter()
246+
.enumerate()
247+
.for_each(|(idx, testcase)| {
248+
let TestCase { strs, expect } = testcase;
249+
let strs = strs.into_iter().map(str::to_string).collect();
250+
let actual = num_similar_groups(strs);
251+
assert_eq!(expect, actual, "case {} failed", idx);
252+
});
253+
}
254+
255+
#[test]
256+
fn test_equations_possible() {
257+
struct TestCase {
258+
equations: Vec<&'static str>,
259+
expect: bool,
260+
}
261+
262+
vec![
263+
TestCase {
264+
equations: vec!["a==b", "b!=a"],
265+
expect: false,
266+
},
267+
TestCase {
268+
equations: vec!["b==a", "a==b"],
269+
expect: true,
270+
},
271+
TestCase {
272+
equations: vec!["a==b", "b==c", "a==c"],
273+
expect: true,
274+
},
275+
TestCase {
276+
equations: vec!["a==b", "b!=c", "c==a"],
277+
expect: false,
278+
},
279+
TestCase {
280+
equations: vec!["c==c", "b==d", "x!=z"],
281+
expect: true,
282+
},
283+
]
284+
.into_iter()
285+
.enumerate()
286+
.for_each(|(idx, testcase)| {
287+
let TestCase { equations, expect } = testcase;
288+
let equations = equations.into_iter().map(str::to_string).collect();
289+
let actual = equations_possible(equations);
290+
assert_eq!(expect, actual, "case {} failed", idx);
291+
});
292+
}
293+
98294
#[test]
99295
fn test_find_redundant_connection() {
100296
struct Testcase {

0 commit comments

Comments
 (0)