• 扫描线+离散化 计算矩形面积


    我们给出了一个(轴对齐的)二维矩形列表 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐标, (xi1, yi1) 是该矩形 左下角 的坐标, (xi2, yi2) 是该矩形 右上角 的坐标。

    计算平面中所有 rectangles 所覆盖的 总面积 。任何被两个或多个矩形覆盖的区域应只计算 一次 。返回 总面积 。因为答案可能太大,返回 10^9 + 7 的 模 。

    i​​​​​​LeetCode链接

    思路:

    我的第一反应是计算所有矩形面积,然后减去两两相交的面积。这种做法是错误的因为每个重叠部分只要减去一次,可能会重复减去。

    这道题的正确思路是把整个区域按所有矩形的边界进行划分,然后逐个计算分块的面积。

    步骤:

    • 把所有矩形的左右边存到一个数组和上下边存到另一个数组,分别将它们去重,然后排序。此时得到的按从左到右和从上到下的排列边界,它们将整个区域划分为了一条条横纵排列的线段,线段组成了一个个小矩形。
    • 按左界排序矩阵。这步是为了接下来从左到右扫描做准备。
    • 创建一个二维数组,其长度等于矩形数量。其中的每个一维数组存储该矩形覆盖的上下边界的分割的线段。这步是为了之后遍历矩形时能快速地找到它覆盖的区域。
    • 创建一个长度等于上下边界-1的bool数组。它的作用是标记在本次扫描中某块区域是否已经被覆盖。
    • 创建一个与bool数组长度相同的long数组,用来存放该区域已经覆盖的总面积。
    • 从左到右遍历左右边界,每次循环时将bool数组全部值为false,在循环中遍历所有覆盖了该边界的矩形,通过二维数组找到该矩形覆盖的上下边界,如果对应的bool值为false,则计算这块面积将他加到long数组的对应位置,并将bool值为true。
    • 返回long数组总和对1000000007的模。
    1. class Solution {
    2. public:
    3. int rectangleArea(vectorint>>& rectangles) {
    4. long res=0;int i,j,k;
    5. vector<int> xbound;vector<int> ybound;
    6. for(i=0;isize();i++)
    7. {
    8. xbound.push_back(rectangles[i][0]);
    9. xbound.push_back(rectangles[i][2]);
    10. ybound.push_back(rectangles[i][1]);
    11. ybound.push_back(rectangles[i][3]);
    12. }
    13. xbound.erase(unique(xbound.begin(),xbound.end()),xbound.end());
    14. ybound.erase(unique(ybound.begin(),ybound.end()),ybound.end());
    15. sort(xbound.begin(),xbound.end());
    16. sort(ybound.begin(),ybound.end());
    17. sort(rectangles.begin(),rectangles.end());
    18. int NumOfLine=ybound.size()-1;
    19. long area[NumOfLine];
    20. fill(area,area+NumOfLine,0);
    21. vectorint>> lines;
    22. for(i=0;isize();i++)
    23. {
    24. vector<int> temp;
    25. j=0;k=ybound.size()-1;
    26. while(ybound[j]1])
    27. j++;
    28. while(ybound[k]>rectangles[i][3])
    29. k--;
    30. while(j
    31. temp.push_back(j++);
    32. lines.push_back(temp);
    33. }
    34. bool flag[NumOfLine];
    35. for(i=0;isize()-1;i++)//i表示扫描线
    36. {
    37. fill(flag,flag+NumOfLine,false);
    38. for(j=0;jsize();j++)//j标记矩形
    39. {
    40. if(rectangles[j][0]>xbound[i])
    41. break;
    42. if(rectangles[j][2]<=xbound[i])
    43. continue;
    44. for(int y:lines[j])
    45. if(!flag[y])
    46. {
    47. area[y]+=(long)(xbound[i+1]-xbound[i])*(ybound[y+1]-ybound[y]);
    48. flag[y]=true;
    49. }
    50. }/**/
    51. }
    52. for(i=0;i
    53. res+=area[i];
    54. return res%1000000007;
    55. }
    56. };

  • 相关阅读:
    2022年9月2日:面向初学者的 web 开发--使用 JavaScript 制定决策
    Rust 技术文档及详细使用命令
    Arduino ESP8266/32 自定义IO组网页状态显示与控制
    基于Qt实现的可视化大屏监控
    运维排查 | Systemd 之服务停止后状态为 failed
    牛客网项目-开发注册功能
    蓝牙资讯|三星推迟发布智能戒指Galaxy Ring,智能穿戴小型化是大趋势
    CSMACD协议与CSMACA协议
    保研后,你们都怎么样了?
    孕妇胃烧心是胎儿长头发?其实是因为这2点
  • 原文地址:https://blog.csdn.net/qq_43533956/article/details/126911288