力扣 391. 完美矩形

该博客主要探讨了一个算法问题,即如何判断一组给定的矩阵坐标是否能完整无重叠地拼成一个大矩阵。关键在于检查小矩阵的面积和、大矩阵的边界坐标以及所有坐标出现的次数。通过遍历所有小矩阵,统计面积和、更新大矩阵坐标及坐标出现次数,最后验证面积和、坐标出现次数的合理性来实现判断。

题目来源:https://leetcode-cn.com/problems/perfect-rectangle/

大致题意:
给定一组矩阵的坐标(左下角和右上角),判断这些矩阵是否完整的拼成另一个大矩阵,并且不能有重合
如:
在这里插入图片描述

思路

若想让给定的小矩阵组成大矩阵,需要满足以下条件:

  • 小矩阵的面积和等于大矩阵的面积
  • 可知每个矩阵有四个角,大矩阵由小矩阵组成,在小矩阵的所有角的坐标中,构成大矩阵的角的坐标只出现一次(否则会有重叠),而大矩阵内部的小矩阵的角坐标出现次数为 2 或 4。若为其它数,则一定是大矩阵内部有小矩阵未覆盖的区域,或者是有小矩阵重叠
    在这里插入图片描述

于是可以通过遍历所有小矩阵,做以下操作:

  • 统计小矩阵面积和
  • 求出大矩阵的角坐标
  • 求出所有小矩阵角坐标的出现次数

然后做以下判断:

  • 大矩阵的面积是否等于小矩阵面积和
  • 出现 1 次的坐标是不是边界坐标
  • 其他坐标是不是出现 2 次或者 4 次

代码:

public boolean isRectangleCover(int[][] rectangles) {
        // 大矩阵的左下角和右上角坐标
        int leftBottomX = rectangles[0][0];
        int leftBottomY = rectangles[0][1];
        int rightTopX = rectangles[0][2];
        int rightTopY = rectangles[0][3];
        int areaSum = 0;
        // 存坐标出现的次数
        Map<String, Integer> point = new HashMap<>();
        // 遍历小矩阵
        for (int[] rectangle : rectangles) {
            // 取出坐标
            int x1 = rectangle[0];
            int y1 = rectangle[1];
            int x2 = rectangle[2];
            int y2 = rectangle[3];
            // 更新大矩阵的坐标
            leftBottomX = Math.min(leftBottomX, x1);
            leftBottomY = Math.min(leftBottomY, y1);
            rightTopX = Math.max(rightTopX, x2);
            rightTopY = Math.max(rightTopY, y2);
            // 统计面积和
            areaSum += (x2 - x1) * (y2 - y1);
            // 统计坐标出现次数
            String leftTop = point(x1, y2);
            String leftBottom = point(x1, y1);
            String rightTop = point(x2, y2);
            String rightBottom = point(x2, y1);
            point.put(leftBottom, point.getOrDefault(leftBottom, 0) + 1);
            point.put(leftTop, point.getOrDefault(leftTop, 0) + 1);
            point.put(rightBottom, point.getOrDefault(rightBottom, 0) + 1);
            point.put(rightTop, point.getOrDefault(rightTop, 0) + 1);
        }
        int area = (rightTopX - leftBottomX) * (rightTopY - leftBottomY);
        // 面积和是否等于大矩阵面积
        if (area != areaSum) {
            return false;
        }
        // 判断坐标出现次数是否合理
        for (Map.Entry<String, Integer> entry : point.entrySet()) {
            String[] curPoint = entry.getKey().split(",");
            int x = Integer.valueOf(curPoint[0]);
            int y = Integer.valueOf(curPoint[1]);
            int count = entry.getValue();
            switch (count) {
                case 1:
                    // 出现 1 次时,若不是大矩阵角坐标
                    if (!((x == leftBottomX && y == leftBottomY) || (x == leftBottomX && y == rightTopY) ||
                            (x == rightTopX && y == rightTopY) || (x == rightTopX && y == leftBottomY))) {
                        return false;
                    }
                    break;
                case 2:
                    // 出现 2 次时,若是大矩阵角坐标
                    if ((x == leftBottomX && y == leftBottomY) || (x == leftBottomX && y == rightTopY) ||
                            (x == rightTopX && y == rightTopY) || (x == rightTopX && y == leftBottomY)) {
                        return false;
                    }
                    break;
                case 4:
                    break;
                default:
                    return false;
            }
        }
        return true;
    }
    // 将坐标转化为字符串
    public String point(int x, int y) {
        return String.format("%d,%d", x, y);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

三更鬼

谢谢老板!

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

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

打赏作者

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

抵扣说明:

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

余额充值