Given an array of points where points[i] = [xi, yi] represents a point on the X-Y plane, return the maximum number of points that lie on the same straight line.
Example 1:
Input: points = [[1,1],[2,2],[3,3]]
Output: 3
Example 2:
Input: points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
Constraints:
- 1 <= points.length <= 300
- points[i].length == 2
- -104 <= xi, yi <= 104
- All the points are unique.
看了看 points 的数量, 计算所有(points[i], points[j])的斜率也不超过 10^5, 所以我们可以定下来一个基调, 就是求出所有 points[j]相对于 points[i]的斜率, 同时记录相对于 points[i]具有相同斜率的 point 的数量, 最终我们只需要找出最大的数量就可以了。因为浮点数不准确,所以我们的斜率还是要用整数来表达,分为 3 个部分, 整数部分、分子和分母, 整数部分好解决, 直接用(yj - yi) / (xj - xi)就可以得到, 分子和分母部分为了可以进行比较, 我们需要进行约分, 也就是分子和分母同时除以最大公约数, 至于最大公约数的算法, 这里不做过多赘述, 网上一搜一大把, 而且也不难理解。这样整体的流程基本就完了, 但是还有个细节问题就是(xj - xi)可能为 0, 这样(yj - yi) / (xj - xi)就会 panic, 我们需要用一个特殊的值来保存这种无限大的斜率, 我们继续看题目的约束, 里面提到了-10^4 <= xi, yi <= 10^4, 而 xi 与 yi 又都是整数, 所以非无限大的斜率最大也就是(2 * 10 ^ 4) / 1, 所以我们无限大斜率只要大于这个值就不会与可能出现的斜率相冲突。
use std::collections::HashMap;
impl Solution {
fn gcd(a: i32, b: i32) -> i32 {
if a == 0 {
return b;
}
if a.abs() > b.abs() {
return Solution::gcd(a % b, b);
}
return Solution::gcd(b % a, a);
}
pub fn max_points(points: Vec<Vec<i32>>) -> i32 {
let mut slopes = HashMap::new();
for i in 0..points.len() {
for j in 0..points.len() {
if i == j {
continue;
}
let xi = points[i][0];
let yi = points[i][1];
let xj = points[j][0];
let yj = points[j][1];
let dx = xj - xi;
if dx == 0 {
*slopes.entry((xi, yi, 100000, 0, 0)).or_insert(1) += 1;
continue;
}
let dy = yj - yi;
let m = dy / dx;
let r = dy % dx;
let gcd = Solution::gcd(r, dx);
*slopes.entry((xi, yi, m, r / gcd, dx / gcd)).or_insert(1) += 1;
}
}
if let Some(c) = slopes.values().max() {
*c
} else {
1
}
}
}