leetcode 149 Max Points on a Line

20200824更新

看了一下以前想的方法,时间复杂度O(n²),并没有想到优化的方式。

思路易想,细节难扣。

————————

给一堆点,找在同一条直线上最多的点数。

其实也不难,按照斜率来就是了。

100个点130ms左右,居然TLE了。

只好找找看有没有别的更好的办法。

有人提出用霍夫变换做,看起来确实是一个好办法。

霍夫变换的基本是,过某一个点的直线可以表示成 y = kx + b,那么把k和b当做参数的空间里,过这个点的所有直线在k-b空间中就是一条直线。过第二个点的所有直线在k-b空间也是一条直线,这两条直线的交点值k,b就是这两个点连线的参数k,b。

所以把所有n个点转换到霍夫空间,就是n条直线;找这n条直线的交点中有最多直线相交的交点,就是我们要找的过最多个点的直线参数k,b。

但是因为y=kx+b不能表示垂直的直线,所以一般用p=x*cos(theta)+y*sin(theta)也就是弧度空间来计算。

这样看来,这n个点变成了p,theta空间的n对参数,目的是要找这n条直线的交点中包含最多直线的交点。

也就是,x1*cos(theta)+y1*sin(theta)  = x2*cos(theta)+y2*sin(theta),已知x1,y1,x2,y2,求theta。

可是theta不好求。所以有人想出枚举的办法:

 

#define computeRho( pt, T ) ( ( pt.x * cos( T ) ) + ( pt.y * sin( T ) ) ) 

class Solution {
public:
    int maxPoints(vector<Point> &points) {
        if ( points.size() <= 2 ) {
            return points.size();
        }
        int max_points = 0;
        for ( int i = 0; i < 180; i++ ) {
            double theta = double( i ) / 180.0 * 3.141592657;
            map<int,int> accumulator;
            for ( int j = 0; j < points.size(); j++ ) {
                int rho = round( computeRho( points[j], theta ) );
                accumulator[ rho ]++;
                if ( accumulator[ rho ] > max_points ) {
                    max_points = accumulator[ rho ];
                }
            }
        }
        return max_points;
    }
};

 

 

 

这样时间复杂度就是O(180N)。

但是测试花的时间比我的还多。。

 

hash_map在leetcode居然不能用!

这道题真折腾人,相同的点要重复计算。。 最后还是按照测试数据量身定制了一个方法,钻空子了又。。

 

 

int findMax(vector<Point> &points)
{
	if ( points.size() <= 2 ) {
            return points.size();
    }
	int i,j,k;
	int result = 0;
	float fmax = 4294967295.0f;


	for (i = 0; i < points.size();i++)
	{
		int samecount = 0, flag = 0;
		unordered_map<float,int> line;
		for (j = i+1; j < points.size();j++)
		{
			float g,tmp;
			int xv = points[i].x - points[j].x;
			int yv = points[i].y - points[j].y;

			//same points
			if(xv == 0 && yv == 0){samecount++; continue;}

			//perpendicular with x axis
			if(xv == 0)
			{
				g = fmax;
			}
			else if(yv == 0)//parallel with x axis
			{
				g = 0;
			}
			else
			{
				g = (float)yv / (float)xv;
			}
			
			if(line[g] == NULL){
				line[g] = 2;
			}
			else{
				line[g]++;
			}
			if(line[g] > result){ result = line[g]; flag = 1;}
		}
		if(flag) result += samecount;
		else if(samecount > result) result = samecount + 1;
	}

	return result;
}

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值