Skip to content

Latest commit

 

History

History

149

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Given an array of points where points[i] = [xi, yi] represents a point on the X-Y plane, return the maximum number of points that lie on the same straight line.

 

Example 1:

Input: points = [[1,1],[2,2],[3,3]]
Output: 3

Example 2:

Input: points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4

 

Constraints:

  • 1 <= points.length <= 300
  • points[i].length == 2
  • -104 <= xi, yi <= 104
  • All the points are unique.

Companies: Oracle, Cisco, Amazon, Apple, Sprinklr, tcs, LinkedIn, Google, Microsoft, MakeMyTrip, Adobe, Uber, Bloomberg, Twitter

Related Topics:
Array, Hash Table, Math, Geometry

Similar Questions:

Solution 1.

Firstly, assume there are no duplicate points.

We keep a list of lines, each of which is a list of points on that line. We push the first line which is formed by the first two points a and b into it. So now the lines becomes:

(a, b)

Then we visit the other points one by one. For the third point c, we traverse through the lines and see if c is in any of the lines.

Assume c is not on line (a, b), we add (a, c) and (b, c) to the lines.

(a, b)
(a, c)
(b, c)

For the next point d, assume d is on line (b, c) but not on the other lines, then add d into this line.

(a, b)
(a, c)
(b, c, d)

And at the same time we know b and c are d's neighbor (i.e. they are on the same line), and a is not d's neighbor. So we add line (a, d) to the lines.

(a, b)
(a, c)
(b, c, d)
(a, d)

We keep visiting the points in this way. The final result will be the length of longest line.

Now, what if our assumption "there are no duplicate points" is wrong? Just merge the same points into one entry, and take a note of its count. The other logics are the same.

// OJ: https://leetcode.com/problems/max-points-on-a-line/
// Author: github.com/lzl124631x
// Time: O(N^3)
//   In worse case, when visiting ith point, there will be O(i^2)
//   lines, but all the lines are of constant size 2. So in
//   sum it's O(N^3), not O(N^4).
// Space: O(N^2)
namespace std {
    template <> struct hash<Point> {
        std::size_t operator () (const Point &p) const {
            return hash<int>()(p.x) ^ hash<int>()(p.y);
        }
    };
}

bool operator==(const Point& a, const Point& b) {
	return a.x == b.x && a.y == b.y;
}

class Solution {
private:
    bool onSameLine(Point &a, Point &b, Point &c) {
        return (long long)(a.x - b.x) * (a.y - c.y) == (long long)(a.x - c.x) * (a.y - b.y);
    }
public:
    int maxPoints(vector<Point>& points) {
        if (points.size() <= 2) return points.size();
        unordered_map<Point, int> m;
        for (auto p : points) m[p]++;
        vector<pair<Point, int>> ps(m.begin(), m.end());
        vector<vector<int>> lines(1, vector<int>{ 0, 1 });
        int N = ps.size();
        for (int i = 2; i < N; ++i) {
            auto &p = ps[i].first;
            vector<int> bad(i, 1);
            for (auto &line : lines) {
                auto &p1 = ps[line[0]].first, &p2 = ps[line[1]].first;
                if (!onSameLine(p1, p2, p)) continue;
                for (int neighbor : line) bad[neighbor] = 0;
                line.push_back(i);
            }
            for (int j = 0; j < i; ++j) {
                if (bad[j]) lines.emplace_back(vector<int>{ j, i });
            }
        }
        int ans = 2;
        for (auto line : lines) {
            int cnt = 0;
            for (auto i : line) cnt += ps[i].second;
            ans = max(ans, cnt);
        }
        return ans;
    }
};

Solution 2.

// OJ: https://leetcode.com/problems/max-points-on-a-line
// Author: github.com/lzl124631x
// Time: O(N^2)
// Space: O(N)
class Solution {
public:
    int maxPoints(vector<vector<int>>& A) {
        int N = A.size(), ans = 0;
        for (int i = 0; i < N; ++i) { // Use A[i] as point1
            unordered_map<double, int> m;
            int mx = 0;
            for (int j = i + 1; j < N; ++j) { // Use A[j] as point2
                int x1 = A[i][0], y1 = A[i][1];
                int x2 = A[j][0], y2 = A[j][1];
                if ((x1 > x2) || (x1 == x2 && y1 < y2)) swap(x1, x2), swap(y1, y2); // make sure these two points are ordered
                mx = max(mx, ++m[atan2(x2 - x1, y2 - y1)]); // cout the frequency of angles
            }
            ans = max(ans, mx + 1);
        }
        return ans;
    }
};