题解

启发式解法-矩形分解

思路

因为多个矩形重叠部分的面积只需要计算一次,因此可以想到将重叠的多个矩形转化为多个不重叠的矩形,最后通过计算不重叠矩形中所有的矩形面积得到答案。
所需要的前置知识,针对任意两个矩形rec1, rec2

  1. 判断两个矩形是否重叠。两个矩形不重叠的条件为:rec1.x1 >= rec2.x2 || rec2.x1 >= rec1.x2 || rec1.y1 >= rec2.y2 || rec2.y1 >= rec1.y2,当满足其中至少一个条件时,说明一个矩形在另一个矩形的四周,不重叠。
  2. 当两个矩形重叠时,重叠部分也是一个矩形。设该矩形的坐标为:(ox1, oy1, ox2, oy2),有:
    ox1 = max(rec1.x1, rec2.x1)
    ox2 = min(rec1.x2, rec2.x2)
    oy1 = max(rec1,y1, rec2,y1)
    oy2 = min(rec1.y2, rec2.y2)

笔者最开始的想法为:
遍历给定的矩形数组,与之前所有的矩形判断一次是否重叠,若重叠,则减去重叠部分的面积。但这里会存在问题,因为减去重叠部分可能是之前矩形公共的部分,只需要减一次,但这种方法可能会减去多次,所以是错误的。
后参考了该题解受到了启发:python 不知道该叫什么方法。。

思路如下:

  1. 记录一个已知不重叠的矩形列表: unOverlapRectangleList,其中的元素为每个矩形的坐标,可以用对象来存也可以用数组来存,这个随意。该列表的特点就在于其中的矩形都是没有重叠的。
  2. 依次遍历输入的每个矩形rectangle[i],与unOverlapRectangleList中的所有矩形进行判断:
    • 若均不重叠则可以直接将其加入列表unOverlapRectangleList
    • 若与其中的某些矩形有重叠部分,则需要将rectangle[i]进行切分:
      • 将重叠的部分删除
      • 将不重叠的部分切分为多个矩形,并将这些矩形继续与unOverlapRectangleList后续的元素进行判断、切分。
      • rectangle[i]最终会被切分成多个不与unOverlapRectangleList中矩形重叠的小矩形,将这些小矩形加入unOverlapRectangleList中即可。
  3. 计算unOverlapRectangleList中每个矩形的面积,做累加求模,即可得到最后的答案。

那么又引出一个问题:如何将没有重叠的部分切分成多个小矩形呢?

因此:我们考虑矩形有重叠时可能出现的情况

矩形重叠情况

以下所有图中,重叠部分矩形用灰色阴影标出,rectangle[i]使用淡蓝色填充。

两个矩形的坐标为(其实有3个,但是第三个矩形的坐标只用于计算重叠矩形的坐标,后续用不到):

  • rectangle[i]的坐标为:(x1,y1,x2,y2)
  • 重叠矩形overlapRectangle的坐标为:(ox1, oy1, ox2, oy2)

切分只竖直切,水平切也可以,但是不是水平+竖直,否则矩形过多,较为繁杂。

  1. rectangle[i]完全包围了当前判断中的矩形,可以切分出四个小矩形的情况:

通过已知的两个坐标我们可以得到切分出来的四个小矩形的坐标:

  • r1的坐标为:(x1, y1, ox1, y2)
  • r2的坐标为:(ox2, y1, x2, y2)
  • r3的坐标为:(ox1, oy2, ox2, y2)
  • r4的坐标为:(ox1, y1, ox2, oy1)
  1. 可以切分出三个小矩形的情况:

有以下四种,矩形编号仍与情况1中相同

可以发现,r1,r2,r3,r4的坐标仍与情况1中的坐标相同

  • r1的坐标为:(x1, y1, ox1, y2)
  • r2的坐标为:(ox2, y1, x2, y2)
  • r3的坐标为:(ox1, oy2, ox2, y2)
  • r4的坐标为:(ox1, y1, ox2, oy1)

不同的地方在于,每一种情况中只有r1,r2,r3,r4中的其中三个:
如左上图只有r1,r3,r4,其中r2坐标因为ox2 = x2,导致矩形面积为0。因此我们只需要考虑面积不为0的矩形,剩下三种情况同理。

  1. 可以切分出两个小矩形的情况:

同样的,r1,r2,r3,r4的坐标仍与上面的相同

  • r1的坐标为:(x1, y1, ox1, y2)
  • r2的坐标为:(ox2, y1, x2, y2)
  • r3的坐标为:(ox1, oy2, ox2, y2)
  • r4的坐标为:(ox1, y1, ox2, oy1)

而每一种情况中只有r1,r2,r3,r4中的其中两个:
如左上图只有r1,r4,其中r2坐标因为ox2 = x2,导致矩形面积为0;r3的坐标因为oy2=y2,导致面积为0。因此我们只需要考虑面积不为0的矩形,剩下三种情况同理。

  1. 可以切分出一个小矩形的情况:

同样的,r1,r2,r3,r4的坐标仍与上面的相同

  • r1的坐标为:(x1, y1, ox1, y2)
  • r2的坐标为:(ox2, y1, x2, y2)
  • r3的坐标为:(ox1, oy2, ox2, y2)
  • r4的坐标为:(ox1, y1, ox2, oy1)

而每一种情况中只有r1,r2,r3,r4中的其中一个:
如左上图只有r1,其中r2的坐标因为ox2 = x2,导致矩形面积为0;r3的坐标因为oy2 = y2,导致面积为0;r4的坐标因为y1 = oy1,导致面积为0。因此我们只需要考虑面积不为0的矩形,剩下三种情况同理。

  1. 无法切分出小矩形的情况:

这种情况仍可以得到四个矩形r1,r2,r3,r4,坐标与上述计算仍然相同,只是面积均为零,不需要做考虑。

代码实现

通过上述的思路,可以实现代码:

class Rectangle {public int x1;public int x2;public int y1;public int y2;public Rectangle(int x1, int y1, int x2, int y2) {this.x1 = x1;this.y1 = y1;this.x2 = x2;this.y2 = y2;}public long area(){return Rectangle.area(this);}public static long area(Rectangle rectangle){return Rectangle.area(new int[]{rectangle.x1, rectangle.y1, rectangle.x2, rectangle.y2});}public static long area(int[] rec){return (long) (rec[2] - rec[0]) * (rec[3] - rec[1]);}
}public class Solution {public static final int MOD = 1000000007;private List<Rectangle> unOverlapRectangleList = new LinkedList<>();public int rectangleArea(int[][] rectangles) {long ans = 0;int n = rectangles.length;for (int i = 0; i < n; i++) {processOverlapRectangle(new Rectangle(rectangles[i][0], rectangles[i][1],rectangles[i][2],rectangles[i][3]));}for (Rectangle rectangle : unOverlapRectangleList) {ans += rectangle.area();}return (int) (ans % MOD);}private void processOverlapRectangle(Rectangle rectangle){//将当前的矩形切分成与已知矩形不重叠的多个小矩形,直至遍历完所有的已知矩形//最后将切分完的小矩形列表添加到已知矩形列表中List<Rectangle> newRectangles = new LinkedList<>();List<Rectangle> temp = new LinkedList<>();newRectangles.add(rectangle);for (Rectangle existRectangle : unOverlapRectangleList) {for (Rectangle newRectangle : newRectangles) {if (!isOverlap(newRectangle, existRectangle)){//如果没有重叠部分,则添加到暂存的列表中,遍历下一个元素temp.add(newRectangle);continue;}//重叠了,则需要对当前新的矩形进行切分,将重叠部分删去,得到剩余部分的矩形分解//切分的结果为一个列表,其中的矩形元素与已知的矩形不重叠且面积大于0。List<Rectangle> segments = segment(newRectangle, existRectangle);temp.addAll(segments);}//将暂存列表中的所有矩形拿出来作为下一次迭代时判断的新矩形列表newRectangles.clear();newRectangles.addAll(temp);//清空暂存列表temp.clear();}//将切分出来的矩形加入已知不重复的矩形列表中unOverlapRectangleList.addAll(newRectangles);}public List<Rectangle> segment(Rectangle newRectangle, Rectangle existRectangle){//首先得到重叠部分矩形坐标Rectangle overlapRectangle = overlapRectangle(newRectangle, existRectangle);//根据重叠部分的坐标获得四个切分后的矩形LinkedList<Rectangle> segments = new LinkedList<>();segments.add(new Rectangle(newRectangle.x1, newRectangle.y1, overlapRectangle.x1, newRectangle.y2));segments.add(new Rectangle(overlapRectangle.x2, newRectangle.y1, newRectangle.x2, newRectangle.y2));segments.add(new Rectangle(overlapRectangle.x1, overlapRectangle.y2, overlapRectangle.x2, newRectangle.y2));segments.add(new Rectangle(overlapRectangle.x1, newRectangle.y1, overlapRectangle.x2, overlapRectangle.y1));//过滤掉面积为0的矩形return segments.stream().filter(rec-> rec.x1 != rec.x2 && rec.y1 != rec.y2).collect(Collectors.toList());}//判断两个矩形是否有重叠public boolean isOverlap(Rectangle rec1, Rectangle rec2){// xi1 >= xj2 || xj1 >= xi2 || yi1 >= yj2 || yj1 >= yi2// 一个矩形在另外一个矩形四周return !(rec1.x1 >= rec2.x2 || rec2.x1 >= rec1.x2 || rec1.y1 >= rec2.y2 || rec2.y1 >= rec1.y2);}// 得到重叠部分矩形的坐标public Rectangle overlapRectangle(Rectangle rec1, Rectangle rec2){int overLapAreaX1 = Math.max(rec1.x1, rec2.x1);int overLapAreaX2 = Math.min(rec1.x2, rec2.x2);int overLapAreaY1 = Math.max(rec1.y1, rec2.y1);int overLapAreaY2 = Math.min(rec1.y2, rec2.y2);return new Rectangle(overLapAreaX1,overLapAreaY1,overLapAreaX2,overLapAreaY2);}
}

850.矩形面积 II 【矩形的分解】相关推荐

  1. 矩形面积和矩形周长并的模板——来自notonlysuccess

    矩形面积并 hdu1542 Atlantis 题意:矩形面积并 思路:浮点数先要离散化;然后把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用cnt表示该区间下边比上边多几个,sum代 ...

  2. 850. 矩形面积 II:扫描线+离散化+线段树

    Difficulty: hard 标签: 扫描线, 离散化, 线段树 题目链接 力扣 题目解析 面试代码 /** x轴方向使用扫描线,y轴方向使用线段树维护扫描线的长度和每个区间覆盖的次数.由于y轴方 ...

  3. leetcode 850. Rectangle Area II | 850. 矩形面积 II(递归分割未重叠矩形)

    题目 https://leetcode.com/problems/rectangle-area-ii/ 题解 没有看懂官方答案,评论区有一种解法写的挺通俗的: Clean Recursive Solu ...

  4. POJ1177矩形面积并(矩形切割+括号匹配)

    题目:http://poj.org/problem?id=1177 分析:(括号匹配)首先把矩形的上边界作为"左括号"边,下边界作为"右括号"边,然后上下排序. ...

  5. 01矩阵最大正方形面积、01矩阵最大矩形面积、直方图最大矩形面积

    01矩阵最大正方形面积 题意:给定一个矩阵,其中的元素为0或者1,要求找出其中元素全为1的面积最大的正方形. 题解:动态规划:对每个元素,把以其为右下角,元素全为1的正方形的最长边长记录下来.如果以元 ...

  6. 直方图中最大矩形面积

    原文地址:http://www.geeksforgeeks.org/largest-rectangle-under-histogram/ 注意:本文并未对原文完整翻译,而是结合原文并根据本人理解写出, ...

  7. c语言直方图最大矩形面积,直方图中最大矩形面积(示例代码)

    注意:本文并未对原文完整翻译,而是结合原文并根据本人理解写出,因此部分内容为完整翻译,部分内容为个人理解所写. Largest Rectangle in Histogram 直方图中最大矩形面积 一个 ...

  8. sdut 2401 最大矩形面积

    1http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2401 /* 2 最大矩形面积,把边界点加上 ...

  9. 语音计算矩形面积_LeetCode85-最大矩形

    今天在制作书签的时候 突然想到了一个问题 如果要送给未来的女朋友一个书签 上面该写些什么话 哈哈哈哈哈哈哈哈哈 The Spring is coming! 想了一会儿,觉得这句话最合适 To xxx: ...

最新文章

  1. 2020年,图机器学习的趋势有哪些?
  2. 从属关系mysql_关系型数据库基础概念:MySQL系列之开篇
  3. python3爬虫系列教程-Python3爬虫视频学习教程
  4. WebView显示的网页在大分辨率屏下被放大--解决方案
  5. 深入浅出 PouchContainer 容器化业务实践 Workshop 开放报名
  6. Mybatis之设计模式之装饰者模式
  7. c 设计计算机报告,C课程设计(计算器)报告
  8. 把杀某程序封装成sh
  9. Android开发笔记(一百七十二)第二代翻页视图ViewPager2
  10. [POJ2195]Going Home(带权最大匹配,KM,最小费用流)
  11. 极简网关认证方案:诞生于国科大的“认证博士”
  12. 计算机病毒有几个阶段,计算机病毒发展9阶段
  13. java keytool 导出证书,keytool 导出证书
  14. 基于wincc的虚拟电梯设计_基于WinCC的电梯PLC控制仿真.doc
  15. c语言公开课教案,9、祝福优质课一等奖教案
  16. javamail解析邮件,内容重复
  17. Flutter 全能型选手GetX —— 路由管理
  18. 第一天,初了解锐捷网络
  19. ORA-00937: 不是单组分组函数
  20. Linux运维精华面试题

热门文章

  1. 软件测试人员应该怎样做好需求分析
  2. python 一亩三分地_攻防世界逆向新手训练
  3. 引流,引流脚本,引流软件
  4. ArcGIS标注图斑四至
  5. 搜集的一些机器学习和数据挖掘的实践项目
  6. 众筹创业资金,他成了“地瓜王子”,收入十分可观
  7. QTP对于支付宝控件无法录制的问题解决
  8. SLAM中的三角测量
  9. 详述激光三角测距法原理
  10. 解决在高分屏电脑上运行Photoshop CS6,程序界面字体过小的问题