The Line Reflection problem asks: Given a set of 2D points on the XY-plane, determine if there exists a vertical line (parallel to the Y-axis) such that each point in the set has a reflection about this line that is also in the set.
[x, y]
.x = c
for some constant c
.
The task is to return true
if such a line exists, and false
otherwise.
At first glance, you might think of brute-forcing all possible vertical lines through the points and checking for each if all points are symmetric about it. However, this would be highly inefficient, especially for large inputs.
Instead, think about the properties of reflection:
x = c
, the reflection of a point (x, y)
is (2c - x, y)
.The challenge is to efficiently check that for every point, its mirror image about this line also exists in the set.
Let's break the solution down step-by-step:
x
values among all points: minX
and maxX
.x = (minX + maxX) / 2
.(x, y)
, compute its reflected x-coordinate: xr = minX + maxX - x
.(xr, y)
exists in the set.false
.true
.
This approach is efficient because:
Let's walk through an example:
Input: points = [[1,1], [2,1], [3,1]]
true
.
If we had a point like (4,1), its reflection would be (0,1), which is not in the set, so the answer would be false
.
This is a significant improvement, making the solution efficient for large datasets.
The key insight is that the only possible reflection line is halfway between the smallest and largest x-coordinates. By leveraging a set for O(1) lookups and checking every point's reflection, we ensure correctness and efficiency. This solution is elegant because it turns a seemingly complex geometric problem into simple arithmetic and set operations, making it both fast and easy to understand.
class Solution:
def isReflected(self, points):
point_set = set((x, y) for x, y in points)
min_x = min(x for x, y in points)
max_x = max(x for x, y in points)
target = min_x + max_x
for x, y in points:
if (target - x, y) not in point_set:
return False
return True
class Solution {
public:
bool isReflected(vector<vector<int>>& points) {
unordered_set<string> pointSet;
int minX = INT_MAX, maxX = INT_MIN;
for (auto& p : points) {
minX = min(minX, p[0]);
maxX = max(maxX, p[0]);
pointSet.insert(to_string(p[0]) + "," + to_string(p[1]));
}
int target = minX + maxX;
for (auto& p : points) {
int xr = target - p[0];
string reflected = to_string(xr) + "," + to_string(p[1]);
if (pointSet.find(reflected) == pointSet.end()) {
return false;
}
}
return true;
}
};
class Solution {
public boolean isReflected(int[][] points) {
Set<String> pointSet = new HashSet<>();
int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
for (int[] p : points) {
minX = Math.min(minX, p[0]);
maxX = Math.max(maxX, p[0]);
pointSet.add(p[0] + "," + p[1]);
}
int target = minX + maxX;
for (int[] p : points) {
int xr = target - p[0];
String reflected = xr + "," + p[1];
if (!pointSet.contains(reflected)) {
return false;
}
}
return true;
}
}
var isReflected = function(points) {
let pointSet = new Set();
let minX = Infinity, maxX = -Infinity;
for (let [x, y] of points) {
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
pointSet.add(x + ',' + y);
}
let target = minX + maxX;
for (let [x, y] of points) {
let xr = target - x;
if (!pointSet.has(xr + ',' + y)) {
return false;
}
}
return true;
};