開始拿到這個題的時候,首先就會想到兩點確定一條直線,若要判斷相應的點是否在同一條直線上,僅需求出它們的斜率即可。
但是此題需注意的幾點是:(1)當斜率不存在的情況:即(y2-y1)/(x2-x1)中(x2-x1)爲0的情況。
(2)當斜率爲0的情況:即(y2-y1)爲0的情況。
(3)最後需要注意的就是此題有一入坑點就是對斜率的存,一般我們可能會想到用double類型來存斜率,但是double類型也有精度不準的機率,導致程序出錯,所以在此我選擇了用最大公約數(最大公因子)gcd來使用分數來代替斜率(此時需要保證分子分母最簡)。
即使用一個Map<Integer, Map<Integer, Integer>> map = new HashMao<>();
其中第一個Integer代表的是(x2-x1)/gcd, 即分母;內嵌的key代表的是(y2-y1)/gcd,即分子;value代表的是出現次斜率的次數。
其中需要一個在每一次外部遍歷時記錄一個特殊情況計數器,即overLop.
import java.util.Map;
import java.util.HashMap;
/**
* Definition for a point.
* class Point {
* int x;
* int y;
* Point() { x = 0; y = 0; }
* Point(int a, int b) { x = a; y = b; }
* }
*/
/*
給定位於二維平面上的n個點,求出位於同一條直線上的最大點數
思路:(1)位於同一直線上即就是斜率相同,用一個hashmap記錄下斜率和點數量的映射關係;
(2)特殊情況:兩個點重合
*/
public class Solution {
public int maxPoints(Point[] points) {
if(points == null){
return 0;
}
if(points.length <=2 ){
return points.length;
}
Map<Integer, Map<Integer,Integer>> map = new HashMap<>();
//設置最終的結果
int res = 0;
//設置每一輪比較後的最大值
int max = 0;
for(int i=0;i<points.length-1;i++){
map.clear();
int overLop=0;//考慮特殊情況
max = 0;
for(int j=i+1;j<points.length;j++){
int x = points[j].x - points[i].x;
int y = points[j].y - points[i].y;
if(x == 0 && y == 0){
overLop++;
continue;
}
//計算最大公約數
//想用分數代表斜率,必須保證分子分母最簡
int gcd = generateor(x,y);
if(gcd != 0){
x = x/gcd;
y = y/gcd;
}
if(map.containsKey(x)){
if(map.get(x).containsKey(y)){
map.get(x).put(y,map.get(x).get(y)+1);
}else{
map.get(x).put(y,1);
}
}else{
Map<Integer,Integer> temp = new HashMap<>();
temp.put(y,1);
map.put(x,temp);
}
max = Math.max(max, map.get(x).get(y) );
}
res = Math.max(res, max+overLop+1);
}
return res;
}
private int generateor(int x, int y){//歐幾里得算法
if(y == 0){
return x;
}
return generateor(y, x%y);
}
}