Given a set of points in the xy-plane, determine the minimum area of any rectangle formed from these points, with sides not necessarily parallel to the x and y axes.
If there isn't any rectangle, return 0.
Example 1:
Input: [[1,2],[2,1],[1,0],[0,1]]
Output: 2.00000
Explanation: The minimum area rectangle occurs at [1,2],[2,1],[1,0],[0,1], with an area of 2.
Example 2:
Input: [[0,1],[2,1],[1,1],[1,0],[2,0]]
Output: 1.00000 Explanation: The minimum area rectangle occurs at [1,0],[1,1],[2,1],[2,0], with an area of 1.
Example 3:
Input: [[0,3],[1,2],[3,1],[1,3],[2,1]]
Output: 0 Explanation: There is no possible rectangle to form from these points.
Example 4:
Input: [[3,1],[1,1],[0,1],[2,1],[3,3],[3,2],[0,2],[2,3]]
Output: 2.00000 Explanation: The minimum area rectangle occurs at [2,1],[2,3],[3,3],[3,1], with an area of 2.
Note:
1 <= points.length <= 50
0 <= points[i][0] <= 40000
0 <= points[i][1] <= 40000
- All points are distinct.
- Answers within
10^-5
of the actual value will be accepted as correct.
這道題是之前那道 Minimum Area Rectangle 的拓展,雖說是拓展,但是解題思想完全不同。那道題由於矩形不能隨意翻轉,所以任意兩個相鄰的頂點一定是相同的橫坐標或者縱坐標,而這道題就不一樣了,矩形可以任意翻轉,就不能利用之前的特點了。那該怎么辦呢,這里就要利用到矩形的對角線的特點了,我們都知道矩形的兩條對角線長度是相等的,而且相交於矩形的中心,這個中心可以通過兩個對頂點的坐標求出來。只要找到了兩組對頂點,它們的中心重合,並且表示的對角線長度相等,則一定可以組成矩形。基於這種思想,可以遍歷任意兩個頂點,求出它們之間的距離,和中心點的坐標,將這兩個信息組成一個字符串,建立和頂點在數組中位置之間的映射,這樣能組成矩形的點就被歸類到一起了。接下來就是遍歷這個 HashMap 了,只能取出兩組頂點及更多的地方,開始遍歷,分別通過頂點的坐標算出兩條邊的長度,然后相乘用來更新結果 res 即可,參見代碼如下:
class Solution {
public:
double minAreaFreeRect(vector<vector<int>>& points) {
int n = points.size();
if (n < 4) return 0.0;
double res = DBL_MAX;
unordered_map<string, vector<vector<int>>> m;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
long dist = getLength(points[i], points[j]);
double centerX = (points[i][0] + points[j][0]) / 2.0;
double centerY = (points[i][1] + points[j][1]) / 2.0;
string key = to_string(dist) + "_" + to_string(centerX) + "_" + to_string(centerY);
m[key].push_back({i, j});
}
}
for (auto &a : m) {
vector<vector<int>> vec = a.second;
if (vec.size() < 2) continue;
for (int i = 0; i < vec.size(); ++i) {
for (int j = i + 1; j < vec.size(); ++j) {
int p1 = vec[i][0], p2 = vec[j][0], p3 = vec[j][1];
double len1 = sqrt(getLength(points[p1], points[p2]));
double len2 = sqrt(getLength(points[p1], points[p3]));
res = min(res, len1 * len2);
}
}
}
return res == DBL_MAX ? 0.0 : res;
}
long getLength(vector<int>& pt1, vector<int>& pt2) {
return (pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1]);
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/963
類似題目:
參考資料:
https://leetcode.com/problems/minimum-area-rectangle-ii/
https://leetcode.com/problems/minimum-area-rectangle-ii/discuss/208361/JAVA-O(n2)-using-Map