我们给出了一个(轴对齐的)二维矩形列表 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐标, (xi1, yi1) 是该矩形 左下角 的坐标, (xi2, yi2) 是该矩形 右上角 的坐标。
计算平面中所有 rectangles 所覆盖的 总面积 。任何被两个或多个矩形覆盖的区域应只计算 一次 。返回 总面积 。因为答案可能太大,返回 10^9 + 7 的 模 。
思路:
我的第一反应是计算所有矩形面积,然后减去两两相交的面积。这种做法是错误的因为每个重叠部分只要减去一次,可能会重复减去。
这道题的正确思路是把整个区域按所有矩形的边界进行划分,然后逐个计算分块的面积。
步骤:
- 把所有矩形的左右边存到一个数组和上下边存到另一个数组,分别将它们去重,然后排序。此时得到的按从左到右和从上到下的排列边界,它们将整个区域划分为了一条条横纵排列的线段,线段组成了一个个小矩形。
- 按左界排序矩阵。这步是为了接下来从左到右扫描做准备。
- 创建一个二维数组,其长度等于矩形数量。其中的每个一维数组存储该矩形覆盖的上下边界的分割的线段。这步是为了之后遍历矩形时能快速地找到它覆盖的区域。
- 创建一个长度等于上下边界-1的bool数组。它的作用是标记在本次扫描中某块区域是否已经被覆盖。
- 创建一个与bool数组长度相同的long数组,用来存放该区域已经覆盖的总面积。
- 从左到右遍历左右边界,每次循环时将bool数组全部值为false,在循环中遍历所有覆盖了该边界的矩形,通过二维数组找到该矩形覆盖的上下边界,如果对应的bool值为false,则计算这块面积将他加到long数组的对应位置,并将bool值为true。
- 返回long数组总和对1000000007的模。
class Solution {
public:
int rectangleArea(vector<vector<int>>& rectangles) {
long res=0;int i,j,k;
vector<int> xbound;vector<int> ybound;
for(i=0;i<rectangles.size();i++)
{
xbound.push_back(rectangles[i][0]);
xbound.push_back(rectangles[i][2]);
ybound.push_back(rectangles[i][1]);
ybound.push_back(rectangles[i][3]);
}
xbound.erase(unique(xbound.begin(),xbound.end()),xbound.end());
ybound.erase(unique(ybound.begin(),ybound.end()),ybound.end());
sort(xbound.begin(),xbound.end());
sort(ybound.begin(),ybound.end());
sort(rectangles.begin(),rectangles.end());
int NumOfLine=ybound.size()-1;
long area[NumOfLine];
fill(area,area+NumOfLine,0);
vector<vector<int>> lines;
for(i=0;i<rectangles.size();i++)
{
vector<int> temp;
j=0;k=ybound.size()-1;
while(ybound[j]<rectangles[i][1])
j++;
while(ybound[k]>rectangles[i][3])
k--;
while(j<k)
temp.push_back(j++);
lines.push_back(temp);
}
bool flag[NumOfLine];
for(i=0;i<xbound.size()-1;i++)//i表示扫描线
{
fill(flag,flag+NumOfLine,false);
for(j=0;j<rectangles.size();j++)//j标记矩形
{
if(rectangles[j][0]>xbound[i])
break;
if(rectangles[j][2]<=xbound[i])
continue;
for(int y:lines[j])
if(!flag[y])
{
area[y]+=(long)(xbound[i+1]-xbound[i])*(ybound[y+1]-ybound[y]);
flag[y]=true;
}
}/**/
}
for(i=0;i<NumOfLine;i++)
res+=area[i];
return res%1000000007;
}
};