Skip to content

Commit 4f3b4d1

Browse files
committed
LC 632. Smallest Range Covering Elements from K Lists (Rust)
1 parent be435e1 commit 4f3b4d1

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ to the solution in this repository.
325325
| [623. Add One Row to Tree][lc623] | 🟠 Medium | [![python](res/py.png)][lc623py] |
326326
| [629. K Inverse Pairs Array][lc629] | 🔴 Hard | [![python](res/py.png)][lc629py] |
327327
| [630. Course Schedule III][lc630] | 🔴 Hard | [![python](res/py.png)][lc630py] |
328+
| [632. Smallest Range Covering Elements from K Lists][lc632] | 🔴 Hard | [![rust](res/rs.png)][lc632rs] |
328329
| [633. Sum of Square Numbers][lc633] | 🟠 Medium | [![rust](res/rs.png)][lc633rs] |
329330
| [637. Average of Levels in Binary Tree][lc637] | 🟢 Easy | [![python](res/py.png)][lc637py] |
330331
| [641. Design Circular Deque][lc641] | 🟠 Medium | [![python](res/py.png)][lc641py] |
@@ -1480,6 +1481,8 @@ to the solution in this repository.
14801481
[lc629py]: leetcode/k-inverse-pairs-array.py
14811482
[lc630]: https://leetcode.com/problems/course-schedule-iii/
14821483
[lc630py]: leetcode/course-schedule-iii.py
1484+
[lc632]: https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/
1485+
[lc632rs]: leetcode/smallest-range-covering-elements-from-k-lists.rs
14831486
[lc633]: https://leetcode.com/problems/sum-of-square-numbers/
14841487
[lc633rs]: leetcode/sum-of-square-numbers.rs
14851488
[lc637]: https://leetcode.com/problems/average-of-levels-in-binary-tree/
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// 632. Smallest Range Covering Elements from K Lists
2+
// 🔴 Hard
3+
//
4+
// https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/
5+
//
6+
// Tags: Array - Hash Table - Greedy - Sliding Window - Sorting - Heap (Priority Queue)
7+
8+
use std::{cmp::Reverse, collections::BinaryHeap, i32};
9+
10+
struct Solution;
11+
impl Solution {
12+
/// Use a heap with one value from each list to keep track of ranges, keep track of the largest
13+
/// value in the heap manually. Keep popping the top of the heap and pushing the next value
14+
/// from the same list, for each pop, recompute the current range of values and, if it is
15+
/// strictly smaller than the current smallest, update the result.
16+
///
17+
/// Time complexity: O(nlog(k)) - We use a heap of size k where we may push all the values in
18+
/// all the lists in nums. Each push/pop is log(k).
19+
/// Space complexity: O(K) - Where k is the number of lists in nums, we push one value per list
20+
/// into the heap.
21+
///
22+
/// Runtime 9 ms Beats 84%
23+
/// Memory 2.74 MB Beats 92%
24+
pub fn smallest_range(nums: Vec<Vec<i32>>) -> Vec<i32> {
25+
// A heap with value, list index and item index.
26+
let mut heap: BinaryHeap<(Reverse<i32>, usize, usize)> = BinaryHeap::new();
27+
// Keep track of the largest value in the heap.
28+
let mut largest = i32::MIN;
29+
for (idx, list) in nums.iter().enumerate() {
30+
largest = largest.max(list[0]);
31+
heap.push((Reverse(list[0]), idx, 1));
32+
}
33+
// Initialize res with the initial values in the heap.
34+
let mut res = (heap.peek().expect("Non-empty heap").0 .0, largest);
35+
while let Some((_, list_idx, item_index)) = heap.pop() {
36+
// Base case, we are out of items on this list.
37+
if nums[list_idx].len() <= item_index {
38+
break;
39+
}
40+
let num = nums[list_idx][item_index];
41+
largest = largest.max(num);
42+
heap.push((Reverse(num), list_idx, item_index + 1));
43+
let top = heap.peek().expect("A top value").0 .0;
44+
if largest - top < res.1 - res.0 {
45+
res = (top, largest);
46+
}
47+
}
48+
vec![res.0, res.1]
49+
}
50+
}
51+
52+
// Tests.
53+
fn main() {
54+
let tests = [
55+
(
56+
vec![
57+
vec![4, 10, 15, 24, 26],
58+
vec![0, 9, 12, 20],
59+
vec![5, 18, 22, 30],
60+
],
61+
vec![20, 24],
62+
),
63+
(
64+
vec![vec![1, 2, 3], vec![1, 2, 3], vec![1, 2, 3]],
65+
vec![1, 1],
66+
),
67+
];
68+
println!("\n\x1b[92m» Running {} tests...\x1b[0m", tests.len());
69+
let mut success = 0;
70+
for (i, t) in tests.iter().enumerate() {
71+
let res = Solution::smallest_range(t.0.clone());
72+
if res == t.1 {
73+
success += 1;
74+
println!("\x1b[92m✔\x1b[95m Test {} passed!\x1b[0m", i);
75+
} else {
76+
println!(
77+
"\x1b[31mx\x1b[95m Test {} failed expected: {:?} but got {:?}!!\x1b[0m",
78+
i, t.1, res
79+
);
80+
}
81+
}
82+
println!();
83+
if success == tests.len() {
84+
println!("\x1b[30;42m✔ All tests passed!\x1b[0m")
85+
} else if success == 0 {
86+
println!("\x1b[31mx \x1b[41;37mAll tests failed!\x1b[0m")
87+
} else {
88+
println!(
89+
"\x1b[31mx\x1b[95m {} tests failed!\x1b[0m",
90+
tests.len() - success
91+
)
92+
}
93+
}

0 commit comments

Comments
 (0)