Here is my solution. The idea others had, to use a*x + b*y + c = 0 to store the lines has one big benefit: you can store these three values as integers and therefore can use your Line as key for a Hashmap. But it will also have one downside - you have to take care of cases like 1*x + 1*y + 0 and 2*x+2*y + 0 and therefore calculate the gcd which will bump your solution to O(n^2log(n))

Using the other format y = m*x + b you will end up with fractions which will be float or double which should NEVER be used in Objects that are supposed to be Hashmap keys.

So how to circumvent this problem? This is the idea: mulitply the slope m and y-distance b (don't know the technical english term) by 1000 and then store this value as int. Basically you're saying you will only need 3 digits after the decimal point with a multiplier by 1000.

There are two caveats:

- We do have limited precision (but 3 digits after the decimal point should be enough here)
- If we have "big" points we could get overflow problems (because multiplying by 1000).

What do you guys think?

```
public class Solution {
public int maxPoints(Point[] points) {
if(points == null || points.length == 0) { return 0; }
if(points.length == 1) { return 1; }
Map<Line, Set<Integer>> lineMap = new HashMap<>();
int max = 2;
for(int i = 0; i < points.length-1; i++) {
for(int j = i+1; j < points.length; j++) {
Line cur = new Line(points[i], points[j]);
if(!lineMap.containsKey(cur)) {
Set<Integer> pointSet = new HashSet<>();
pointSet.add(i);
pointSet.add(j);
lineMap.put(cur, pointSet);
} else {
Set<Integer> pointSet = lineMap.get(cur);
if(!pointSet.contains(i)) {
pointSet.add(i);
}
if(!pointSet.contains(j)) {
pointSet.add(j);
}
max = Math.max(pointSet.size(), max);
}
}
}
return max;
}
private static class Line {
final static int ACC_MULT = 1000;
// Note: slope and yDist are multiplied by ACC_MULT;
int slope;
int yDist;
int xDist;
boolean infSlope;
Line(Point p1, Point p2) {
if(p2.x - p1.x == 0) {
infSlope = true;
xDist = p1.x;
} else {
slope = ((p2.y - p1.y) * ACC_MULT) / (p2.x - p1.x);
yDist = ((p1.x*p2.y-p2.x*p1.y) * ACC_MULT) / (p1.x-p2.x);
}
}
@Override
public boolean equals(Object o) {
if (o == this) { return true; }
if (!(o instanceof Line)) { return false; }
Line line = (Line) o;
return line.slope == this.slope &&
line.yDist == this.yDist &&
line.infSlope == this.infSlope &&
line.xDist == this.xDist;
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + slope;
result = 31 * result + yDist;
result = 31 * result + xDist;
result = 31 * result + ((infSlope) ? 1 : 0);
return result;
}
}
}
```