149. Max Points on a Line (Hard)
https://leetcode.com/problems/max-points-on-a-line/
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Example 1:
Input: [[1,1],[2,2],[3,3]] Output: 3 Explanation: ^ | | o | o | o +-------------> 0 1 2 3 4
Example 2:
Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]] Output: 4 Explanation: ^ | | o | o o | o | o o +-------------------> 0 1 2 3 4 5 6
Solutions
class Solution {
// Be careful of the special cases, same points may occurs more than one times.
public int maxPoints(int[][] points) {
int ans = 0;
if (points == null || points.length == 0) {
return ans;
}
int len = points.length;
if (len <= 2) {
return len;
}
Map<String, Set<Integer>> lineMap = new HashMap<>();
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
// vector from points[j] to points[i], b/a is the slope of the line
int a = points[i][0] - points[j][0];
int b = points[i][1] - points[j][1];
String key;
// a == 0 represents a vertical line;
if (a == 0) {
key = "x=" + points[i][0];
}
// b == 0 represents a horizontal line
else if (b == 0) {
key = "y=" + points[i][1];
} else {
int g = gcd(a, b);
if (g != 0) {
a = a / g;
b = b / g;
}
// y = b/a * x + c --> ay = bx + ac --> c = (ay - bx) / a --> c = m / n
int m = (a * points[i][1] - b * points[i][0]);
int n = a;
g = gcd(m, n);
if (n!= 0 && g != 0) {
m = m / g;
n = n / g;
}
key = a + "#" + b + "#" + m + "#" + n;
}
if (!lineMap.containsKey(key)) {
lineMap.put(key, new HashSet<>());
}
lineMap.get(key).add(i);
lineMap.get(key).add(j);
}
}
int max = 0;
for (String key : lineMap.keySet()) {
max = Math.max(max, lineMap.get(key).size());
}
return max;
}
private int gcd(int a, int b) {
if (a == 0) {
return b;
}
return a / Math.abs(a) * Math.abs(gcd(b % a, a));
}
}