Max Points on a Line(leetcode)

题目:

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

题目来源:https://oj.leetcode.com/problems/max-points-on-a-line/

解题思路:由两点计算出斜率,然后根据斜率和初始点计算任意一点是否在这两点所确定的直线上,如果在就把计数器+1,返回最多的点的直线上的点数。

注意:如果第一个点是[1,3],第5个点也是[1,3],则在第5个点往后的点,以[1,3]为起点计算时,都需要加两遍[1,3],这个地方要特别注意。但是leetcode题解上避免了这个问题,可以从代码上看出来,如果点M和点N的x轴坐标相等,则只计算和x轴其坐标相等的点,否则利用公式计算。这样就把两个相等的点放到了第一种情况。

#include<iostream>
#include<vector>
using namespace std;

struct Point 
{
    int x;
    int y;
    Point() : x(0), y(0) {}
    Point(int a, int b) : x(a), y(b) {}
};

int maxPoints(vector<Point> &points)
{
	if(points.size()<=1)
		return points.size();
	const int N=points.size();
	int result=0,temp=1;
	for(int i=0;i<N;i++)
	{	
		temp=1;
		int firstNum=temp;
		for(int j=i+1;j<N;j++)
		{
			if(points[j].x==points[i].x && points[j].y==points[i].y)
			{
				temp++;
				//表示到目前为止第一个数即points[i]重复出现的次数,因为每次重复相当于每条线都有加一个点
				firstNum++;
				continue;
			}
			temp++;
			double k=(points[j].x-points[i].x)==0?0:double(points[j].y-points[i].y)/(points[j].x-points[i].x);
			for(int m=j+1;m<N;m++)
			{
				double tempk=(points[m].x-points[i].x)==0?0:double(points[m].y-points[i].y)/(points[m].x-points[i].x);
				if(k==tempk || (points[m].x==points[i].x && points[m].y==points[i].y) || (points[m].x==points[j].x && points[m].y==points[j].y))
					temp++;
			}
			if(temp>result)
				result=temp;
			temp=firstNum;
		}
		if(temp>result)
				result=temp;
	}
	return result;
}


int maxPoints1(vector<Point> &points)
{
	if(points.empty())
		return 0;
	const int N=points.size();
	int temp=0;
	int result=0;
	for(int i=0;i<N;i++)
	{
		temp=1;
		int firstNum=temp;
		for(int j=i+1;j<N;j++)
		{
			int A=points[i].x-points[j].x;
			int B=points[i].y-points[j].y;
			if(A==0 && B==0)
			{
				temp++;
				firstNum++;
				continue;
			}
			temp++;
			for(int m=j+1;m<N;m++)
			{
				if((A==0 && points[m].x==points[i].x) || (points[m].y-points[i].y)*A==B*(points[m].x-points[i].x))
					temp++;
			}
			result=max(result,temp);
			temp=firstNum;
		}
		result=max(result,temp);
	}
	return result;
}

int maxPoints2(vector<Point> &points)
{
	if(points.size()<3)
		return points.size();
	int result=0;
	for(int i=0;i<points.size()-1;i++)
	{
		for(int j=i+1;j<points.size();j++)
		{
			int sign=0;
			int a,b,c;
			if(points[i].x==points[j].x)
				sign=1;
			else
			{
				a=points[j].x-points[i].x;
				b=points[j].y-points[i].y;
				c=a*points[i].y-b*points[i].x;
			}
			int count=0;
			for(int k=0;k<points.size();k++)
			{
				//这里巧妙的避免了上面所出现的问题及firstNum的问题
				if((0==sign && a*points[k].y==c+b*points[k].x) || (1==sign && points[k].x==points[j].x))
					count++;
			}
			if(count>result)
				result=count;
		}
	}
	return result;
}

int main()  
{  
	freopen("input.txt","r",stdin);
	vector<Point> points;
	int x,y;
	while(cin>>x>>y)
	{
		points.push_back(Point(x,y));
	}

	int result=maxPoints(points);
	int result1=maxPoints1(points);
	int result2=maxPoints2(points);

    system("pause");  
    return 0;  
}

以上的跌代版的时间复杂度是O(n^3),下面的算法是以每个点为中心,计算构成的每条线的斜率来算的,这样能够使复杂度降低到O(n^2),参考的是《leetcode题解》。

#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;

struct Point 
{
    int x;
    int y;
    Point() : x(0), y(0) {}
    Point(int a, int b) : x(a), y(b) {}
};

int maxPoints(vector<Point> &points)
{
	if(points.size()<3)
		return points.size();
	const int N=points.size();
	int result=0;
	unordered_map<double,int> slopmap;
	for(int i=0;i<N;i++)
	{
		slopmap.clear();
		int samePoint=0;
		int commenLineNum=1;
		for(int j=i+1;j<N;j++)
		{
			double slop;
			if(points[i].x==points[j].x && points[i].y==points[j].y)
			{
				samePoint++;
				continue;
			}
			if(points[i].x==points[j].x)
				slop=double(INT_MAX);
			else
				slop=double(points[i].y-points[j].y)/(points[i].x-points[j].x);
			int count=0;
			if(slopmap.find(slop)!=slopmap.end())
				count=++slopmap[slop];
			else
			{
				count=2;
				slopmap[slop]=count;
			}
			if(count>commenLineNum)
				commenLineNum=count;
		}
		result=max(result,samePoint+commenLineNum);
	}
	return result;
}


int main()  
{  
	freopen("input.txt","r",stdin);
	vector<Point> points;
	int x,y;
	while(cin>>x>>y)
	{
		points.push_back(Point(x,y));
	}

	int result=maxPoints(points);

    system("pause");  
    return 0;  
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值