Leetcode149. Max Points on a Line

题目:

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

Example 1:

Input: [[1,1],[2,2],[3,3]]
Output: 3
Explanation:
^
|
|        o
|     o
|  o  
+------------->
0  1  2  3  4

Example 2:

Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
Explanation:
^
|
|  o
|     o        o
|        o
|  o        o
+------------------->
0  1  2  3  4  5  6

题目分析:给出二维平面上几个点坐标,求最多有几点共线。

方法一、

看了题目第一反应就是用斜率,固定一个点,求其余各点与该点组成的线的斜率。偷瞄了一眼这道题目的标签发现是hash,因此就考虑将斜率作为key,与这一点组成的线的斜率是key的点数为value(包含固定点),用这个hash表来快速统计结果。

然而由于存在与y轴平行的线,考虑用INT_MAX表示斜率。

在提交过程中发现了坑:

1、给出的点存在重复情况,重复的点也算作共线,因此还要统计重复情况。

2.

在提交中发现这样的错误,研究发现这个实例的斜率由于double的精度不够而错把这三个点看作同线。由于通过斜率来判断共线除法不可避免,因此必须使用别的方法。方法在后面介绍。

虽然没能通过这个实例,这里仍然给出这种方法的代码:

/**
 * Definition for a point.
 * struct Point {
 *     int x;
 *     int y;
 *     Point() : x(0), y(0) {}
 *     Point(int a, int b) : x(a), y(b) {}
 * };
 */
class Solution {
public:
    int maxPoints(vector<Point>& points) {
        int n=points.size();
	if(n==0) return 0;
	if(n==1) return 1;
	if(n==2) return 2;

	int max=0;
	for(int i=0;i<n-1;i++){
	    int imax=1;
	    map<float, int> hash_table;
	    int samepoint=0;
	    for(int j=i+1;j<n;j++){
		if(points[j].x==points[i].x&&points[j].y==points[i].y) {
                    samepoint++;
                    continue;}
	        float k=0;
	        if(points[j].x-points[i].x!=0) k=float(points[j].y-points[i].y)/(points[j].x-points[i].x);
	        else k=INT_MAX;
	        if(hash_table[k]==0) 
	            hash_table[k]=2;
	        else hash_table[k]++;
	        if(imax<hash_table[k]) imax=hash_table[k];
	    }
	    if(max<imax+samepoint) max=imax+samepoint;
	}
	
	return max;
    }
};

方法二、

在斜率行不通的情况下我又看了大神们的解答,发现了利用最大公约数的方法。

把横纵坐标的值保存下来,不做除法,为了统一,我们把这两数分别除以它们的最大公约数,这样斜率相同的数就都会存到一个映射里面。

例如:[2,1],[4,2],[8,4]

4、2的最大公约数是2,8、4的最大公约数是4,对应的整数对都是2、1。

代码如下:

/**
 * Definition for a point.
 * struct Point {
 *     int x;
 *     int y;
 *     Point() : x(0), y(0) {}
 *     Point(int a, int b) : x(a), y(b) {}
 * };
 */
class Solution {
public:
    int gcd(int x, int y) {
        return (y == 0) ? x : gcd(y, x % y);}
    int maxPoints(vector<Point>& points) {
        int n=points.size();
	if(n==0) return 0;
	if(n==1) return 1;
	if(n==2) return 2;

	int max=0;
	for(int i=0;i<n-1;i++){
		int imax=1;
		map<pair<int,int>, int> hash_table;
		int samepoint=0;int dx,dy;pair<int,int> k;
		for(int j=i+1;j<n;j++){
			if(points[j].x==points[i].x&&points[j].y==points[i].y) {
				samepoint++;continue;}
			
				dx = points[j].x - points[i].x;
                dy = points[j].y - points[i].y;
                int d = gcd(dx, dy);
				k.first=dx/d;
				k.second=dy/d;
			if(hash_table[k]==0) 
				hash_table[k]=2;
			else hash_table[k]++;
			if(imax<hash_table[k]) imax=hash_table[k];
		}
		if(max<imax+samepoint) max=imax+samepoint;
	}
	
	return max;
    }
};

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值