leetcode 149. 直线上最多的点数(枚举)

leetcode149. 直线上最多的点数(困难)


题目描述

题目链接:leetcode 149. 直线上最多的点数
给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
示例 1:
在这里插入图片描述

输入:points = [[1,1],[2,2],[3,3]]
输出:3

示例 2:
在这里插入图片描述

输入:points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出:4

提示:

1 <= points.length <= 300
points[i].length == 2
- 1 0 4 10^4 104 <= xi, yi <= 1 0 4 10^4 104
points 中的所有点 互不相同

解题思路

思路:
两点确定一条直线,枚举所有两个点的组合就可以得到所有可能出现的直线。在确定一条直线后,再枚举这两个点以外的其它点,判断有几个点落在该直线上
实现细节:
1.已知两个点( x 1 x_{1} x1, y 1 y_1 y1)和( x 2 x_{2} x2, y 2 y_2 y2)所在直线,判断点( x 3 x_{3} x3, y 3 y_3 y3)是否在该直线上只需判断 y 3 − y 1 x 3 − x 1 \frac{y_3-y_1}{x_3-x_1} x3x1y3y1 y 2 − y 1 x 2 − x 1 \frac{y_2-y_1}{x_2-x_1} x2x1y2y1是否相等即可
2.为防止上述公式的分母出现为0的特殊情况,可以排除所有铅直线的情况。为了减少后续枚举数,可进一步排除水平线的情况。实现:先遍历一下所有点并将横坐标x(或纵坐标y)放入HashMap中统计个数,x(或y)的个数即为该铅直线(或水平线)上点的个数。后续的枚举只需枚举非水平和非铅直的情况即可。
3.判断两个浮点数x、y是否相等:(x-y)<eps (定义eps时要确保精度)。

Java代码

class Point{
    double x ;
    double y ;
    public Point(int x ,int y){
        this.x = (double)x;
        this.y = (double)y;
    }
}
public class Solution{
	    final double eps = 0.00000001;//精度
		 //判断两个浮点数是否相等
	    public Boolean isEqual(double x, double y) {
	  	     return Math.abs(x-y)<eps;
	    }
	   //判断两个点所连直线是否水平 或铅直
	   public Boolean onParallel(Point a, Point b) {
	  	   if(isEqual(a.x, b.x) || isEqual(a.y, b.y)) return true;
	  	   else return false;
	   }
       //判断三个点是否在一条直线上
	   public Boolean isLine(Point a, Point b,Point c) {
		      return isEqual((b.y-a.y)/(b.x-a.x),(c.y-a.y)/(c.x-a.x));
	   }
         
	     public int maxPoints(int[][] points){
               int res = 1;   //记录答案
               HashMap<Integer, Integer>X = new HashMap<Integer, Integer>();
               HashMap<Integer, Integer>Y = new HashMap<Integer, Integer>();
           //求在同一条水平线或同一条铅直线上点的个数
               for(int []key : points)
               {
            	       if(!X.containsKey(key[0])) X.put(key[0], 1);
            	       else{
            	           int cnt = X.get(key[0]) +1;
            	           res = Math.max(res, cnt);
            	           X.put(key[0], cnt);
            	       }
            	       if(!Y.containsKey(key[1])) Y.put(key[1], 1);
            	       else{
            	           int cnt = Y.get(key[1]) +1;
            	           res = Math.max(res, cnt);
            	           Y.put(key[1], cnt);
            	       }
               }


            //先选取两个点,在看第三个点是否在连点所连直线上
               int n = points.length;
               for(int i = 0; i<n; i++)
               {
            	   for(int j=i+1;j<n;j++)
            	   {
            		
            		   Point a = new Point(points[i][0], points[i][1]);
            		   Point b = new Point(points[j][0], points[j][1]);
            		   if(onParallel(a, b)) continue;
            		   int cnt = 2;
            		   for(int k = 0;k<n;k++){
            			    if(k==i || k==j ) continue;
            			    Point c = new Point(points[k][0], points[k][1]);
                            if(onParallel(a, c) || onParallel(b, c) ) continue;
            			    if(isLine(a, b, c)) cnt++; 
            		   }
            		   res = Math.max(res, cnt);
            	   }
               }
               return res;
	       }	     
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值