Bootstrap

【力扣149. 直线上最多的点数】


题目: 149. 直线上最多的点数

解题思路

暴力解法:
枚举两个点构成的直线中,其余点在该直线上的个数,返回个数最大的情况
判断点p是否在由startend构成的直线上:

  • p分别与startend点的斜率是否相等
    p [ 1 ] − s t a r t [ 1 ] p [ 0 ] − s t a r t [ 0 ] = p [ 1 ] − e n d [ 1 ] p [ 0 ] − e n d [ 0 ] \frac {p[1]-start[1]} {p[0]-start[0]}=\frac {p[1]-end[1]} {p[0]-end[0]} p[0]start[0]p[1]start[1]=p[0]end[0]p[1]end[1]
  • 为了防止除数为0的情况,可以将上述公式转换为:
    ( p [ 1 ] − s t a r t [ 1 ] ) ∗ ( p [ 0 ] − e n d [ 0 ] ) = ( p [ 1 ] − e n d [ 1 ] ) ∗ ( p [ 0 ] − s t a r t [ 0 ] ) ) (p[1]-start[1])*(p[0]-end[0])=(p[1]-end[1])*(p[0]-start[0])) (p[1]start[1])(p[0]end[0])=(p[1]end[1])(p[0]start[0]))

具体操作

  1. 一条直线可由两个点决定(startend)
  2. ans记录最终答案,初始化为1 (至少有一个点在穿过它的直线上)
  3. 逐次选择startend
    1. same为余下所有点中,在该直线上的点的个数,初始化为2 (startend已经在该直线上)
    2. 逐次选择剩下的点,这里记为点p
      1. 如果点p在该直线上,则same++
      2. 否则,选下一个点
    3. startend的情况遍历完毕,得到same
  4. ans选取目前为止最大的same
  5. 继续循环或返回结果

代码

class Solution {
    public int maxPoints(int[][] ps) {
        int ans = 1;
        for(int i=0; i<ps.length; i++){
            for(int j=i+1; j<ps.length; j++){
                int same = 2;
                for(int k=j+1; k<ps.length; k++){
                    // start:第一个选择的点
                    int[] start = ps[i];
                    // end:第二个选择的点
                    int[] end = ps[j];
                    // p: 判断是否在start与end所在线上的点
                    int[] p = ps[k];

                    // p与start的斜率 与 p与end的斜率 如果相同,则在一条线上
                    /*
                        (p[1]-start[1]) / (p[0]-start[0]) = (p[1]-end[1]) / (p[0]-end[0]) 
                        为了防止除数为0的情况,可转化为
                        (p[1] - start[1]) * (p[0] - end[0]) = (p[1] - end[1]) * (p[0] - start[0])
                     */
                    int s1 = (p[1] - start[1]) * (p[0] - end[0]);
                    int s2 = (p[1] - end[1]) * (p[0] - start[0]);
                    if(s1 == s2) same++;
                }
                ans = Math.max(same,ans);
            }
        }
        return ans;
    }
}

;