笔试题(十六):计算矩阵面积

# 我们给出了一个(轴对齐的)二维矩形列表 rectangles。
# 对于 rectangle[i] = [xi1, yi1, xi2, yi2],表示第i个矩形的坐标, 
# (xi1, yi1)是该矩形左下角的坐标, (xi2, yi2)是该矩形右上角的坐标。
# 计算平面中所有 rectangles 所覆盖的总面积。任何被两个或多个矩形覆盖的区域应只计算一次。
# 返回总面积。因为答案可能太大,返回 10^9 + 7 的模。


 # 方法一:找出所有重叠的部分,所有图形总面积减去重叠的部分就是总面积def cal_measure(rectangles):   
    sum_all = 0
    re0 = rectangles[0]
    sum_all += (re0[2] - re0[0]) * (re0[3] - re0[1])  # 总面积
    if len(rectangles) < 2:
        return sum_all % (10 ** 9 + 7)
    for i in range(len(rectangles) - 1):
        re1 = rectangles[i]
        for j in range(i + 1, len(rectangles)):
            duplicate = []
            re2 = rectangles[j]
            sum_all += (re2[2] - re2[0]) * (re2[3] - re2[1])
            if re2[0] > re1[0]:
                duplicate.append(re2[0] - re1[0])
            else:
                duplicate.append(re1[0] - re2[0])
            if re2[1] > re1[1]:
                duplicate.append(re2[1] - re1[1])
            else:
                duplicate.append(re1[1] - re2[1])
            if re2[2] > re1[2]:
                duplicate.append(re1[2])
            else:
                duplicate.append(re2[2])
            if re2[3] > re1[3]:
                duplicate.append(re1[3])
            else:
                duplicate.append(re2[3])
            sum_all -= (duplicate[2] - duplicate[0]) * (duplicate[3] - duplicate[1])
    return sum_all % (10 ** 9 + 7)


 # 方法二:将所有给定的矩形的左右边对应的 x 端点提取出来并排序,每个端点可看作是一条竖直的线段(红色),问题转换为求解「由多条竖直线段分割开」的多个矩形的面积总和(黄色)

from more_itertools import pairwise
from typing import List
MOD = int(1e9 + 7)
def rectangleArea(rectangles: List[List[int]]) -> int:
    xs, ans = set(), 0
    for x0, _, x1, _ in rectangles:
        xs.add(x0)
        xs.add(x1)
    # 纵向x轴扫描线
    for a, b in pairwise(sorted(xs)):  # xs为所有的x轴扫描线
        ys = [(y0, y1) for x0, y0, x1, y1 in rectangles if x0 <= a and b <= x1]  # 获得a,b扫描线之间的纵向坐标
        s = cur = 0
        # 横向y轴扫描线
        for c, d in sorted(ys, key=lambda x: (x[0], -x[1])):  # 按y0升序,按y1降序
            if c > cur:
                s += d - c  # 总高度
            elif d > cur:
                s += d - cur
            cur = max(cur, d)  # 记录当前已计算高度
        ans = (ans + s * (b - a)) % MOD
    return ans


if __name__ == '__main__':
    rectangles = [[0, 0, 2, 2], [1, 0, 2, 3], [1, 0, 3, 1]]
    rectangles2 = [[0, 0, 1000000000, 1000000000]]
    print(cal_measure(rectangles))
    print(cal_measure(rectangles2))
    print(rectangleArea(rectangles))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Trisyp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值