Skip to content

Commit aaf3af5

Browse files
committed
LC 1396. Design Underground System (Rust)
1 parent 3eaa20f commit aaf3af5

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ Solutions to LeetCode problems. The first column links to the problem in LeetCod
411411
| [1354. Construct Target Array With Multiple Sums][lc1354] | 🔴 Hard | [![python](res/py.png)][lc1354py] |
412412
| [1372. Longest ZigZag Path in a Binary Tree][lc1372] | 🟠 Medium | [![python](res/py.png)][lc1372py] [![rust](res/rs.png)][lc1372rs] |
413413
| [1383. Maximum Performance of a Team][lc1383] | 🔴 Hard | [![python](res/py.png)][lc1383py] |
414+
| [1396. Design Underground System][lc1396] | 🟠 Medium | [![rust](res/rs.png)][lc1396rs] |
414415
| [1402. Reducing Dishes][lc1402] | 🔴 Hard | [![python](res/py.png)][lc1402py] [![rust](res/rs.png)][lc1402rs] |
415416
| [1406. Stone Game III][lc1406] | 🔴 Hard | [![rust](res/rs.png)][lc1406rs] |
416417
| [1416. Restore The Array][lc1416] | 🔴 Hard | [![python](res/py.png)][lc1416py] [![rust](res/rs.png)][lc1416rs] |
@@ -1413,6 +1414,8 @@ Solutions to LeetCode problems. The first column links to the problem in LeetCod
14131414
[lc1372rs]: leetcode/longest-zigzag-path-in-a-binary-tree.rs
14141415
[lc1383]: https://leetcode.com/problems/maximum-performance-of-a-team/
14151416
[lc1383py]: leetcode/maximum-performance-of-a-team.py
1417+
[lc1396]: https://leetcode.com/problems/design-underground-system/
1418+
[lc1396rs]: leetcode/design-underground-system.rs
14161419
[lc1402]: https://leetcode.com/problems/reducing-dishes/
14171420
[lc1402py]: leetcode/reducing-dishes.py
14181421
[lc1402rs]: leetcode/reducing-dishes.rs

leetcode/design-underground-system.rs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// 1396. Design Underground System
2+
// 🟠 Medium
3+
//
4+
// https://leetcode.com/problems/design-underground-system/
5+
//
6+
// Tags: Hash Table - Design - String
7+
8+
use std::collections::HashMap;
9+
10+
struct UndergroundSystem {
11+
travelers: HashMap<i32, (String, i32)>,
12+
times: HashMap<(String, String), (f64, usize)>,
13+
}
14+
15+
/// Use two hashmaps, one to store travelers in transit information, it will
16+
/// save an entry when a traveler starts a trip with the traveler's id as the
17+
/// key and the station and time as the value. When a traveler checks out, it
18+
/// will use all the data to compute the travel time and insert it into the
19+
/// times hashmap under the (start_st, end_st) key, if the key already exists
20+
/// in the hashmap, it will update the values. When we need to get the average,
21+
/// we access the times hashmap and use the total traveled time and number of
22+
/// trips to get and return it.
23+
///
24+
/// Time complexity: O(1) - Each call to any of the methods is processed in
25+
/// constant time.
26+
/// Space complexity: O(n) - We could have as many entries in the travelers
27+
/// hashmap as calls to the check_in method, but most likely that number will
28+
/// remain low, as entries are removed by calls to the checkout method. The
29+
/// number of entries in the times hashmap could be equal to the number of
30+
/// total trips, if every combination of in_station and out_station was unique.
31+
///
32+
/// Runtime 34 ms Beats 92.86%
33+
/// Memory 17.1 MB Beats 100%
34+
impl UndergroundSystem {
35+
fn new() -> Self {
36+
UndergroundSystem {
37+
travelers: HashMap::new(),
38+
times: HashMap::new(),
39+
}
40+
}
41+
42+
fn check_in(&mut self, id: i32, station_name: String, t: i32) {
43+
self.travelers.insert(id, (station_name, t));
44+
}
45+
46+
fn check_out(&mut self, id: i32, station_name: String, t: i32) {
47+
match self.travelers.remove(&id) {
48+
Some((in_st, in_tm)) => {
49+
let travel_time = (t - in_tm) as f64;
50+
let src_station = in_st.to_owned();
51+
self.times
52+
.entry((src_station, station_name))
53+
.and_modify(|(total_travel_time, count)| {
54+
*total_travel_time += travel_time;
55+
*count += 1;
56+
})
57+
.or_insert((travel_time, 1));
58+
}
59+
None => unreachable!(),
60+
}
61+
}
62+
63+
fn get_average_time(&self, start_station: String, end_station: String) -> f64 {
64+
match self.times.get(&(start_station, end_station)) {
65+
Some(e) => e.0 / e.1 as f64,
66+
None => unreachable!(),
67+
}
68+
}
69+
}
70+
71+
/**
72+
* Your UndergroundSystem object will be instantiated and called as such:
73+
* let obj = UndergroundSystem::new();
74+
* obj.check_in(id, stationName, t);
75+
* obj.check_out(id, stationName, t);
76+
* let ret_3: f64 = obj.get_average_time(startStation, endStation);
77+
*/
78+
79+
/**
80+
* Your MyHashSet object will be instantiated and called as such:
81+
* let obj = MyHashSet::new();
82+
* obj.add(key);
83+
* obj.remove(key);
84+
* let ret_3: bool = obj.contains(key);
85+
*/
86+
fn main() {
87+
let mut us = UndergroundSystem::new();
88+
us.check_in(10, String::from("Leyton"), 3);
89+
us.check_out(10, String::from("Paradise"), 8);
90+
assert_eq!(
91+
us.get_average_time(String::from("Leyton"), String::from("Paradise")),
92+
5.0
93+
);
94+
us.check_in(5, String::from("Leyton"), 10);
95+
us.check_out(5, String::from("Paradise"), 16);
96+
assert_eq!(
97+
us.get_average_time(String::from("Leyton"), String::from("Paradise")),
98+
5.5
99+
);
100+
us.check_in(2, String::from("Leyton"), 21);
101+
us.check_out(2, String::from("Paradise"), 30);
102+
assert!(
103+
us.get_average_time(String::from("Leyton"), String::from("Paradise")) - (20.0 / 3.0)
104+
< 0.00001
105+
);
106+
println!("\x1b[92m» All tests passed!\x1b[0m")
107+
}

0 commit comments

Comments
 (0)