Max Points on a Line
Return the largest number of given points that lie on one straight line.
Open on LeetCode ↗Intuition
Trying every pair as a line and rescanning all points costs O(n^3), and floating-point slopes can merge or split lines incorrectly. Fixing one point changes the question into counting how many other points share each direction from that anchor. A direction can be represented exactly by a reduced integer pair (dy, dx). Normalizing signs makes geometrically identical slopes use the same hash key.
When points must be grouped by collinearity, anchor one point and group the rest by slope. Exact integer normalization is the reliable substitute for floating-point division in geometry hashing.
Approach
Choose each point as the line's anchor
For anchor i, inspect every later point j. Every line through the anchor is identified by the direction from points[i] to points[j], so the largest direction count plus the anchor gives the best line through i.
Reduce direction vectors with a greatest common divisor
Compute dx and dy, divide both by gcd(abs(dx), abs(dy)), and force dx nonnegative. Give vertical directions one canonical pair and horizontal directions another so equivalent slopes cannot receive different keys.
Count canonical slopes per anchor
Store each reduced pair in a fresh frequency map for the current anchor. Update the global answer with count + 1, where one accounts for the anchor itself. Rebuilding the map is essential because slopes from different anchors describe different lines.
Solution
Common pitfalls
Hashing floating-point slopes
slope = dy / dx
slope = (dy // g, dx // g)
Floating-point rounding can assign different keys to the same rational slope.
Leaving equivalent signs unnormalized
key = (dy // g, dx // g)
if dx < 0:
dx, dy = -dx, -dyVectors (1, 1) and (-1, -1) describe the same direction class.
Forgetting the anchor
answer = max(answer, counts[key])
answer = max(answer, counts[key] + 1)
The frequency counts other points, while the fixed anchor also lies on the line.
Edge cases
Initialize the answer to one and return it without needing a pair.
All vectors with dx == 0 are normalized to (1, 0).
Sign normalization moves the negative sign to dy, producing one shared key.