20241223 finished.
This commit is contained in:
parent
7a54ca5ff9
commit
e92b2cb4b1
|
@ -386,3 +386,5 @@ mod p3138_minimum_length_of_anagram_concatenation;
|
||||||
mod p2545_sort_the_students_by_their_kth_score;
|
mod p2545_sort_the_students_by_their_kth_score;
|
||||||
|
|
||||||
mod p1387_sort_integers_by_the_power_value;
|
mod p1387_sort_integers_by_the_power_value;
|
||||||
|
|
||||||
|
mod p855_exam_room;
|
||||||
|
|
154
src/problem/p855_exam_room.rs
Normal file
154
src/problem/p855_exam_room.rs
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/**
|
||||||
|
* [855] Exam Room
|
||||||
|
*/
|
||||||
|
pub struct Solution {}
|
||||||
|
|
||||||
|
// submission codes start here
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::{BTreeSet, BinaryHeap};
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
struct Interval {
|
||||||
|
start: i32,
|
||||||
|
end: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interval {
|
||||||
|
fn new(start: i32, end: i32) -> Self {
|
||||||
|
Self { start, end }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn distance(&self) -> i32 {
|
||||||
|
(self.end - self.start) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Interval {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
// Interval将会被放入BinaryHeap中进行排序
|
||||||
|
// 所以先返回middle的大
|
||||||
|
// 再返回start小的
|
||||||
|
match self.distance().cmp(&other.distance()) {
|
||||||
|
Ordering::Equal => other.start.cmp(&self.start),
|
||||||
|
r => r,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Interval {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(&other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ExamRoom {
|
||||||
|
n: i32,
|
||||||
|
seats: BTreeSet<i32>,
|
||||||
|
intervals: BinaryHeap<Interval>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `&self` means the method takes an immutable reference.
|
||||||
|
* If you need a mutable reference, change it to `&mut self` instead.
|
||||||
|
*/
|
||||||
|
impl ExamRoom {
|
||||||
|
fn new(n: i32) -> Self {
|
||||||
|
Self {
|
||||||
|
n,
|
||||||
|
seats: BTreeSet::new(),
|
||||||
|
intervals: BinaryHeap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seat(&mut self) -> i32 {
|
||||||
|
if self.seats.is_empty() {
|
||||||
|
self.seats.insert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 坐在最左边到左边同学的距离
|
||||||
|
let left = *self.seats.iter().next().unwrap();
|
||||||
|
let right = self.n - 1 - *self.seats.iter().rev().next().unwrap();
|
||||||
|
|
||||||
|
// 当当前坐着的同学数量大于等于2
|
||||||
|
while self.seats.len() >= 2 {
|
||||||
|
if let Some(interval) = self.intervals.peek() {
|
||||||
|
// 判断是否需要延迟删除该区间
|
||||||
|
if !self.seats.contains(&interval.start)
|
||||||
|
|| !self.seats.contains(&interval.end)
|
||||||
|
|| *self.seats.range((interval.start + 1)..).next().unwrap() != interval.end
|
||||||
|
{
|
||||||
|
self.intervals.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断坐在区间的中间是否比坐在两个端点更好
|
||||||
|
let distance = interval.distance();
|
||||||
|
// 小于等于 left 是因为当距离一致时坐在较小的地方
|
||||||
|
if distance < right || distance <= left {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择坐在中间
|
||||||
|
let interval = self.intervals.pop().unwrap();
|
||||||
|
let middle = interval.start + distance;
|
||||||
|
self.intervals.push(Interval::new(interval.start, middle));
|
||||||
|
self.intervals.push(Interval::new(middle, interval.end));
|
||||||
|
self.seats.insert(middle);
|
||||||
|
return middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有一个同学
|
||||||
|
if right > left {
|
||||||
|
let last = *self.seats.last().unwrap();
|
||||||
|
self.intervals.push(Interval::new(last, self.n - 1));
|
||||||
|
self.seats.insert(self.n - 1);
|
||||||
|
self.n - 1
|
||||||
|
} else {
|
||||||
|
let first = *self.seats.first().unwrap();
|
||||||
|
self.intervals.push(Interval::new(0, first));
|
||||||
|
self.seats.insert(0);
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn leave(&mut self, p: i32) {
|
||||||
|
// 如果学生不是最左或者是最右的区间
|
||||||
|
// 那么删除会产生新的区间
|
||||||
|
// 判断区间是否有效是Self::seat()的工作
|
||||||
|
if p != *self.seats.first().unwrap() && p != *self.seats.last().unwrap() {
|
||||||
|
let pre = *self.seats.range(..p).last().unwrap();
|
||||||
|
let next = *self.seats.range((p + 1)..).next().unwrap();
|
||||||
|
|
||||||
|
self.intervals.push(Interval::new(pre, next));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.seats.remove(&p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Your ExamRoom object will be instantiated and called as such:
|
||||||
|
* let obj = ExamRoom::new(n);
|
||||||
|
* let ret_1: i32 = obj.seat();
|
||||||
|
* obj.leave(p);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// submission codes end
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_855() {
|
||||||
|
let mut room = ExamRoom::new(10);
|
||||||
|
assert_eq!(0, room.seat());
|
||||||
|
assert_eq!(9, room.seat());
|
||||||
|
assert_eq!(4, room.seat());
|
||||||
|
assert_eq!(2, room.seat());
|
||||||
|
room.leave(4);
|
||||||
|
assert_eq!(5, room.seat());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user