356 Line Reflection
Given n points on a 2D plane, find if there is such a line parallel to y-axis that reflect the given points.
Example 1:
Givenpoints=
[[1,1],[-1,1]]
, returntrue
.Example 2:
Givenpoints=
[[1,1],[-1,-1]]
, returnfalse
.Follow up:
Could you do better than O(n^2)?
The Idea: First iterate through the list of points to find the most left and the most right x coordinates. The respected axis for between these two points must be 1/2 the distance between these points from left coordinate. It also must follow that the remaining points are a reflection of this axis. In order compare against this axis, I allocated an
unordered_set
of points, so that I can quickly lookup any point by its unique string permutation (x,y). So then, in order to verify the reflection, I iterate through each point and check to see whether its reflected analog exists through in the unordered_set
through a simple lookup. If all the reflected analogs exists, return true.There are a few edge cases:
1. Empty set is a valid reflection.
2. Checking for points that exist along the axis of reflection.
Time Complexity: O(n) time and space
struct pair_hash {
inline std::size_t operator()(const std::pair<int, int> & v) const {
return hash<string>{}(to_string(v.first) + to_string(v.second));
}
};
unordered_set<pair<int, int>, pair_hash> add_to_set(const vector<pair<int, int>> &points) {
unordered_set<pair<int, int>, pair_hash> unique_points;
unique_points.reserve(points.size());
for (auto p : points)
unique_points.insert(p);
return unique_points;
}
pair<int, int> min_and_max_x_val(const vector<pair<int, int>>& points) {
int my_min = INT_MAX, my_max = INT_MIN;
for (auto &p : points) {
my_min = min(my_min, p.first);
my_max = max(my_max, p.first);
}
return {my_min, my_max};
}
bool isReflected(vector<pair<int, int>>& points) {
if (points.empty()) return true;
pair<int, int> min_max_x = min_and_max_x_val(points);
if (min_max_x.first == min_max_x.second) return true; // TODO: try without this later as well
double verify_this_y_axis = (abs(min_max_x.second - min_max_x.first) / 2.0) + min_max_x.first;
unordered_set<pair<int, int>, pair_hash> unique_points = add_to_set(points);
for (auto p : unique_points) {
double dist_to_axis = abs(verify_this_y_axis - p.first);
pair<int, int> reflected_analog;
if (p.first <= verify_this_y_axis)
reflected_analog = {p.first + (dist_to_axis) * 2, p.second};
else reflected_analog = { p.first - (dist_to_axis) * 2, p.second };
if (unique_points.find(reflected_analog) == unique_points.end())
return false;
}
return true;
}
Testing
int main()
{
vector<pair<int, int>> points1 = { { 1,1 },{ -1,1 } };
cout << boolalpha << isReflected(points1) << endl; // T
vector<pair<int, int>> points2 = { { 1,1 },{ -1,-1 } };
cout << boolalpha << isReflected(points2) << endl; // F
vector<pair<int, int>> points3 = { { 0,0 },{ 1,0 } };
cout << boolalpha << isReflected(points3) << endl; // T
vector<pair<int, int>> points4 = { { -2,0 },{ -1,1 },{ 1,1 },{ 2,0 }, { 1,-1 },{ -1,-1 } };
cout << boolalpha << isReflected(points4) << endl; // T
vector<pair<int, int>> points5 = { { -2,0 }, {1,2}, { -1,1 },{ 1,1 },{ 2,0 },{ 1,-1 },{ -1,-1 } };
cout << boolalpha << isReflected(points5) << endl; // F
vector<pair<int, int>> points6 = { { 1, 1 }, {-4, 1} };
cout << boolalpha << isReflected(points6) << endl; // T
vector<pair<int, int>> points7 = { {10, 10},{11, 11},{9, 11} };
cout << boolalpha << isReflected(points7) << endl; // T
}
Update:
The previous submission performed in 21 percentile range. Updating the hash function to the follow improved performance to 75 percentile.
struct pair_hash {
inline std::size_t operator()(const std::pair<int, int> & v) const {
std::hash<int> int_hasher;
return int_hasher(v.first) ^ int_hasher(v.second);
}
};
Last modified 4yr ago