
Problem Statement
Given an array named points
where each element points[i]
represents a coordinate [xi, yi]
on the X-Y plane (where xi
and yi
are integers), the task is to determine the maximum number of these points that can align on the same straight line. The solution should effectively evaluate all possible lines that could be formed by joining any two points and then determine the line that passes through the most number of these points. It's a computational geometry problem focusing on lines and slopes in a coordinate system.
Examples
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.
Approach and Intuition
To determine the maximum number of points that lie on the same straight line from a given set of points on a 2D plane, we can employ a strategy based on calculating slopes and using hash maps to count occurrences. Here's the breakdown of the approach:
- For each point in the given array, consider it as a potential starting point of a line.
- For every other point, calculate the slope it forms with this starting point. The slope between two points
p1
(x1, y1) andp2
(x2, y2) is given by(y2 - y1) / (x2 - x1)
. However, direct division may lead to issues with floating-point precision. - To handle the precision and divisibility, represent the slope as a normalized fraction or use a particular encoding (like storing the numerator and denominator as a tuple after reducing them to their greatest common divisor (GCD)).
- Use a hash map to count the number of times each slope occurs with the current starting point as one end of the line. Additionally, take care of vertical lines (undefined slope) and overlapping points (though in this problem, all points are unique).
- The maximum value in the hash map for a particular starting point gives the maximum number of points that align along a line passing through that starting point.
- Iterate over all points to ensure each one is considered as a starting point, updating a global maximum count whenever a local maximum exceeds it.
Understanding examples provided:
- Example 1: Points =
[[1, 1], [2, 2], [3, 3]]
- All points lie on the line y = x, a very straightforward scenario where the slope between any two points is 1.
- Example 2: Points =
[[1, 1], [3, 2], [5, 3], [4, 1], [2, 3], [1, 4]]
- The maximum number of points that lie on a single straight line is 4. These four points form a line with a consistent increment pattern in x and y coordinates (revealing the same slope).
This problem highlights the importance of efficiently calculating and comparing the slope between points. Using a hash map to store these slopes for each point, and keeping track of the counts is a crucial part of the solution, enabling us to determine the line with maximum collinear points efficiently within given constraints.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
int maximumPoints(vector<vector<int>>& coordinates) {
int total_points = coordinates.size();
if (total_points == 1) {
return 1;
}
int max_result = 2;
for (int i = 0; i < total_points; i++) {
unordered_map<double, int> slope_count;
for (int j = 0; j < total_points; j++) {
if (j != i) {
double slope = atan2(coordinates[j][1] - coordinates[i][1],
coordinates[j][0] - coordinates[i][0]);
slope_count[slope]++;
}
}
for (auto [angle, count] : slope_count) {
max_result = max(max_result, count + 1);
}
}
return max_result;
}
};
The C++ solution provided tackles the problem of finding the maximum number of points that lie on a straight line from a given set of 2D coordinates. This solution methodically approaches the problem by:
- Initializing the count of total points.
- Returning
1
if there's only one point, since a single point trivially forms a line on its own. - Initializing a variable
max_result
to store the maximum number of points that can be aligned straightly and starts its value at2
since at least two points are needed to form a line. - Utilizing two nested loops to compare the slopes between a point and all other points. The key observation here is using the mathematical function
atan2
to calculate the slope to maintain precision and handle the uniqueness. - Storing the computed slopes in an unordered map
slope_count
, where the key is the slope and the value is the count of how many times this slope occurs. - Updating the
max_result
for each slope comparison by considering the maximum count of any particular slope plus one (accounting for the initial point). - Ultimately, the function returns the value of
max_result
, which represents the maximum number of collinear points found.
This approach efficiently handles the concern of precision and computational complexity by mapping slopes and counting occurrences, optimizing the process of identifying maximum aligned points.
class Solution {
public int findMaxPoints(int[][] coordinates) {
int totalPoints = coordinates.length;
if (totalPoints == 1) {
return 1;
}
int maxCount = 2;
for (int i = 0; i < totalPoints; i++) {
Map<Double, Integer> slopeCount = new HashMap<>();
for (int j = 0; j < totalPoints; j++) {
if (j != i) {
double slope = Math.atan2(
coordinates[j][1] - coordinates[i][1],
coordinates[j][0] - coordinates[i][0]
);
slopeCount.merge(slope, 1, Integer::sum);
}
}
maxCount = Math.max(maxCount, Collections.max(slopeCount.values()) + 1);
}
return maxCount;
}
}
The provided Java code defines a method to determine the maximum number of collinear points from a list of points on a 2D plane. The method findMaxPoints
takes an array of integer arrays, where each sub-array contains two integers representing the $(x, y)$ coordinates of a point.
Here's a breakdown of how the code works:
- Start by getting the total number of points.
- If there is only one point, then the maximum number of collinear points is obviously 1.
- Initialize
maxCount
to 2 to account for the fact that at least two points are required to form a line. - Use nested loops where each outer iteration picks a point and the inner loop calculates the slope of a line formed with every other point using the
atan2
function. This function calculates the angle from the positive X-axis to the point, ensuring a unique value for slopes of lines between pairs, allowing for the handling of vertical lines. - Use a
HashMap
to count occurrences of each slope for a given base point. - Update the
maxCount
if any slope count for a point exceeds the currentmaxCount
. - At the end of the outer loop, return the
maxCount
which represents the maximum number of collinear points.
This approach, using the slope calculation via the atan2
function, ensures robustness against issues like vertical slopes creating undefined behaviors. Furthermore, it considers each point as a potential part of multiple lines, ensuring that the maximum collinear set is correctly identified. The use of a hashmap to count the frequency of each slope significantly optimizes the search process by avoiding the need for extensive pairwise comparisons. The complexity is mainly dictated by the nested loops and hashmap operations, culminating in a time complexity close to $O(n^2)$, where $n$ is the number of points. This solution is optimized for accuracy and handles a variety of edge cases effectively.
struct point_map {
double slope;
int count;
UT_hash_handle hh;
};
int maximumPointsOnLine(int **coordinates, int size, int *rowSize) {
if (size == 1) {
return 1;
}
int maxPoints = 2;
for (int i = 0; i < size; i++) {
struct point_map *slopeCounts = NULL, *element;
for (int j = 0; j < size; j++) {
if (i != j) {
double slope = atan2((double)(coordinates[j][1] - coordinates[i][1]),
(double)(coordinates[j][0] - coordinates[i][0]));
HASH_FIND(hh, slopeCounts, &slope, sizeof(double), element);
if (element == NULL) {
element = (struct point_map *)malloc(sizeof(struct point_map));
element->slope = slope;
element->count = 1;
HASH_ADD(hh, slopeCounts, slope, sizeof(double), element);
} else {
element->count++;
}
}
}
struct point_map *cur;
int maxCurrent = 0;
for (cur = slopeCounts; cur != NULL; cur = cur->hh.next) {
if (cur->count > maxCurrent) {
maxCurrent = cur->count;
}
}
maxPoints = maxPoints > maxCurrent + 1 ? maxPoints : maxCurrent + 1;
HASH_CLEAR(hh, slopeCounts);
}
return maxPoints;
}
The provided C code solution addresses the problem of finding the maximum number of points that can be aligned on a straight line from a given set of points in a 2D plane. This solution achieves it by calculating and comparing the slopes of lines formed between each pair of points.
- Implement a specific C structure called
point_map
which holds a slope value and a count of how many times this slope appears between various pairs of points. - Use a hash table to store each unique slope encountered while iterating through point pairs, employing the uthash hashing library for this purpose.
- Iterate through all the points, and for each point, iterate through all other points to compute the slope formed by the pair.
- For each computed slope, either add a new record to the hash table if the slope has not been encountered before, or update the existing record's count.
- Using atan2 function ensures avoidance of division by zero and correctly handles horizontal and vertical lines.
- Maintain the count of points that lie on the line represented by each slope.
- Continuously track and update the maximum number of points on a line.
The code finally returns the maximum count, adding 1 to the count value stored in the hash table to account for the initial point. This algorithm handles all edge and corner cases by considering all pairs and using a dynamic counting mechanism via hash tables.
var maximumCollinearPoints = function(points) {
let totalPoints = points.length;
if (totalPoints === 1) {
return 1;
}
let maxResult = 2;
for (let idx = 0; idx < totalPoints; idx++) {
let count = {};
for (let jdx = 0; jdx < totalPoints; jdx++) {
if (jdx !== idx) {
let slope = Math.atan2(
points[jdx][1] - points[idx][1],
points[jdx][0] - points[idx][0],
);
count[slope] = count[slope] ? count[slope] + 1 : 1;
}
}
maxResult = Math.max(maxResult, Math.max(...Object.values(count)) + 1);
}
return maxResult;
};
The JavaScript solution for determining the maximum number of collinear points on a plane follows a creative approach leveraging the properties of slopes between pairs of points. Here's an insight into how the function maximumCollinearPoints
achieves this:
- Start by defining the function
maximumCollinearPoints
, which takes an array of point coordinates as its argument. - Begin by determining the total number of points received in the array.
- Handle a base case: if there is only one point, return 1 directly as a single point can't form a line with others.
- Initialize a variable
maxResult
to store the maximum number of collinear points found, starting with a default of 2 since at a minimum two points are required to form a line. - Use two nested for loops to compare each point in the array with every other point. Utilize the outer loop to pick a reference point and the inner loop to pick a comparison point:
- Exclude the case where both indices in the loop refer to the same point, ensuring comparisons only between distinct points.
- Compute the slope for each pair using the
atan2
function, which considers both the X and Y differences to determine the angle of the line connecting both points. - Store the count of how many times each slope occurs using a hash map. This helps determine how many points share the same angle relative to the reference point.
- Inside the inner loop, after iterating over all points relative to one reference, update the
maxResult
if the maximum slope occurrences (plus one for the reference point itself) exceed the current stored maximum. - Return the
maxResult
which represents the largest collinear set found.
This solution effectively ensures that all possible pairs and their resultant slopes are considered, efficiently identifying the maximum set of collinear points using angle comparisons, thereby avoiding the complexities of traditional slope and intercept calculations. This approach also accounts for vertical lines where traditional slope calculations might fail due to division by zero errors.
class Solution:
def maximumPoints(self, coordinates: List[List[int]]) -> int:
total_points = len(coordinates)
if total_points == 1:
return 1
max_points = 2
for index in range(total_points):
point_count = collections.defaultdict(int)
for other_index in range(total_points):
if other_index != index:
slope = math.atan2(
coordinates[other_index][1] - coordinates[index][1],
coordinates[other_index][0] - coordinates[index][0]
)
point_count[slope] += 1
max_points_on_line = max(point_count.values()) + 1
max_points = max(max_points, max_points_on_line)
return max_points
The given solution is a Python function designed to determine the maximum number of points that lie on a singular straight line from a list of 2D coordinate points. This function, maximumPoints
, utilizes mathematical calculations and Python libraries to efficiently solve the problem. Below outlines the core actions performed in the code:
- Declare a function within the class
Solution
that accepts a list of lists representing points in 2D space. - Calculate the total number of points. If only one point exists, the function immediately returns 1, since the single point trivially forms a line.
- Initialize
max_points
variable to 2 to account for the minimum points forming a straight line. - Iterate through each point, treating it possibly as a beginning of a line, in a nested loop to compare it with every other point for collective line calculations.
- Calculate the slope of the line formed with any other point using the arctangent function
math.atan2
. This helps in determining the orientation of the line segment formed by any pair of points. - Utilize
collections.defaultdict
for efficient counting of identical slope values which indicates that the points share the same line. - Determine the maximum number of points on any line passing through the current base point and update
max_points
accordingly. - Return the highest count of points that can be aligned in a straight line after all points have been considered.
This method leverages geometrical insights and hashing (via slope calculations) to find an optimal line that contains the maximum points. By comparing every point with every other point using slopes, the algorithm ensures all possible lines are considered. The solution efficiently handles larger sets of points using constant space for slope counting and linear space relative to input size for storing points.
No comments yet.