题目地址:
https://leetcode.com/problems/minimum-area-rectangle-ii/
给定平面直角坐标系的 n n n个点,题目保证这 n n n个点都是整点并且各不相同。可以任意挑 4 4 4个能组成矩形的点,问这些矩形的面积最小值。如果不存在任何矩形则返回 0 0 0。
可以先将 n ( n − 1 ) / 2 n(n-1)/2 n(n−1)/2条边构造出来,将它们视为对角线,那么能组成矩形的对角线必须满足中点重合并且长度相等。那么按照中点和长度将所有对角线分类,矩形只会在某一类对角线内部产生。直接枚举即可。代码如下:
class Solution {
public:
long get_dist(vector<int>& a, vector<int>& b) {
long dx = a[0] - b[0], dy = a[1] - b[1];
return dx * dx + dy * dy;
}
double minAreaFreeRect(vector<vector<int>>& p) {
int n = p.size();
vector<vector<long>> v;
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++) {
long x1 = p[i][0], y1 = p[i][1], x2 = p[j][0], y2 = p[j][1];
long cx = x1 + x2, cy = y1 + y2;
v.push_back({cx, cy, get_dist(p[i], p[j]), i, j});
}
sort(v.begin(), v.end());
double res = 1e20;
for (int i = 0; i < v.size(); i++) {
int j = i + 1;
// 找出能构成矩形的下标范围
while (j < v.size() && v[i][0] == v[j][0] && v[i][1] == v[j][1] &&
v[i][2] == v[j][2])
j++;
for (int a = i; a < j; a++)
for (int b = i; b < a; b++) {
auto &a1 = p[v[a][3]], &a2 = p[v[a][4]], &b1 = p[v[b][3]],
&b2 = p[v[b][4]];
double area = sqrt(get_dist(a1, b1)) * sqrt(get_dist(a1, b2));
if (area > 0) res = min(res, area);
}
i = j - 1;
}
return res == 1e20 ? 0 : res;
}
};
时间复杂度 O ( n 2 + ∑ e i 2 ) O(n^2+\sum e_i^2) O(n2+∑ei2), e i e_i ei表示归为同一类的边的数量,空间 O ( n 2 ) O(n^2) O(n2)。