力扣 391. 完美矩形

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/perfect-rectangle

给你一个数组 rectangles ,其中 rectangles[i] = [xi, yi, ai, bi] 表示一个坐标轴平行的矩形。这个矩形的左下顶点是 (xi, yi) ,右上顶点是 (ai, bi) 。

如果所有矩形一起精确覆盖了某个矩形区域,则返回 true ;否则,返回 false 。

哈希表

精确覆盖意味着:

  • 矩形区域中不能有空缺,即矩形区域的面积等于所有矩形的面积之和;
  • 矩形区域中不能有相交区域

思路:

 

class Solution {
    public boolean isRectangleCover(int[][] rectangles) {
        // 计算每个小矩形面积是否等于大矩形面积
        // 看每个顶点出现的次数,如果最后出现一次的顶点不是四个,则说明不符合完美矩形
        int area = 0;
        Set<Integer> set = new HashSet<>();
        // 记录大矩形的左下角和右上角
        int a1 = Integer.MAX_VALUE, b1 = Integer.MAX_VALUE;
        int a2 = Integer.MIN_VALUE, b2 = Integer.MIN_VALUE;

        for (int[] rec : rectangles) {
            // 小矩形的坐标
            int x1 = rec[0];
            int y1 = rec[1];
            int x2 = rec[2];
            int y2 = rec[3];

            // 计算左下角
            if (x1 < a1 || y1 < b1) {
                a1 = x1;
                b1 = y1;
            }

            // 计算右上角
            if (x2 > a2 || y2 > b2) {
                a2 = x2;
                b2 = y2;
            }

            // 计算面积
            area += (x2 - x1) * (y2 - y1);

            // 记录每个顶点出现的次数
            record(set, x1, y1);
            record(set, x1, y2);
            record(set, x2, y1);
            record(set, x2, y2);
        }

        // 通过左下角和右上角坐标可以算出总面积
        int totalArea = (a2 - a1) * (b2 - b1);

        // 如果两个面积不相等,直接返回false
        if (area != totalArea) return false;
        
        // 四个为1的顶点正好是大矩形的四个顶点
        return set.size() == 4 && set.contains(key(a1, b1)) && set.contains(key(a1, b2)) && set.contains(key(a2, b1)) && set.contains(key(a2, b2));
    }

    private void record(Set<Integer> set, int x, int y) {
        // 记录顶点出现的次数,如果一个顶点出现偶数次,则移除
        int key = key(x, y);
        if (set.contains(key)) {
            set.remove(key);
        } else {
            set.add(key);
        }
    }

    private int key(int x, int y) {
        // 二维坐标转一维,方便比较
        // 100000007是随便取的一个大质数
        // 这里即使溢出了也没什么问题
        return x * 100000007 + y;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值