一. 题意描述
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
二. 题目分析
看到这道题想到的第一种方法是暴力枚举法,时间复杂度为O(n3),显然是不够好的。
于是我们需要进行一些优化,注意到对于一条直线上的任意两点,他们连线的斜率是相同的。于是我们可以算出指定点到其他所有点的斜率,先使得包含指定点的直线上点数最多,这个过程中可以建立斜率和直线上点数的一一对应关系,可以利用STL中的map模板。
然后再将包含各个点的直线上点的数量进行比较,得到max points on a line.
需要注意的地方:
1.就像奇怪的高中数学解析几何题告诉我们的一样,使用斜率就一定要考虑斜率不存在的情况。
2.斜率不存在的情况还有两种,一种是两个点根本就是一样的,另一种就是两个点只有横坐标一样,这两种情况都需要特殊判断。
代码如下:
/**
* 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) {
if(points.size() <= 2)
return points.size();
double k = 0;
int maxPoints = 0; //max points on a line
int maxPointsTemp = 0; //包含特定点的max points on a line
int samePoints = 0; //特定点重复了几次,没重复过算一次
int sameXPoints = 0; //和特定点横坐标相同但不重合的点有几个
map<double, int> Map;
for(int i = 0; i < (points.size() - 1); i++)
{
maxPointsTemp = 0;
samePoints = 1; //1是i点本身
sameXPoints = 0;
Map.clear();
for(int j = (i + 1); j < points.size(); j++)
{
if(points[j].x == points[i].x)
{
if(points[j].y == points[i].y) //重合
samePoints++;
else //横坐标相同但不重合
sameXPoints++;
}
else
{
k = (double)(points[j].y - points[i].y) / (points[j].x - points[i].x); //求斜率
if(Map.find(k) != Map.end())
Map[k]++;
else
Map[k] = 1;
}
}
map<double, int>::iterator it, iend;
iend = Map.end();
for(it = Map.begin(); it != iend; it++)
{
if(maxPointsTemp < it->second)
maxPointsTemp = it->second;
}
if(maxPointsTemp < sameXPoints)
maxPointsTemp = sameXPoints;
maxPointsTemp += samePoints; //得到包含特定点的max points on a line,包含自身和重复点
if(maxPoints < maxPointsTemp)
maxPoints = maxPointsTemp; //得到max points on a line
}
return maxPoints;
}
};
最后是在实际写代码过程中遇到的一些问题:
1. 最开始使用的是数据结构是哈希表,但写完之后再Leetcode上提交显示编译错误,报错Line 21: ‘hash_map’ was not declared in this scope。
额感觉一定是我哪儿写错了= =
2.有一个bug调了挺长时间,发现是
k = (double)(points[j].y - points[i].y) / (points[j].x - points[i].x);
这一句一开始忘了进行强制类型转换,感觉以后写代码的时候一些细节还是要更加注意。
最后,谢谢收看~