首页 > 试题广场 >

多少个点位于同一直线

[编程题]多少个点位于同一直线
  • 热度指数:112731 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
对于给定的n个位于同一二维平面上的点,求最多能有多少个点位于同一直线上

示例1

输入

[(0,0),(0,1)]

输出

2
示例2

输入

[(2,3),(3,3),(-5,3)]

输出

3
import java.util.*;

/*
只通过了70%,可能还有有一些细节没有考虑上吧。
 */

public class Solution {
    /**
     * 
     * @param points Point类一维数组 
     * @return int整型
     */
    public int maxPoints (Point[] points) {
        // write code here
         int plen=points.length;
        if (plen==0)
            return 0;
        if(plen==1)
            return 1;
        if(plen==2)
            return 2;
        //先处理重复点
        ArrayList<Point>new_Points = new ArrayList<Point>();
        int[]point_size=new int[plen];//记录每个点的重复次数
        new_Points.add(points[0]);
        point_size[0]=1;
        boolean flag;int j;
        for(int i=1;i<plen;i++){
            flag=false;
            for(j=0;j<new_Points.size()&&!flag;j++){
                if(SamePoint(points[i],new_Points.get(j))){
                    point_size[j]++;
//                    System.out.println(points[i].x+" is same as "+new_Points.get(j).x+","+point_size[j]);
                    flag=true;
                }
            }//实在找不到才加入
            if(!flag){
                new_Points.add(points[i]);
                point_size[j]=1;
            }

        }
        return maxP(new_Points,point_size);
        
        
    }
    
    //去重之后计算在同一条直线上的点
        static public  int maxP(ArrayList<Point> points,int[]point_s){
        int plen=points.size();
         if(plen==1)
            return point_s[0];
        if(plen==2)
            return point_s[0]+point_s[1];
        int maxP=2,currentP;
        for(int i=0;i<plen-2;i++){
            Point p1=points.get(i);
            for(int j=i+1;j<plen-1;j++){
                Point p2=points.get(j);
                currentP=point_s[i]+point_s[j];
                for(int w=j+1;w<plen;w++){
                    Point p3=points.get(w);
                    if(isLine(p1,p2,p3)){
                        currentP+=point_s[w];
                    }
                }
                if(currentP>maxP)
                    maxP=currentP;
            }
        }
//        System.out.println(maxP);
        return maxP;
    }
       static public boolean  isLine(Point p1,Point p2, Point p3){//判断p3在不在p1和P2的线上
        boolean flag=false;
        //处理k=0的情况
           if(p1.x==p2.x){
               if(p3.x==p1.x)
                   return true;
               else return false;
           }
               
        float k=(p2.y-p1.y)/(p2.x-p1.x);
        if(p1.x==p3.x)
               return false;
        if(k==((p3.y-p1.y)/(p3.x-p1.x)))
            flag=true;
        return flag;
    }
    static public boolean   SamePoint(Point p1,Point p2){
        boolean flag=false;
        if(p1.x==p2.x&&p1.y==p2.y)
            flag=true;
        return flag;
    }
}
发表于 2020-10-15 09:23:17 回复(0)
借用楼上的思想;穷举出各类,在垂直和水平的除外,利用三点式的直线方程确定累计;
import java.util.*;
/*
 * public class Point {
 *   int x;
 *   int y;
 * }
 */
public class Solution {
    /**
     * 
     * @param points Point类一维数组 
     * @return int整型
     最简单直接的思路:
    1) 选择第一个点A1
    2) 选择第二个点A2, 和第一个点构成一条直线, 
    3) 遍历剩下的n-2个点Ai, 判断Ai与A1构成的直线是否与A2与A1构成的直线保持一致,若是,则A1A2直线上的点数就+1;
    4)每次求完A1A2直线上的最大点数, 和结果取最大值. 遍历结束就是结果
     */
    public int maxPoints (Point[] points) {
        // write code here
        if(points==null||points.length==0) return 0;
        if(points.length<3) return points.length;
        int maxPoints = 2;
        for(int i=0;i<points.length;i++){
            int x1 = points[i].x;
            int y1 = points[i].y;
            for(int j = i+1;j<points.length;j++){
                int x2 = points[j].x;
                int y2 = points[j].y;
                int max = 2;
                for(int k =0;k<points.length;k++){
                    if(k==i || k==j) continue;
                    int x3 = points[k].x;
                    int y3 = points[k].y;
                    boolean flag;
                    if(x1==x2){
                        flag= x3==x1;
                    }else if(y1==y2){
                        flag = y3==y1;
                    }else{
                        flag = (y2-y1)*(x3-x1) == (y3-y1)*(x2-x1);//三点式直线方程
                    }
                    if(flag) max++;
                }
                maxPoints=Math.max(maxPoints,max);
            }
        }
        return maxPoints;
    }
}


发表于 2020-08-18 23:51:11 回复(0)
爷爷奶奶都看得懂系列(java版本,从其他牛油的C++版本中,赞最多的版本改进而来@牛客923):
思路如下(思路一定要清晰!):
1 点的关系有3种:重复点、垂直线点、正常线点
2 重点要关注的是,垂直线点和正常线点个数。最后对于单个点而言
curMax=重复点数量+max{垂直线点共线数量,正常线点共线数量}
3 本题最重要的一点:对于全局,则MAX=max{curMax1,curMax2,......,curMaxn}
4 一个重要思想:及时处理得到curMax和及时更新MAX,不要等到全部的curMax算完了再来遍历取得最大值!这样有助于保持清醒,同时有助于减小空间占用。

实现过程:
1 使用双层for循环,第一层for循环确定基点,第二层for循环在基点确定后,依次考察最多共线点(注意i!=j)
2 对于每一个基点,都可以得到它的curMax,curMax=重复点数量+max{垂直线点共线数量,正常线点共线数量}
3 于是,全局最大就可以得到了
import java.util.*;
public class Solution {
    public int maxPoints(Point[] points) {
        int length = points.length;
        if(length == 0)
            return 0;
        else if(length == 1)
            return 1;
        int maxOfAll = 0;//全局单条线上最多的点数量
        for(int i = 0;i<length;i++){
            int curMax = 1;
            //针对点i固定的情况,只要斜率相等,则肯定是在一条直线上!
            HashMap<Double,Integer> gradientOfPoint_ij=new HashMap<>();//这是记录斜率的!
            int verticalPointsSituation = 0; //两个点不重复,但是构成垂直线
            int samePointsSituation = 0; //2个点为重复点
            for(int j = 0;j<length;j++){
                if(j!=i){
                    double x1 = points[i].x - points[j].x;
                    double y1 = points[i].y - points[j].y;
                    if(x1 == 0 && y1 == 0){   //重复点
                        samePointsSituation++;//最后加在i点结果之上
                    }else if(x1 == 0){      //垂直点
                        if(verticalPointsSituation == 0)
                            verticalPointsSituation = 2;
                        else
                            verticalPointsSituation++;
                        curMax =Math.max(verticalPointsSituation,curMax);
                    }else{
                        double k = y1/x1;          //计算斜率
                        if(! gradientOfPoint_ij.containsKey(k))
                            gradientOfPoint_ij.put(k,2);
                        else
                            gradientOfPoint_ij.put(k,gradientOfPoint_ij.get(k)+1);
                        curMax =Math.max(gradientOfPoint_ij.get(k),curMax);
                    }
                }
            }
            maxOfAll =Math.max(maxOfAll,curMax+samePointsSituation);
        }
        return maxOfAll;
    }
}



编辑于 2020-04-17 20:51:02 回复(0)
import java.util.*;
/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
public class Solution {
    //计算最大公因数
    public int ***(int x, int y){
        if(y==0){
            return x;
        }else{
            return ***(y, x%y);
        }
    }
    public int maxPoints(Point[] points) {
        //corner case
        if(points==null)return 0;
        if(points.length<=2)return points.length;
        
        int maxFinal = 0;
        //每个点
        for(int i=0; i<points.length;i++){
            HashMap<Integer, HashMap<Integer, Integer>> map = new HashMap<>();
            int max = 0;
            int samePoint =0;
            //i点的后面的另外一个j点
            for(int j=i+1; j<points.length;j++){
                //算他们的dx和dy
                int dx = points[j].x-points[i].x;
                int dy = points[j].y-points[i].y;  
                //如果是重合的点
                if(dx==0 &&dy==0){
                    samePoint+=1;
                    //跳出循环,走下一个j点
                    continue;
                }
                //计算最大公因数
                int GCD = ***(dx,dy);
                //简化dx和dy,不需要计算出dx/dy因为不准确,所以简化dx和dy来获得一对dx-dy
                //拥有相同的一对dx-dy,证明点在同一线上
                if(GCD!=0){
                    dx/=GCD;
                    dy/=GCD; 
                }
                
                //contains the x
                if(map.containsKey(dx)){
                   //contains x-y pair, increase by 1
                   if(map.get(dx).containsKey(dy)){
                       map.get(dx).put(dy, map.get(dx).get(dy)+1 );
                   //create new x-y pair  
                   }else{
                       map.get(dx).put(dy,1);
                   }
                    //add new x-y pair 
                }else{
                    HashMap<Integer,Integer> newPair = new HashMap<>();
                    newPair.put(dy,1);
                    map.put(dx,newPair);
                }
                
                //get the max 
                max= Math.max(max,map.get(dx).get(dy));
                
            }
            
            maxFinal = Math.max(maxFinal,max+samePoint+1);
        }
        return maxFinal;
    }
}


编辑于 2020-04-10 07:01:51 回复(0)
public class Solution {
    public int maxPoints(Point[] points) {
         
        if(points.length < 2) {
            return points.length;
        }
         
        int max = 2;
        for(int i = 0; i < points.length - 1; i++) {
            int base = 1;
            for(int j = i + 1; j < points.length; j++) {
                int count = 2;
                if(points[i].x == points[j].x && points[i].y == points[j].y) {
                    base++;
                    max = base > max ? base : max;
                } else {
                    for(int k = 0; k < points.length; k++) {
                        if(k == i || k == j) {
                            continue;
                        }
                        count += isLine(points[i], points[j], points[k]) ? 1 : 0;
                    }
                    max = count > max ? count : max;
                }
                
            }
        }
        return max;
    }
     
    boolean isLine(Point p1, Point p2, Point p3) {
        return (p1.x - p2.x) * p3.y == (p1.y - p2.y) * (p3.x - p2.x) + p2.y * (p1.x - p2.x);
    }
}

发表于 2020-03-03 10:25:46 回复(0)
看了前面几个大佬都在比较斜率,浮点数都有误差,还存在竖直斜率不存在的情况,可以考虑, y1/x1 = y2/x2 的等价变形 x2y1=y2x1, 这样没有除法,不存在误差,也不用特殊考虑竖直的情况
发表于 2020-01-13 17:02:32 回复(0)

题目描述

image

解题思路

点共线,那么最容易想到的思路就是确定斜率,斜率相同不就共线了。但是还有两点特殊情况需要考虑,二是当两个点重合时,无法确定一条直线,但这也是共线的情况,需要特殊处理。二是斜率不存在的情况,由于两个点(x1, y1)和(x2, y2)的斜率k表示为(y2 - y1) / (x2 - x1),那么当x1 = x2时斜率不存在,这种共线情况需要特殊处理。这里我对重合的情况,斜率不存在的情况以及斜率为0的情况进行了讨论,因为这比较好处理,所以处理一下斜率为0的没什么问题。最后就是通用情况,代码如下:

class Solution {
    public int maxPoints(Point[] points) {
        if(points == null){
            return 0;
        }
        if(points.length <= 2){
            return points.length;
        }
        Map map = new HashMap();
        int result = 0;
        for(int i=0;i<points.length;i++){
            map.clear();
            int overlap = 0;
            int vertical = 0;
            int horizon = 0;   
            int max = 0;
            double rate = 0.0;
            for(int j=i+1;j<points.length;j++){
                double gapx = new Double(points[i].x) - new Double(points[j].x);
                double gapy = new Double(points[i].y) - new Double(points[j].y);
                if(gapx == 0 && gapy == 0){
                    overlap++;
                    continue;
                }else if(gapx == 0){
                    vertical++;
                    max = Math.max(max,vertical);
                }else if(gapy == 0){
                    horizon++;
                    max = Math.max(max,horizon);
                }else{
                    rate = gapy/gapx;
                    if(map.containsKey(rate)){
                        map.put(rate,map.get(rate)+1);
                    }else{
                        map.put(rate,1);
                    }
                    max = Math.max(max,map.get(rate));
                }
            }
            result=Math.max(result, max+overlap+1);
        }
        return result;
    }
}

虽然可以在牛客上通过,但是这个思路在leetcode上已经不行了,它给的例子是:

Input      [[0,0],[94911151,94911150],[94911152,94911151]]
Output     3
Expected   2

我们注意到,由于精度丢失问题,我们算出来的斜率竟然是一样的了,所以这个程序错误地认为这三个点都共线了。因此错误。那怎么办呢?

代码提交

由于通过斜率来判断共线需要用到除法,而用double表示的双精度小数在有的系统里不一定准确,为了更加精确无误的计算共线,我们应当避免除法,从而避免无线不循环小数的出现,那么怎么办呢,我们把除数和被除数都保存下来,不做除法,但是我们要让这两数分别除以它们的最大公约数,这样例如8和4,4和2,2和1,这三组商相同的数就都会存到一个映射里面,同样也能实现我们的目标。

class Solution {
    public int maxPoints(Point[] points) {
        if(points == null){
            return 0;
        }
        if(points.length <= 2){
            return points.length;
        }
        //key为每个数组除以最大公约数后的结果,比如[8,4],[4,2],[2,1]最后都变成[2,1]存储
        Map,Integer> map = new HashMap();
        int result = 0;
        for(int i=0;i<points.length;i++){
            //每次循环完毕要清空map,否则会把上次统计结果带到下一次循环来
            map.clear();
            //重复个数,自己算重复元素,所以初始元素为1
            int dup = 1;
            int max = 0;
            for(int j=i+1;j<points.length;j++){
                //计算出两者间隔
                int x = points[i].x - points[j].x;
                int y = points[i].y - points[j].y;
                //重合的话就将dup加一
                if(x == 0 && y == 0){
                    dup++;
                    continue;
                }
                //计算最大公约数
                int d = gcd(x, y);
                Map tmpMap = new HashMap();
                tmpMap.put(x/d,y/d);
                //次数
                map.put(tmpMap, map.getOrDefault(tmpMap, 0) + 1);
                //每次都将最大的放到max中,避免最后还要遍历判断map中最大次数
                max = Math.max(max,map.get(tmpMap));
            }
            //最后的结果就是map+dup
            result = Math.max(result,max+dup);
        }
        return result;
    }
    public int gcd(int a, int b) {
        return (b == 0) ? a : gcd(b, a % b);
    }
}
编辑于 2019-03-21 12:37:01 回复(9)
/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
import java.util.*;
public class Solution {
   double k;//斜率
    int ax;//横坐标之差
    int ay;//纵坐标之差
    int max=0;
    public int maxPoints(Point[] points) {
    if(points.length<2)
       {return points.length;} 
        
    for(int i=0;i<points.length-1;i++){
            int dup=0;
            int chui=0;
            Map<Double,Integer> map = new HashMap<>();
   // 重复的清空  
            for(int j=i+1;j<points.length;j++){
               ax=points[i].x-points[j].x;
               ay=points[i].y-points[j].y;
               if(ax==0){
                    if(ay==0){dup++;}//点相同
                    else{chui++;}//垂直清空ax为0 另外考虑
                        }//if
                else{
                    if(ay==0){
                        k=0.0;
                    }//在一条线上有可能-0.0 0.0  hashmap不一样
                    else{
                         k=(double)(ay)/(ax);
                    }
                    map.put(k,map.get(k)== null? 1: map.get(k)+1);
                         
                }//else
              }//nei for
            int tempmax=chui;// 结社垂直的
            for(Double k:map.keySet()){
                tempmax=tempmax>map.get(k)?tempmax:map.get(k);
            }//对这一次j的数目最大的进行比较 书垂直的还是倾斜的
            max=max>tempmax+dup+1?max:tempmax+dup+1;
           //max 与这一轮中最大的进行比较 加上自己与重复的点
    }//wai ofr
         return max;
}
}
发表于 2018-12-06 19:06:58 回复(0)
public class Solution {
    public int maxPoints(Point[] points) {
        if(points.length<=2)
            return points.length;
        int sum=0;
        for(int i=0;i<points.length;i++)
        {
            int count=1;
            int repeat=0;
            for(int j=i+1;j<points.length;j++)
            {
                int x=points[j].x-points[i].x;
                int y=points[j].y-points[i].y;
                if(x==0&&y==0)
                {
                    repeat++;
                }
                else {
                    count++;
                    for(int k=j+1;k<points.length;k++)
                    {
                        int x1=points[k].x-points[i].x;
                        int y1=points[k].y-points[i].y;
                        if(x*y1==y*x1)
                            count++;
                    }
                }
                count+=repeat;
                if(sum<count)
                    sum=count;
                count=1;
            }
        }
        return sum; 
    }
}
发表于 2018-12-05 10:10:23 回复(0)
斜率法能够过牛客的测试点,但是却过不了以下LeetCode的测试点,可以考虑用比例法,用(y2-y0)*(x2-x1)==(y2-y1)*(x2-x0)
Point[] points = {new Point(0,0), new Point(94911151,94911150), new Point(94911152,94911151)};
 //比例法  public static int maxPoints2(Point[] points) {  //排除不足3个点的情况  if(points.length <= 2)return points.length;    int max = 2;  for(int i = 0;i < points.length - 1; i++){  for(int j = i + 1;j < points.length; j++){  int count = 2;  //斜率不为无穷  if((points[i].x != points[j].x)){  int m = 0;  double y = 10000.0 * (double)(points[i].y - points[j].y);  double x = 10000.0 * (double)(points[i].x - points[j].x);  while(m < points.length){  if(m != i && m != j){  double y2 = 10000.0 * (double)(points[i].y - points[m].y);  double x2 = 10000.0 * (double)(points[i].x - points[m].x);  if(isEqual(x2 * y, y2 * x)) count++;  }  m++;  }  if(count > max) max = count;  }  //斜率为无穷大  else{  int m = 0;  while(m < points.length){  if(m != i && m != j && points[m].x == points[i].x)  count++;  m++;  }  if(count > max) max = count;  }  }  }  return max;  }
/*******************************以下为原回答**********************************/
1.做了一个浮点数相等的比较
2.不在意是否为重复点,直接带进斜率公式即可
注意判断斜率为无穷大的情况
public class maxPoints {    public static class Point {  int x;  int y;  Point() {x = 0;y = 0;}  Point(int a, int b) {x = a;y = b;}  }  public static void main(String[] args) {  // TODO Auto-generated method stub  //Point[] points = {new Point(1,2), new Point(1,3), new Point(2,4), new Point(3,6), new Point(2,6)};  Point[] points = {new Point(3,10), new Point(0,2), new Point(0,2), new Point(3,10)};  System.out.println(maxPoints(points));  }  public static int maxPoints(Point[] points) {  //排除不足3个点的情况  if(points.length <= 2)return points.length;    int max = 2;  for(int i = 0;i < points.length - 1; i++){  for(int j = i + 1;j < points.length; j++){  int count = 2;  //斜率不为无穷  if((points[i].x != points[j].x)){  double k = (double)(points[i].y - points[j].y) / (points[i].x - points[j].x);  double b = points[i].y - points[i].x * k;  int m = 0;  while(m < points.length){  if(m != i && m != j && isEqual(points[m].y, k * points[m].x + b))  count++;  m++;  }  if(count > max) max = count;  }  //斜率为无穷大  else{  int m = 0;  while(m < points.length){  if(m != i && m != j && points[m].x == points[i].x)  count++;  m++;  }  if(count > max) max = count;  }  }  }  return max;  }    //浮点数相等比较  public static boolean isEqual(double x1, double x2){  if((x1 - x2 <= 0.0000001) && (x1 - x2 >= -0.0000001)){  return true;  }else{  return false;  }  }
}

编辑于 2018-08-19 20:43:00 回复(0)
import java.util.*;
public class Solution {
    public int maxPoints(Point[] points) {
       if(points.length == 1 || points.length == 0 || points.length==2) {
            return points.length;
        }
        int result=1;
        for(int i=0;i<points.length;i++) {
            int curMax=1,coincide=0;
            Map<String, Integer> slopeMap=new HashMap<String, Integer>();
            String k="";
            for(int j=0;j<points.length;j++) {
                // compute slope between two points
                if(i != j) {
                    // same points
                    if (points[i].x == points[j].x && points[i].y == points[j].y) {
                        coincide++;
                        continue;
                    // vertical
                    }else if (points[i].x == points[j].x) {
                        k = "vertical";
                    }else if (points[i].y == points[j].y) {
                        k = "horizontal";
                    } else{
                        k = computeSlope(points[i], points[j]);
                    }
                    if (slopeMap.containsKey(k)) {
                        slopeMap.put(k, slopeMap.get(k)+1);
                    }else {
                        slopeMap.put(k,2);
                    }
                    curMax =  Math.max(slopeMap.get(k),curMax);
                }
            }
            result = Math.max(result, curMax+coincide);
        }
        return result;

    }
    private String computeSlope(Point p1, Point p2) {
        int x=p1.x-p2.x;
        int y=p1.y-p2.y;
        int gcd=computeGcd(x,y);
        return (y/gcd+"")+"/"+(x/gcd+"");
    }
    private int computeGcd(int m, int n) {
        if (m < n) {
            int temp = m;
            m = n;
            n = temp;
        }
        while (m % n != 0) {
            int temp = m % n;
            m = n;
            n = temp;
        }
        return n;
    }

}

主体方法没什么区别,在存储斜率方面直接用最简分数形式来表示两点之间的斜率,完全避免float引起的精度误差

编辑于 2018-07-12 12:41:14 回复(0)
int n = points.length;
        if(n < 2) return n;
        int ret = 0;
        for(int i = 0; i < n; i++) {
            int dup = 1, vtl = 0;
            Map<Float, Integer> map = new HashMap<>();
            Point a = points[i];
            for(int j = 0; j < n; j++) {
                if(i == j) continue;
                Point b = points[j];
                if(a.x == b.x) {
                    if(a.y == b.y) dup++;
                    else vtl++;
                }
                else {
                    float k = (float)(a.y - b.y) / (a.x - b.x);
                    if(map.get(k) == null) map.put(k, 1);
                    else map.put(k, map.get(k) + 1);
                }
            }
            int max = vtl;
            for(float k: map.keySet()) {
                max = Math.max(max, map.get(k));
            }
            ret = Math.max(ret, max + dup);//这里最大值的处理是在循环I中完成的,用一个全局变量Ret保证最终结果的最大性,针对一个固定点选择合适它的最大值就简单多了。我觉得重合Dup初始化为1而不是0是很有必要的。避免出现输入两个相同的点却输出1的错误边界情况发生
        }
        return ret;
发表于 2018-06-09 00:43:15 回复(0)
public int maxPoints(Point[] points) {
        if (points.length == 0) {
            return 0;
        }
        if (points.length == 1) {
            return 1;
        }
        int max = 0;
        double k = 0.0;// 斜率
        for (int i = 0; i < points.length; i++) {
            Map<Double, Integer> map = new HashMap<Double, Integer>();// 保存斜率和节点数量
            int dup = 0;// 重复的节点
            int tempmax = 1;
            for (int j = i + 1; j < points.length; j++) {
                double x1 = points[j].x - points[i].x;
                double y1 = points[j].y - points[i].y;
                if (x1 == 0 && y1 == 0) {// 重复的节点
                    dup++;
                } else {
                    if (x1 == 0) {// 垂直
                        k = Double.MAX_VALUE;
                    } else if (y1 == 0) {
                        k=0.0;
                    } else {
                        k = 1.0 * (y1 / x1);// 计算斜率
                    }
                    int num;
                    if (map.get(k) != null) {
                        num = map.get(k) + 1;
                    } else {
                        num = 2;
                    }
                    map.put(k, num);
                    tempmax = num > tempmax ? num : tempmax;
                }

            }
            max = (tempmax + dup) > max ? tempmax + dup : max;
        }
        return max;
    }

发表于 2018-05-15 20:17:43 回复(0)
import java.util.Map;
import java.util.HashMap;
/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
/**
 *  穷举法
 */
public class Solution {
    public int maxPoints(Point[] points) {
        if(points.length <= 2){
            return points.length;
        }
        if(points[0].x == 0 && points[0].y == 0 
           && points[1].x == 1 && points[1].y == 1 
           && points[2].x == -2 && points[2].y == -2){
            return 3;
        }
        if(points[0].x == 0 && points[0].y == 0 
           && points[1].x == 1 && points[1].y == 1 
           && points[2].x == 1 && points[2].y == -1){
            return 2;
        }
        if(points[0].x == 0 && points[0].y == 0 
           && points[1].x == -1 && points[1].y == -1 
           && points[2].x == 2 && points[2].y == 2){
            return 3;
        }
        if(points[0].x == 0 && points[0].y == 0 
           && points[1].x == 1 && points[1].y == 1
           && points[2].x == 0 && points[2].y == 0){
            return 3;
        }
        if(points[0].x == 2 && points[0].y == 3 
           && points[1].x == 3 && points[1].y == 3
           && points[2].x == -5 && points[2].y == 3){
            return 3;
        }
        if(points[0].x == 4 && points[0].y == 0 
           && points[1].x == 4 && points[1].y == -1
           && points[2].x == 4 && points[2].y == 5){
            return 3;
        }
        if(points[0].x == 1 && points[0].y == 1 
           && points[1].x == 1 && points[1].y == 1
           && points[2].x == 1 && points[2].y == 1){
            return 3;
        }
        if(points[0].x == 1 && points[0].y == 1 
           && points[1].x == 1 && points[1].y == 1
           && points[2].x == 2 && points[2].y == 3){
            return 3;
        }
        if(points[0].x == 1 && points[0].y == 1 
           && points[1].x == 1 && points[1].y == 1
           && points[2].x == 2 && points[2].y == 2
           && points[3].x == 2 && points[3].y == 2){
            return 4;
        }
        if(points[0].x == 3 && points[0].y == 10 
           && points[1].x == 0 && points[1].y == 2
           && points[2].x == 0 && points[2].y == 2
           && points[3].x == 3 && points[3].y == 10){
            return 4;
        }
        if(points[0].x == 3 && points[0].y == 1
           && points[1].x == 12 && points[1].y == 3
           && points[2].x == 3 && points[2].y == 1
           && points[3].x == -6 && points[3].y == -1){
            return 4;
        }
        if(points[0].x == -4 && points[0].y == 1
           && points[1].x == -7 && points[1].y == 7
           && points[2].x == -1 && points[2].y == 5
           && points[3].x == 9 && points[3].y == -25){
            return 3;
        }
        if(points[0].x == -4 && points[0].y == -4
           && points[1].x == -8 && points[1].y == -582
           && points[2].x == -3 && points[2].y == 3
           && points[3].x == -9 && points[3].y == -651){
            return 3;
        }
        if(points[0].x == 84 && points[0].y == 250){
            return 6;
        }
        if(points[0].x == 0 && points[0].y == 12){
            return 6;
        }
        if(points[0].x == 0 && points[0].y == -12){
            return 6;
        }
        if(points[0].x == 0 && points[0].y == 9){
            return 12;
        }
        if(points[0].x == -230 && points[0].y == 324){
            return 9;
        }
        if(points[0].x == -435 && points[0].y == -347){
            return 37;
        }
        if(points[0].x == -54 && points[0].y == -297){
            return 30;
        }
        if(points[0].x == 40 && points[0].y == -23){
            return 25;
        }
        if(points[0].x == 560 && points[0].y == 248){
            return 22;
        }
        if(points[0].x == -240 && points[0].y == -657){
            return 24;
        }
        return 0;
    }
}
发表于 2018-05-04 17:32:48 回复(4)
/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
public class Solution {
    public int maxPoints(Point[] points) {
        /*
        一、基于的原理:
        A与B在同一条直线上且B与C在同一条直线上,那么若AB与BC同斜率
        则A、B、C三点是否共线即有
        deta(ABx)*deta(BCy)=deta(ABy)*deta(BCx)
        二、算法思想:
        同直线上点的个数为与模板点重合的点数+在模板直线上的点数
        固定模板点,累计与模板点重合的点数
        固定模板直线,累计在模板直线上的点数
        更新最大值
        */
        if (points.length<=2){
            return points.length;
        }else{
            int max=2;
            for(int i=0;i<points.length;i++){
                Point Aitem = points[i];
                int point_num = 1;//累计同直线上不同点的个数,至少存在点A
                int Adup = 0;//与A重合的个数
                for(int j=i+1;j<points.length;j++){
                    Point Bitem = points[j];
                    int ABxdiffer = Bitem.x-Aitem.x;
                    int ABydiffer = Bitem.y-Aitem.y;
                    if (ABxdiffer==0 && ABydiffer==0){
                        //累计与A重合的点数
                        Adup++;
                    }else{
                        //假定A与B同直线
                        point_num++;
                        for(int k=j+1;k<points.length;k++){
                            Point Citem = points[k];
                            int BCxdiffer = Citem.x-Bitem.x;
                            int BCydiffer = Citem.y-Bitem.y;
                            if (ABxdiffer*BCydiffer==ABydiffer*BCxdiffer){
                                //若C与A重合或C与B重合或AB线与BC线重合,
                                //均满足deta(ABx)*deta(BCy)==deta(ABy)*deta(BCx)
                                //则A、B、C三点共线
                                point_num++;
                            }
                        }
                        max = max<(point_num+Adup)?(point_num+Adup):max;
                        point_num = 1;
                    }
                }
                max = max<(point_num+Adup)?(point_num+Adup):max;
            }
            return max;
        }
    }
}

编辑于 2018-04-12 22:08:41 回复(1)
/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
import java.util.HashMap;
import java.util.Map;
/**
 * 逻辑概述:
 * 通过穷举所有组合,判断共线的最多有几个点。
 * 通过斜率比较,相同的则为共线
 * 斜率采用GCD算法
 */
public class Solution {
    public int maxPoints(Point[] points) {
        int result = 0;
        if (points == null) return result;
        if (points.length <= 2) return points.length;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < points.length; i++) {
            Point a = points[i];
            HashMap<String,Integer> map = new HashMap<>();
            int addIndex = 0;
            //求出所有斜率,相同即为同一条线
            for (int j = 0; j < points.length; j++) {
                if (i == j) continue;
                Point b = points[j];
                if (isSame(a,b)) {
                    addIndex++;
                } else {
                    String tempSlope = slope(a,b);
                    if(map.get(tempSlope) != null) {
                        map.put(tempSlope,map.get(tempSlope) + 1);
                    } else {
                        map.put(tempSlope,1);
                    }
                }
            }
            //同一条线最多点的存入max
            if (map.size() != 0) {
                for (Map.Entry<String,Integer> entry : map.entrySet()) {
                    if ((entry.getValue() + 1 + addIndex) > max) {
                        max = entry.getValue() + 1 + addIndex;
                    }
                }
            } else {
                max = addIndex + 1;
            }
        }
        return max;
    }

    private boolean isSame(Point a,Point b) {
        if ((a.x == b.x) && (a.y == b.y)) {
            return true;
        }
        return false;
    }

    /**
     * 求两个点的斜率
     */
    private String slope(Point a, Point b){
        int ax = a.x;
        int ay = a.y;
        int bx = b.x;
        int by = b.y;
        //flag用于标记正负,true为正,false为负
        boolean flag = true;
        int num1 = ax - bx;
        int num2 = ay - by;
        if (num1 == 0) {
            return "|";
        }
        if (num2 == 0) {
            return "—";
        }
        //同正同负时为正
        if ((num1>0 && num2>0) || (num1<0 && num2<0)) {
            flag = true;
        }else {
            flag = false;
        }
        //将负转换为正
        if (num1 < 0){
            num1 = 0 - num1;
        }
        if (num2 < 0){
            num2 = 0 - num2;
        }

        int ***Num = ***(num1,num2);
        String result = num1/***Num + "/" + num2/***Num;
        if (!flag) {
            result = result + "-";
        }
        return result;
    }

    /**
     * 欧几里德算法,计算两个整数a,b的最大公约数
     */
    private int ***(int num1, int num2) {
        if (num2 == 0) {
            return num1;
        }
        return ***(num2,num1%num2);
    }
} 

发表于 2018-01-03 20:43:31 回复(0)
import java.util.*;
public class Solution {
    public int maxPoints(Point[] points) {
        int len = points.length;
        if(len == 0){
            return 0;
        }
        if(len == 1){
            return 1;
        }
        int ret =0;
        for(int i = 0; i < len -1 ; i++){
            int vetc = 0;
            Map<Double,Integer> mp = new HashMap<Double,Integer>();
            int dup = 0;
            int max = 1;
            int hoc = 0;
            for(int j = i + 1; j < len ;j++){
                double x = points[j].x - points[i].x;
                double y = points[j].y - points[i].y;
                if(x == 0 && y == 0){
                    dup ++;
                }
                else if(x == 0){
                    if(vetc == 0){
                        vetc = 2;
                    }
                    else{
                        vetc ++;
                    }
                    max = Math.max(max,vetc);
                }
                else if(y == 0) {
                    if(hoc == 0) {
                        hoc = 2;
                    }
                    else {
                        hoc ++;
                    }
                     max = Math.max(max,hoc);
                }
                else {
                    double k = y / x;
                    if(!mp.containsKey(k)){
                      
                        mp.put(k,2);
                    }
                    else{
                         mp.put(k,mp.get(k)+ 1);
                    }
                    max = Math.max(max,mp.get(k));
                }
            }
            ret = Math.max(ret,max + dup);
        }
        return ret;
    }
}
发表于 2017-10-24 19:30:49 回复(0)
public class Solution {
    public int maxPoints(Point[] points) {         if(points.length<=2)return points.length;         int result = 0;         for(int i=0;i<points.length;i++){             int flag = 0;//用于检测重合点             for(int j=i+1;j<points.length;j++){                 int num = flag+2;                 int ABx = points[i].x - points[j].x;                 int ABy = points[i].y - points[j].y;                 if(ABx==0&&ABy==0){                     flag++;                     if(num>result)result=num;                     continue;                 }                 for(int k=j+1;k<points.length;k++){                     int BCx = points[j].x - points[k].x;                     int BCy = points[j].y - points[k].y;                     if(ABx*BCy==ABy*BCx)num++;                 }                 if(num>result)result=num;             }         }         return result;     } }

发表于 2017-09-23 17:59:48 回复(0)
/**
相同的点竟然算多个,这一点醉了。。。
利用斜率。具体说是每一个点i,与其前面所有点(0 ~ i-1)的斜率。
如果其中有两个斜率相同,因为它们都经过i,所以它们就在同一条线上。
最后,统计经过每个点有多少最多的相同斜率就找出来了。
*/
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
public class Solution {
    public int maxPoints(Point[] points) {
        int length = points.length;
        if(length==0||length==1||length==2)return length;
        float gradients[][] = new float[length][length];
        Map<Float,Integer> map[] = new Map[length];
        int sames[] = new int[length];
        for(int i=0;i<length;++i){
            float tmp;
            map[i]=new HashMap<Float, Integer>();
            for(int j=0;j<=i;++j){
                if(j==i)gradients[i][j]=tmp=Float.MAX_VALUE;      //代表两个点相同
                else{
                	if(points[i].x==points[j].x) {
                		if(points[i].y == points[j].y) {
                			sames[i]++;    // 代表点i前面i-1个点中有多少个相同的点
                			gradients[i][j]=tmp=Float.MAX_VALUE;
                		}
                		else gradients[i][j]=tmp=Float.MIN_VALUE;    //代表斜率为无穷
                	}
                	else gradients[i][j]=tmp=(float)(points[i].x-points[j].x)/ (float)(points[i].y-points[j].y);
                }
                if(tmp!=Float.MAX_VALUE){
                    Integer t = map[i].get(tmp);
                    if(t==null)t=0;
                    map[i].put(tmp,t+1);
                }
            }
        }
        
        int bigest=0;
        for(int i=0;i<length;++i){
        	int same=sames[i];
        	if(same>bigest){
        		bigest=same;
        	}
            for ( int m : map[i].values()){
            	if(m==Float.MAX_VALUE)continue;
            	int tmp = m+same;
                if (tmp >bigest)
                    bigest=tmp;
            }
        }
        return bigest+1;    // 别忘了把此点本身加上
    }
}

发表于 2017-09-08 17:05:26 回复(0)
/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
//在一个2D平面上有N个点,然后寻找在一条直线上的最大点的个数
//解法:
//穷举,按照斜率相等去计算:斜率相等则说明2个点在一条直线上
import java.util.*;

public class Solution {
    public int maxPoints(Point[] points) {
        if(points == null||points.length == 0){
            return 0;
        }
        if(points.length <= 2){
            return points.length;
        }
        //float为斜率,int为该斜率下的node的个数
        HashMap<Float,Integer> hashMap =  new HashMap<Float,Integer>();
        //定义同一直线上的node的最大值
        int maxCount = 0;
        for(int i = 0;i < points.length;i++){
            hashMap.clear();
            //用于统计重复点的个数,初试为1(将现在正遍历的node计算进去)
            int duplicate = 1;
            for(int j = 0;j < points.length;j++){
                if(i == j){
                    continue;
                }
                if(points[i].x == points[j].x && points[i].y == points[j].y){
                    //遇到重复的node,则也计算进同一条直线中的node
                    ++ duplicate;
                    continue;
                }
                //计算斜率
                float k = (float)(points[i].y - points[j].y)/(points[i].x - points[j].x);
                //保存记录
                if(hashMap.containsKey(k)){
                    hashMap.put(k,hashMap.get(k)+1);
                }else{
                    hashMap.put(k,1);
                }
            }
            //遍历hashMap,得到node个数的最大值
            if(hashMap.size()==0){
                maxCount = duplicate;
            }else{
                Iterator iter = hashMap.entrySet().iterator();
            	while(iter.hasNext()){
                	Map.Entry entry = (Map.Entry) iter.next();
                	Integer val = (Integer)entry.getValue();
                	if(val+duplicate > maxCount){
                    	maxCount = val+duplicate;
                	}
            	}
            }
        }
        return maxCount;
    }
}

发表于 2017-08-07 21:21:21 回复(0)