Skip to content

Commit 0143b95

Browse files
committed
Added Task Scheduler
1 parent 0d926ff commit 0143b95

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

Diff for: src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ pub mod subtree_of_another_tree; // 572 ✓
377377

378378
pub mod can_place_flowers; // 605 ✓
379379

380+
pub mod task_scheduler; // 621 ✓
381+
380382
pub mod average_of_levels_in_binary_tree; // 637
381383

382384
pub mod maximum_average_subarray_i; // 643

Diff for: src/task_scheduler.rs

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
use std::collections::BinaryHeap;
2+
use std::collections::HashMap;
3+
use std::collections::HashSet;
4+
use std::collections::VecDeque;
5+
6+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
7+
struct Item {
8+
count: usize,
9+
letter: char,
10+
}
11+
12+
impl Item {
13+
14+
pub fn new(letter: char) -> Self {
15+
Self { count: 1, letter }
16+
}
17+
18+
pub fn increment(&mut self) {
19+
self.count += 1;
20+
}
21+
22+
pub fn decrement(&mut self) {
23+
if self.count > 0 {
24+
self.count -= 1;
25+
}
26+
}
27+
28+
pub fn is_empty(&self) -> bool {
29+
self.count == 0
30+
}
31+
32+
}
33+
34+
/// Given a character array `tasks`, representing the tasks a CPU needs to do, where each letter
35+
/// represents a different task. Tasks could be done in any order. Each task is done in one unit of
36+
/// time, the CPU could complete either one task or just be idle.
37+
///
38+
/// However, there is a non-negative integer `n` that represents the cooldown period between the
39+
/// two same tasks (the same letter in the array), that is that there must be at least `n` units of
40+
/// time between any two same tasks.
41+
///
42+
/// Return the least number of units of times that the CPU will take to finish all the given tasks.
43+
struct Solution;
44+
45+
impl Solution {
46+
47+
fn to_counts(tasks: Vec<char>) -> HashMap<char, Item> {
48+
let mut results = HashMap::new();
49+
50+
for task in tasks {
51+
results
52+
.entry(task)
53+
.and_modify(|item: &mut Item| item.increment())
54+
.or_insert(Item::new(task));
55+
}
56+
57+
results
58+
}
59+
60+
fn to_heap(counts: HashMap<char, Item>) -> BinaryHeap<Item> {
61+
let mut results = BinaryHeap::new();
62+
63+
for value in counts.values() {
64+
results.push(*value);
65+
}
66+
67+
results
68+
}
69+
70+
// The actual solution is much simpler than this in that the slots can
71+
// be prefilled by starting with the highest counts and scheduling them
72+
// for the slot in the future when they'll next be able to be run.
73+
pub fn least_interval(tasks: Vec<char>, n: i32) -> i32 {
74+
let mut result = 0;
75+
let n = n as usize;
76+
77+
let counts = Self::to_counts(tasks);
78+
let mut heap = Self::to_heap(counts);
79+
80+
let mut queue: VecDeque<char> = VecDeque::new();
81+
let mut current: HashSet<char> = HashSet::new();
82+
83+
while !heap.is_empty() {
84+
result += 1;
85+
86+
if queue.len() == n+1 {
87+
let first = queue.pop_front().unwrap();
88+
if first != ' ' {
89+
current.remove(&first);
90+
}
91+
}
92+
let mut options: Vec<Item> = Vec::new();
93+
let mut choice = ' ';
94+
while !heap.is_empty() {
95+
let mut option = heap.pop().unwrap();
96+
if current.contains(&option.letter) {
97+
options.push(option);
98+
} else {
99+
option.decrement();
100+
choice = option.letter;
101+
if !option.is_empty() {
102+
options.push(option);
103+
}
104+
break;
105+
}
106+
}
107+
queue.push_back(choice);
108+
current.insert(choice);
109+
for option in options {
110+
heap.push(option);
111+
}
112+
}
113+
114+
result
115+
}
116+
117+
}
118+
119+
#[cfg(test)]
120+
mod tests {
121+
use super::Solution;
122+
123+
#[test]
124+
fn example_1() {
125+
// [A, B, _, A, B, _, A, B]
126+
let tasks = vec!['A', 'A', 'A', 'B', 'B', 'B'];
127+
let n = 2;
128+
let result = Solution::least_interval(tasks, n);
129+
assert_eq!(result, 8);
130+
}
131+
132+
#[test]
133+
fn example_2() {
134+
// [A, A, A, B, B, B]
135+
let tasks = vec!['A', 'A', 'A', 'B', 'B', 'B'];
136+
let n = 0;
137+
let result = Solution::least_interval(tasks, n);
138+
assert_eq!(result, 6);
139+
}
140+
141+
#[test]
142+
fn example_3() {
143+
// [A, B, C, A, D, E, A, F, G, A, _, _, A, _, _, A]
144+
let tasks = vec!['A','A','A','A','A','A','B','C','D','E','F','G'];
145+
let n = 2;
146+
let result = Solution::least_interval(tasks, n);
147+
assert_eq!(result, 16);
148+
}
149+
150+
}

0 commit comments

Comments
 (0)