【leetcode】【2022/9/16】850. 矩形面积 II

问题描述:

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

核心思路:

  • 该题是扫描线题目。【扫描线题目其实就是一类区间问题,如官方题解所讲解的那样,扫描线就是一种离散化的技巧,将大范围的连续的坐标转化成离散的坐标
  • 暴力解法其实不难理解。
    • 矩形面积其实就是宽和高,固定宽,进而求每一个不重叠的高。
    • 具体来说,把一个矩形范围视作两个行和两个列(离散化)。
    • 首先,行与行之间的距离就是宽,宽是固定的。
    • 接着,再处理列与列的重叠关系,因为本题数据量较低,暴力法可以直接搜索所有矩形,选出当前宽所囊括的所有矩形,把这些矩形的两个列作为区间存入一个临时数组中,之后把临时数组排序(也就是把区间排序),最后就遍历区间找出所有范围即可,也就是找出当前宽下所有的矩形高。【这里处理列就是扫描线问题,扫描线问题可以用前缀数组来处理】
  • 优化算法就是用线段树处理扫描线部分。【等整理了线段树再重写一下该题】
  • 该题难度不算特别大,考察的东西都比较直接,是扫描线的模板题。

代码实现:

  • 暴力解法代码实现如下:【逻辑来自下面参考内容中的链接】
    class Solution
    {
    public:
        int rectangleArea(vector<vector<int>>& rectangles)
        {
            int MOD = 1e9+7;
    
            // 行的处理,用于求宽
            vector<int> vec; // 行数组
            for(auto& rect : rectangles) // 把 x1 和 x2 存入数组中
                vec.emplace_back(rect[0]), vec.emplace_back(rect[2]);
            sort(vec.begin(), vec.end());
    
            // 列的处理,用于求高,高的处理就是扫描线的处理
            long long ans = 0;
            for(int i = 1; i < vec.size(); ++i)
            {
                int a = vec[i-1], b = vec[i];
                int len = b - a; // 宽
                if(len == 0) continue;
                vector<vector<int>> tmp;
                for(auto& rect : rectangles) // 列的区间
                    if(rect[0] <= a and b <= rect[2]) tmp.push_back({rect[1], rect[3]});
                sort(tmp.begin(), tmp.end(), [&](const vector<int>& a, const vector<int>& b)
                {
                    return a[0] == b[0] ? a[1] < b[1] : a[0] < b[0];
                });
                long long cnt = 0, l = -1, r = -1; // 前一个区间
                for(auto& cur : tmp)
                {
                    if(cur[0] > r) // 没有重叠
                    {
                        cnt += r - l;
                        l = cur[0], r = cur[1];
                    }
                    else if(cur[1] > r) // 重叠,更新区间的右边界
                        r = cur[1];
                }
                cnt += r - l;
                ans += cnt * len;
                ans %= MOD;
            }
            return (int)ans;
        }
    };
    

参考内容:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值