【LeetCode】149. 直線上最多的點數 結題報告 (C++)
阿新 • • 發佈:2018-11-11
原題地址:https://leetcode-cn.com/problems/max-points-on-a-line/description/
題目描述:
給定一個二維平面,平面上有 n 個點,求最多有多少個點在同一條直線上。
示例 1:
輸入: [[1,1],[2,2],[3,3]]
輸出: 3
解釋:
^
|
| o
| o
| o
+------------->
0 1 2 3 4
示例 2:
輸入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
輸出: 4
解釋:
^
|
| o
| o o
| o
| o o
+------------------->
0 1 2 3 4 5 6
解題方案:
這題好難,不會做。網上找的解題方式,參考地址給忘了。。。
有幾點值得學習:
- 雜湊表定義的結構與以往不同,表的key值為座標點,存的是在改直線上點的個數。
- 解題的主要思路是對點的集合從頭到尾遍歷一次,每次迴圈以當前點為目標,對其他點進行求解斜率k。由於每次確定了一個點的座標,不用再考慮b的大小。這種方法使得計算變得簡單,減少了需要儲存的值,並且每次迴圈結束後,需要對雜湊表進行空間的釋放,也節省了空間。
- 其實,為了實現快速查詢,map內部本身就是按序儲存的(比如紅黑樹)。在我們插入鍵值對時,就會按照key的大小順序進行儲存。這也是作為key的型別必須能夠進行<運算比較的原因。現在我們用Point型別作為key,因此,我們的儲存順序需要自定義。
- 雜湊表的key值為Point型別,進行儲存時使用的技巧很巧妙,運用了一點數學技巧。
程式碼:
/** * 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 gcd(int a, int b) {//最大公約數 return b ? gcd(b, a % b) : a; } struct cmp{ bool operator()(const Point &a, const Point &b){ return a.x < b.x || (a.x == b.x && a.y < b.y); } }; int maxPoints(vector<Point>& points) { if (points.empty()) return 0; map<Point, int, cmp> A; int L = points.size(), ans = 1, n; for (int i = 0; i < L; ++i) { if (L - i <= ans) break; A.clear(); n = 1; for (int j = i + 1; j < L; ++j) { int a = points[i].x - points[j].x, b = points[i].y - points[j].y; if (!(a | b)) { n ++; continue; } if (!a) A[Point(0, 1)] ++; else if (!b) A[Point(1, 0)] ++; else { int k = gcd(a, b); A[Point(a / k, b / k)] ++; } } ans = max(ans, n); for (auto &x : A) ans = max(ans, x.second + n); } return ans; } };