一. 题意描述
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);
这一句一开始忘了进行强制类型转换,感觉以后写代码的时候一些细节还是要更加注意。
最后,谢谢收看~