一、题目
给你一个数组 points ,其中 points[i] = [x, y] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
点击查看原题
难度级别: 困难
二、思路
1)哈希表+斜率表达
首先,考虑在同一条直线上的点,其两两之间斜率一定相等,普通的斜率表达如下所示:
在代码中令:
因为比值相等时,其最简形式一定相等,求出diffX和diffY的最大公约数(这里使用辗转相除法),并除以最大公约数。斜率有负值的情况,但不知道是分子还是分母,假定diffX不能小于0,小于的话就将分子分母取相反数。
因为-10 <= x, y <= 10,斜率采用另一种表达方式,kVal`` = diffY + diffX*``100000,将diffX移到高位进行表示。
使用两层for循环,选择一个点对其他所有点进行斜率计算,每次选择一个点都建立新的哈希表,该哈希表记录经过选取点所有直线斜率和直线上点的数量。
三、代码
1)哈希表+斜率表达
class Solution {public int maxPoints(int[][] points) {int ans = 1;for (int k = 0; k < points.length; k++) {Map<Integer, Integer> map = new HashMap();for (int i = 0; i < points.length; i++) {if (i == k) { // 跳过自身点continue;}int diffX = points[i][0] - points[k][0]; // 获取坐标差值int diffY = points[i][1] - points[k][1];int gcdVal = gcd(Math.abs(diffX), Math.abs(diffY)); // 获取最大公约数diffX = diffX / gcdVal;diffY = diffY / gcdVal;if (diffX < 0) { // 指定diffX不能为小于0的数diffX = -diffX;diffY = -diffY;}int kVal = diffY + diffX*100000; // 通过将diffX移动到高位形成唯一的斜率编码map.put(kVal, map.getOrDefault(kVal, 1) + 1);}for (Map.Entry<Integer, Integer> entry : map.entrySet()) {ans = Math.max(ans, entry.getValue());}}return ans;}private int gcd(int a, int b) { // 辗转相除法return b != 0 ? gcd(b, a%b) : a;}}
n为点总数,m为横纵坐标差最大值,时间复杂度O(n^2``*logm),空间复杂度为O(n)
