直線上最多的點數問題
作者:Grey
原文地址:直線上最多的點數問題
題目描述
LeetCode 149. Max Points on a Line
思路
共線的點,有如下可能
第一種可能:點在同一條水平線上,即縱座標的一樣。
第二種可能:點在同一個豎直線上,即橫座標一樣。
第三種可能:點連成的線共斜率,即斜率一致。
三種可能分別如下圖
共水平線,共豎線的值單獨統計,針對共斜率的線,我們設計如下結構來存
Map<Integer,Map<Integer,Integer>> map = new HashMap<>();
map
通過如下方式來存斜率,例如:
Map<Integer,Integer> m = new HashMap<>();
m.put(3,30);
map.put(4,m);
表示:斜率爲3/4
的點有30
個。
再如:
Map<Integer,Integer> m = new HashMap<>();
m.put(7,10);
map.put(5,m);
表示:斜率爲7/5
的點有10
個。
假設兩個點的座標爲(x1,y1)
和(x2,y2)
,那麼斜率tan = (y1-y2)/(x1-x2)
,由於要用分數來表示,所以要化簡,即先求x2-x1
和y2-y1
的最大公約數(輾轉相除法)。
private static int gcd(int m, int n) {
return n == 0 ? m : gcd(n, m % n);
}
完整代碼如下:
public static int maxPoints(int[][] points) {
if (points == null || points.length == 0) {
return 0;
}
if (points.length == 1) {
return 1;
}
int max = 1;
// map形如(3,(4,10)) 表示:斜率爲3/4的點有10個
Map<Integer, Map<Integer, Integer>> map = new HashMap<>();
for (int i = 0; i < points.length; i++) {
map.clear();
int sameY = 1;
int sameX = 1;
int sameSlope = 1;
int x1 = points[i][0];
int y1 = points[i][1];
for (int j = i + 1; j < points.length; j++) {
int x2 = points[j][0];
int y2 = points[j][1];
if (x2 == x1) {
sameX++;
} else if (y2 == y1) {
sameY++;
} else {
int rangeY = y2 - y1;
int rangeX = x2 - x1;
int z = gcd(rangeX, rangeY);
rangeY = rangeY / z;
rangeX = rangeX / z;
if (map.containsKey(rangeY)) {
Map<Integer, Integer> m = map.get(rangeY);
if (m.containsKey(rangeX)) {
m.put(rangeX, m.get(rangeX) + 1);
map.put(rangeY, m);
} else {
m.put(rangeX, 2);
map.put(rangeY, m);
}
} else {
Map<Integer, Integer> m = new HashMap<>();
m.put(rangeX, 2);
map.put(rangeY, m);
}
sameSlope = Math.max(map.get(rangeY).get(rangeX), sameSlope);
}
max = Math.max(max, Math.max(Math.max(sameX, sameY), sameSlope));
}
}
return max;
}
private static int gcd(int m, int n) {
return n == 0 ? m : gcd(n, m % n);
}