Created
May 3, 2020 20:31
-
-
Save mexus/ed88ea8fef189939661c69d2436a0f37 to your computer and use it in GitHub Desktop.
Solution to "Data Stream as Disjoint Intervals" Leetcode problem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{ | |
cmp::{self, Ordering}, | |
collections::BTreeSet, | |
}; | |
#[derive(Default)] | |
pub struct SummaryRanges { | |
ranges: BTreeSet<ClosedRange>, | |
} | |
// A closed range. | |
#[derive(Debug, Clone, Copy)] | |
struct ClosedRange { | |
begin: i32, | |
end: i32, | |
} | |
impl Ord for ClosedRange { | |
fn cmp(&self, other: &Self) -> Ordering { | |
if self.end < other.begin.saturating_sub(1) { | |
// . . a . . . b . . . . . . | |
// . . . . . . . . c . . . d | |
Ordering::Less | |
} else if self.end == other.begin.saturating_sub(1) { | |
// . . a . . . b . . . . . | |
// . . . . . . . c . . . d | |
Ordering::Equal | |
} else if self.begin > other.end.saturating_add(1) { | |
// . . . . . . . . a . . . b | |
// . . c . . . d . . . . . . | |
Ordering::Greater | |
} else if self.begin == other.end.saturating_add(1) { | |
// . . . . . . . a . . . b | |
// . . c . . . d . . . . . | |
Ordering::Equal | |
} else { | |
// Overlapping means equality. | |
Ordering::Equal | |
} | |
} | |
} | |
impl PartialOrd for ClosedRange { | |
fn partial_cmp(&self, other: &ClosedRange) -> Option<cmp::Ordering> { | |
Some(self.cmp(other)) | |
} | |
} | |
impl Eq for ClosedRange {} | |
impl PartialEq for ClosedRange { | |
fn eq(&self, other: &ClosedRange) -> bool { | |
self.cmp(other) == Ordering::Equal | |
} | |
} | |
impl ClosedRange { | |
/// Creates a "range" that contains only one value. | |
pub fn new(value: i32) -> Self { | |
ClosedRange { | |
begin: value, | |
end: value, | |
} | |
} | |
/// Merges two ranges together. The ranges must overlap or share a border. | |
pub fn merge(self, other: ClosedRange) -> ClosedRange { | |
debug_assert_eq!(self, other); | |
let begin = cmp::min(self.begin, other.begin); | |
let end = cmp::max(self.end, other.end); | |
ClosedRange { begin, end } | |
} | |
/// Converts the range into a pair of numbers. | |
pub fn to_vec(&self) -> Vec<i32> { | |
vec![self.begin, self.end] | |
} | |
} | |
impl SummaryRanges { | |
pub fn new() -> Self { | |
Self::default() | |
} | |
pub fn add_num(&mut self, val: i32) { | |
let mut temp_range = ClosedRange::new(val); | |
while let Some(range) = self.ranges.take(&temp_range) { | |
temp_range = range.merge(temp_range); | |
} | |
self.ranges.insert(temp_range); | |
} | |
pub fn get_intervals(&self) -> Vec<Vec<i32>> { | |
self.ranges.iter().map(ClosedRange::to_vec).collect() | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn range() { | |
let one = ClosedRange::new(1); | |
let two = ClosedRange::new(2); | |
let three = ClosedRange::new(3); | |
assert_eq!(one.cmp(&two), Ordering::Equal); | |
assert_eq!(two.cmp(&one), Ordering::Equal); | |
assert_ne!(one.cmp(&three), Ordering::Equal); | |
assert_ne!(three.cmp(&one), Ordering::Equal); | |
let one_two = one.merge(two); | |
assert_eq!(one_two.begin, 1); | |
assert_eq!(one_two.end, 2); | |
assert_eq!(one_two.cmp(&three), Ordering::Equal); | |
assert_eq!(three.cmp(&one_two), Ordering::Equal); | |
let one_three = one_two.merge(three); | |
assert_eq!(one_three.begin, 1); | |
assert_eq!(one_three.end, 3); | |
assert_eq!(one_three.cmp(&two), Ordering::Equal); | |
assert_eq!(two.cmp(&one_three), Ordering::Equal); | |
} | |
#[test] | |
fn it_works() { | |
let mut summary = SummaryRanges::new(); | |
assert!(summary.get_intervals().is_empty()); | |
summary.add_num(1); | |
assert_eq!(summary.get_intervals(), vec!(vec!(1, 1))); | |
summary.add_num(3); | |
assert_eq!(summary.get_intervals(), vec!(vec!(1, 1), vec!(3, 3))); | |
summary.add_num(7); | |
assert_eq!( | |
summary.get_intervals(), | |
vec!(vec!(1, 1), vec!(3, 3), vec!(7, 7)) | |
); | |
summary.add_num(2); | |
assert_eq!(summary.get_intervals(), vec!(vec!(1, 3), vec!(7, 7))); | |
summary.add_num(6); | |
assert_eq!(summary.get_intervals(), vec!(vec!(1, 3), vec!(6, 7))); | |
summary.add_num(6); | |
assert_eq!(summary.get_intervals(), vec!(vec!(1, 3), vec!(6, 7))); | |
summary.add_num(2); | |
assert_eq!(summary.get_intervals(), vec!(vec!(1, 3), vec!(6, 7))); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment