LeetCode 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.
强行解:
inline bool valueSame(double a, double b) { return abs(a - b) < 0.01; } class Line { public: double k; double d; bool infiniteK; Line(){}; Line(double _k, double _d) : k(_k), d(_d), infiniteK(false) {} Line(double _k) : k(_k), d(0.0), infiniteK(true) {} bool operator==(const Line& line) const { if (infiniteK != line.infiniteK) { return false; } else if (line.infiniteK) { return valueSame(k, line.k); } return valueSame(k, line.k) && valueSame(d, line.d); } }; struct LineHashFunc { size_t operator() (const Line& line) const { return (std::hash<double>()(line.k)) ^ (std::hash<double>()(line.d)) ^ (std::hash<bool>()(line.infiniteK)); } }; struct PointHashFunc { size_t operator() (const Point& point) const { return (hash<int>()(point.x)) ^ (hash<int>()(point.y) << 1); } }; struct PointEqualFunc { bool operator()(const Point& a, const Point& b) const { return valueSame(a.x, b.x) && valueSame(a.y, b.y); } }; class Solution { public: unordered_map<Line, unordered_set<int>, LineHashFunc> pts; int line_count; Line maxline; public: int maxPoints(vector<Point>& points) { pts.clear(); line_count = 0; unordered_map<Point, int, PointHashFunc, PointEqualFunc> pnums; int max_pnums = 0; for (Point& p : points) { max_pnums = max(max_pnums, ++pnums[p]); } int len = points.size(); for (int i=0; i<len; i++) { Point& a = points[i]; vector<Line> lines; for (int j = i + 1; j<len; j++) { Point& b = points[j]; if (valueSame(a.x, b.x)) { if (!valueSame(a.y, b.y)) { lines.push_back(Line(a.x)); inc(lines.back(), i, j); } else { for (Line line : lines) { inc(line, i, j); } } continue; } double k = (a.y - b.y) * 1.0 / (a.x - b.x); double d = a.y - k * a.x; lines.push_back(Line(k, d)); inc(lines.back(), i, j); } } return max(max_pnums, line_count); } void inc(Line a, int ia, int ib) { if (!pts.count(a)) { pts[a] = unordered_set<int>(); } pts[a].insert(ia); pts[a].insert(ib); if (pts[a].size() > line_count) { line_count = pts[a].size(); maxline = a; } } };
能把程序写成这样真是太忧伤了。以上是从全局的角度考虑,等算出所有可能的直线后进行最大值提取。
从discuss中找了个高大上的:从局部考虑,过一点,再加个斜率,一条直线就确定了,逐步计算过这些线的点,取最大的即可。
/** * 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 len = points.size(); if (len <= 2) { return len; } int maxon = 0;; for (int i=0; i<len; i++) { Point& a = points[i]; unordered_map<double, int> lines; int normal = 1; int vertical = 1; int duplicate= 0; for (int j=i+1; j<len; j++) { Point& b = points[j]; if (a.x == b.x) { if (a.y == b.y) { duplicate++; } else { vertical++; } } else { double k = (a.y - b.y) * 1.0 / (a.x - b.x); lines[k] += !lines[k] + 1; normal = max(normal, lines[k]); } } maxon = max(maxon, max(normal + duplicate, vertical + duplicate)); } return maxon; } };