入门力扣自学笔记151 C++ (题目编号850)

850. 矩形面积 II

题目:

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

计算平面中所有 rectangles 所覆盖的 总面积 。任何被两个或多个矩形覆盖的区域应只计算 一次 。

返回 总面积 。因为答案可能太大,返回 109 + 7 的 模 。


示例 1:

输入:rectangles = [[0,0,2,2],[1,0,2,3],[1,0,3,1]]
输出:6
解释:如图所示,三个矩形覆盖了总面积为6的区域。
从(1,1)到(2,2),绿色矩形和红色矩形重叠。
从(1,0)到(2,3),三个矩形都重叠。


示例 2:

输入:rectangles = [[0,0,1000000000,1000000000]]
输出:49
解释:答案是 1018 对 (109 + 7) 取模的结果, 即 49 。


提示:

1 <= rectangles.length <= 200
rectanges[i].length = 4
0 <= xi1, yi1, xi2, yi2 <= 109
矩形叠加覆盖后的总面积不会超越 2^63 - 1 ,这意味着可以用一个 64 位有符号整数来保存面积结果。


来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/rectangle-area-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思路:

本质题目其实就是去计算面积,那么其实问题并不难

从下往上扫描,计算每一段之间的最大宽度,那么y的差值乘以宽度就是面积
为了扫描计算的准确,需要额外辅助
需要按照y排序,从小到大
需要对于当前区间内的范围x也进行排序,考虑x范围会有重复用一个multiset来保存
对于离开区间需要删除multiset里的key,进入则插入key
计算时候从x1,x2里x1小的开始计算,这样子就能算出最大的宽度,参见函数 QueryWidth


代码:

class Solution 
{
private:
    const static int MOD = 1e9 + 7;
    const static int OPEN = 0;
    const static int CLOSE = 1;

    // 计算宽度:其实就是不断累加更大的x的差值即可
    int QueryWidth(multiset<pair<int,int>>& activate)
    {
        int res = 0;
        int maxX = -1;
        for (auto [x1, x2] : activate)
        {
            maxX = max(maxX, x1);
            // 如果x变大了,则计算差值累加更大的宽度
            res += max(0, x2 - maxX);
            // 不断更新最大x
            maxX = max(maxX, x2);
        }
        return res;
    }

public:
    int rectangleArea(vector<vector<int>>& rectangles) 
    {
        vector<vector<int>> rec;
        for (auto v: rectangles)
        {
            rec.push_back({v[1], OPEN, v[0], v[2]});
            rec.push_back({v[3], CLOSE, v[0], v[2]});
        }
        // 排序从下到上来扫描
        sort(rec.begin(), rec.end());
        
        // 存储面积和
        int res = 0;
        // 初始化第一个y的位置
        int lastY = rec[0][0];
        // 当前需要计算的面积横坐标 [x1,x2]
        // 扫描过程中 对于每次OPEN则插入,CLOSE则删除
        multiset<pair<int,int>> activate;

        for (const vector<int> r : rec)
        {
            int y = r[0];
            int state = r[1];
            int x1 = r[2];
            int x2 = r[3];

            // 累加面积
            res = (res + (long long)QueryWidth(activate)*(y-lastY)) % MOD;
            // 更新上一个y坐标
            lastY = y;
            // 对于每次OPEN则插入,CLOSE则删除
            if (state == OPEN)
            {
                activate.insert({x1, x2});
            }
            else
            {
                activate.erase(activate.find(pair<int,int>{x1, x2}) );
            }
        }

        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值