use std::{cmp::Ordering, ops::Range};
trait BinarySearch<F, Idx>
where
F: FnMut(Idx) -> Ordering
{
fn binary_search_by(&self, f: F) -> Result<Idx, Idx>;
fn binary_search_min_by(&self, f: F) -> Idx;
fn binary_search_max_by(&self, f: F) -> Idx;
}
macro_rules! impl_binary_search_for_range {
($($t:ty)*) => ($(
impl<F> BinarySearch<F, $t> for Range<$t>
where F: FnMut($t) -> Ordering,
{
fn binary_search_by(&self, mut f: F) -> Result<$t, $t> {
let mut left = self.start;
let mut right = self.end;
while left < right {
let middle = left + (right - left) / 2;
match f(middle) {
Ordering::Equal => return Ok(middle),
Ordering::Less => left = middle + 1,
Ordering::Greater => right = middle
}
}
Err(left)
}
fn binary_search_min_by(&self, mut f: F) -> $t {
let search_result =
Self::binary_search_by(&self, |index| {
match f(index) {
Ordering::Equal => Ordering::Greater,
other => other
}
});
search_result.unwrap_or_else(|i| i)
}
fn binary_search_max_by(&self, mut f: F) -> $t {
let search_result =
Self::binary_search_by(&self, |index| {
match f(index) {
Ordering::Equal => Ordering::Less,
other => other
}
});
search_result.unwrap_or_else(|i| i)
}
}
)*)
}
impl_binary_search_for_range!{ i32 }
impl Solution {
pub fn max_distance(mut position: Vec<i32>, m: i32) -> i32 {
position.sort_unstable();
let n = position.len();
let max_pos = position[n - 1];
let hi = (max_pos / (m - 1)) + (max_pos % (m - 1) != 0) as i32 + 1;
let mut answer = 0;
(1..hi).binary_search_max_by(|min_dist| {
let mut ball_count = 1;
let mut last_ball_pos = position[0];
for &pos in position.iter().skip(1) {
if pos - last_ball_pos >= min_dist {
ball_count += 1;
last_ball_pos = pos;
}
}
if ball_count >= m {
answer = min_dist;
}
m.cmp(&ball_count)
});
answer
}
}