From f26fe3244096d157e2eb8ea777cdbb4ba1b65d60 Mon Sep 17 00:00:00 2001 From: Xu Shaohua Date: Thu, 9 May 2024 21:44:38 +0800 Subject: [PATCH] leetcode: Add 0973 --- .../Cargo.toml | 7 + .../0973.k-closest-points-to-origin/index.md | 4 + .../src/main.rs | 122 ++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 src/leetcode/0973.k-closest-points-to-origin/Cargo.toml create mode 100644 src/leetcode/0973.k-closest-points-to-origin/index.md create mode 100644 src/leetcode/0973.k-closest-points-to-origin/src/main.rs diff --git a/src/leetcode/0973.k-closest-points-to-origin/Cargo.toml b/src/leetcode/0973.k-closest-points-to-origin/Cargo.toml new file mode 100644 index 00000000..e994666a --- /dev/null +++ b/src/leetcode/0973.k-closest-points-to-origin/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "lc-0973-k-closest-points-to-origin" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/src/leetcode/0973.k-closest-points-to-origin/index.md b/src/leetcode/0973.k-closest-points-to-origin/index.md new file mode 100644 index 00000000..77a618ba --- /dev/null +++ b/src/leetcode/0973.k-closest-points-to-origin/index.md @@ -0,0 +1,4 @@ + +# + +[问题描述](../problems/) diff --git a/src/leetcode/0973.k-closest-points-to-origin/src/main.rs b/src/leetcode/0973.k-closest-points-to-origin/src/main.rs new file mode 100644 index 00000000..7fa94aa8 --- /dev/null +++ b/src/leetcode/0973.k-closest-points-to-origin/src/main.rs @@ -0,0 +1,122 @@ +// Copyright (c) 2024 Xu Shaohua . All rights reserved. +// Use of this source is governed by General Public License that can be found +// in the LICENSE file. + +use std::cmp::{Ord, Ordering, PartialOrd}; +use std::collections::BinaryHeap; + +// Priority Queue +pub fn k_closest1(points: Vec>, k: i32) -> Vec> { + assert!(k >= 1 && (k as usize) <= points.len()); + + #[derive(Debug, Clone, Eq, PartialEq)] + struct Entry { + dist: i64, + point: Vec, + } + impl PartialOrd for Entry { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + impl Ord for Entry { + fn cmp(&self, other: &Self) -> Ordering { + self.dist.cmp(&other.dist) + } + } + + // 构造优先级队列. + let k = k as usize; + let mut heap: BinaryHeap = BinaryHeap::with_capacity(k + 1); + for point in points { + // 这里, 不需要求平方根, 因为不够精确, 也没必要, 只需要计算出 x*x + y*y 的值即可. + // 为了处理整数溢出, 先转成 i64. + let x = point[0] as i64; + let y = point[1] as i64; + let dist: i64 = x * x + y * y; + //println!("dist: {dist}, point: {point:?}"); + heap.push(Entry { dist, point }); + if heap.len() > k { + heap.pop(); + } + } + + let mut out = Vec::with_capacity(k); + while let Some(top_entry) = heap.pop() { + out.push(top_entry.point); + } + // 再次排序. + out.reverse(); + out +} + +// 有序数组 +pub fn k_closest2(points: Vec>, k: i32) -> Vec> { + assert!(k >= 1 && (k as usize) <= points.len()); + + // 构造优先级队列. + let k = k as usize; + let mut point_dists: Vec<(i64, Vec)> = points + .into_iter() + .map(|point| { + // 这里, 不需要求平方根, 因为不够精确, 也没必要, 只需要计算出 x*x + y*y 的值即可. + // 为了处理整数溢出, 先转成 i64. + let x = point[0] as i64; + let y = point[1] as i64; + let dist: i64 = x * x + y * y; + (dist, point) + }) + .collect(); + // 根据 dist 升序排列 + point_dists.sort_by(|a, b| a.0.cmp(&b.0)); + + // 取前k个元素 + point_dists + .into_iter() + .take(k) + .map(|(_dist, point)| point) + .collect() +} + +// TODO(Shaohua): Quickselect + +pub type SolutionFn = fn(Vec>, i32) -> Vec>; + +fn check_solution(func: SolutionFn) { + let points = vec![vec![1, 3], vec![-2, 2]]; + let k = 1; + assert_eq!(func(points, k), vec![vec![-2, 2]]); + + let points = vec![vec![3, 3], vec![5, -1], vec![-2, 4]]; + let k = 1; + assert_eq!(func(points, k), vec![vec![3, 3]]); + + let points = vec![vec![3, 3], vec![5, -1], vec![-2, 4]]; + let k = 2; + assert_eq!(func(points, k), vec![vec![3, 3], vec![-2, 4]]); + + let points = vec![vec![9997, 9997], vec![9996, 9998]]; + let k = 1; + assert_eq!(func(points, k), vec![vec![9997, 9997]]); +} + +fn main() { + check_solution(k_closest1); + check_solution(k_closest2); +} + +#[cfg(test)] +mod tests { + use super::{check_solution, k_closest1, k_closest2}; + + #[test] + fn test_k_closest1() { + check_solution(k_closest1); + } + + #[test] + fn test_k_closest2() { + check_solution(k_closest2); + } +}