# 149. Max Points on a Line(Linkedin Hard)(Java)

作者:JY

## 题目
Given _n_ points on a 2D plane, find the maximum number of points that lie on the same straight line.

## 分析
题目给出二维点，我们需要求最大的共线点的个数，看到题目我们需要思考如何判断最多的共线点，点(x1, y1)，(x2, y2)，(x3, y3)三点共线条件是：(y2-y1)/(x2-x1) = (y3-y1)/(x3-x1)，对于每个点p出发，对与该点到所有点的斜率我们需要计算出来，判断相同数值的总和其中最多的个数加1（出发点p）即为最多的共线点。但是还有两点特殊情况需要考虑，当x1 = x2，y1!=y2时，为垂直连线，计算斜率时分母为0会出错。

当x1 = x2，y1 = y2时，两点重合，则(x2, y2)和所有(x1, y1)的连线共线。

## 题解1:Brute Force

n个点总共构成n*(n-1)/2条直线，然后对每条直线看看是有多少点在直线上，记录最大值，最后返回结果。而判断一个点i在j,k构成的直线上的条件是points[k].y-points[i].y) _(points[j].x-points[i].x)==(points[j].y-points[i].y)_(points[k].x-points[i].x)。算法总共是三层循环.

### Time complexity: O(n^3)

### Space complexity: O(1)

### 代码如下：
```java
  public class Solution {
    public int maxPoints(Point[] points) {
        int result = 0, n = points.length;
        for (int i = 0; i < n; ++i) {
            int inSame = 1;
            for (int j = i + 1; j < n; ++j) {
                int newResult = 0;
                long a.x = points[i].x, a.y = points[i].y;
                long b.x = points[j].x, b.y = points[j].y;
                if (a.x == b.x && a.y == b.y) {
                    ++inSame;
                    continue;
                }for (int k = 0; k < n; ++k) {
                    int c.x = points[k].x, c.y = points[k].y;
                    if (a.x*b.y + b.x*c.y + c.x*a.y - c.x*b.y - b.x*a.y - a.x * c.y == 0) {
                        ++newresultult;
                    }
                }
                result = Math.max(result, newResult);
            }
            result = Math.max(result, inSame);
        }
        return result;
    }
}
```

##

## 题解2：HashMap空间换时间

哈希表来记录斜率和共线点个数之间的映射，对每个点建立map，斜率是key。 计算斜率分数时，用gcd法。我们还需要顶一个变量duplicate来记录重合点的个数，与哈希表中数值相加，共线点个数总和。

### Time complexity: O(n^2)

### Space complexity: O(n)

### 代码如下：
```java
  public class Solution{
        public int maxPoints(Point[] points) {
            if (points==null) return 0;
            if (points.length<=2) return points.length;
            int res=0;
            for (int i=0;i<points.length;i++){
                Map<String,Integer> map = new HashMap<>();
           //HashMap第一遍遍历所有点，第二遍还是遍历所有点，只要两个点不是同一个点，我们就求出这两两个点的斜率
             //key用来存斜率，value用来存当前斜率下点的个数
                int inSame=0;//定义两个变量用来表示两点重合的情况和在x轴上的情况
                int xAxis =0;
                 int l = points.length;
            for (int j = i + 1; j < l; j++) {
                int x = points[i].x - points[j].x;//分子
                int y = points[i].y - points[j].y;//分母
                if (x == 0 && y == 0) {
                    inSame++;
                    continue;
                }
                int gcd = helper(x, y);
                x /= gcd;
                y /= gcd;
                // 用string来存储斜率
                String slope = String.valueOf(x) + String.valueOf(y);
                int count = map.getOrDefault(slope, 0);
                count++;
                map.put(slope, count);
                xAxis = Math.max(xAxis, count);
            }
            res = Math.max(res, xAxis + inSame + 1);
        }
        return res;
    }
    public int helper(int x, int y) {//最大公约数函数，辗转相除法
        if (y == 0) return x;
        return helper(y, x % y);
    }
  }
```

##

##
