149. 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
解题思路:
这道题让我们找在一条直线上的点的最多的数目。
很容易我们想到把点和其所在的直线构成一个键值对放到map中。
问题是,如何表示直线?
若用y = kx + b来表示, x = c则无法表示。
一开始我用Ax + By + C =0来表示直线,自己构造了一个struct来存放参数,并且自己写了struct的hash方法,来存入unordered_map中。(见C++11 unordered_set & unordered_map 存储结构体(struct)
我通过 A = y1 - y2 B = x2- y1 C = x1y2 - x2y1来计算,但是这样会出现一个问题,就是由于点的相对距离不同, 明明在一条直线上却会被认为不在一条直线上。
参考了discussion中的16ms/28ms C++ Solutions with Explanations的答案
这里用一个pair来存储dx,dy的值,为了避免上述情况的发生,对dx 和 dy求了最大公约数并进行约分。
同时注意的是,为了避免重复计算多个点,在外部循环时创建map,一次循环结束时找到最大值存储起来。
还需要注意的是:若两点重合,虽然不能构成线,但是可以认为落在同一条直线上。
关于如何找到最大公约数:求最大公约数的算法
代码:
/** * 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 ret = 0; for(int i = 0; i < points.size(); i++){ map<pair<int,int>, int> m; int duplicate = 1; for(int j = i+1; j < points.size(); j++){ if(points[i].x == points[j].x && points[i].y == points[j].y){ duplicate++; continue; } int dx = points[i].x - points[j].x; int dy = points[i].y - points[j].y; int div = gcd(dx, dy); m[{dx/div, dy/div}]++; } ret = max(duplicate, ret); for(auto p:m){ ret = max(ret, (p.second+duplicate)); } } return ret; } private: int gcd(int a, int b){ while(b){ int temp = b; b = a % b; a = temp; } return a; } };