当前位置: 首页 > article >正文

力扣.223 矩形面积 rectangle-area

题目

给你 二维 平面上两个 由直线构成且边与坐标轴平行/垂直 的矩形,请你计算并返回两个矩形覆盖的总面积。

每个矩形由其 左下 顶点和 右上 顶点坐标表示:

第一个矩形由其左下顶点 (ax1, ay1) 和右上顶点 (ax2, ay2) 定义。 第二个矩形由其左下顶点 (bx1, by1) 和右上顶点 (bx2, by2) 定义。

示例 1:

Rectangle Area 输入:ax1 = -3, ay1 = 0, ax2 = 3, ay2 = 4, bx1 = 0, by1 = -1, bx2 = 9, by2 = 2 输出:45 示例 2:

输入:ax1 = -2, ay1 = -2, ax2 = 2, ay2 = 2, bx1 = -2, by1 = -2, bx2 = 2, by2 = 2 输出:16

提示:

-10^4 <= ax1, ay1, ax2, ay2, bx1, by1, bx2, by2 <= 10^4

v1-重叠面积

思路

如果矩形不重叠,就是 2 个矩形的面积之和。

如果重合,计算出重叠面积,就是原始的面积之和-重叠面积。

如果两个矩形重叠,那么重叠的面积一定大于0.

于是问题变成如何计算重叠的矩形面积?

二维

如果有重叠,重叠的部分也一定是一个矩形

交集面积的计算方式是基于两个矩形的重叠区域的 左下角和右上角的坐标 来推算的。

具体来说,两个矩形的交集矩形(如果存在)也是一个矩形,它的边界由两个矩形的边界决定。

计算重叠面积

  • 第一个矩形 rec1 = [x1, y1, x2, y2],表示其左下角坐标为 (x1, y1),右上角坐标为 (x2, y2)

  • 第二个矩形 rec2 = [x3, y3, x4, y4],表示其左下角坐标为 (x3, y3),右上角坐标为 (x4, y4)

如果两个矩形有交集,那么交集的矩形的左下角和右上角的坐标可以通过取两者的最大和最小值来确定:

  • 交集矩形的左下角(x1', y1') = (max(x1, x3), max(y1, y3))

  • 交集矩形的右上角(x2', y2') = (min(x2, x4), min(y2, y4))

判断交集是否存在

交集矩形的面积只有在其宽度和高度都大于 0 时才存在。

如果交集矩形的宽度或高度小于等于 0,说明两个矩形没有交集。

因此,交集矩形的宽度和高度的计算方式如下:

  • 宽度:width = x2' - x1'
  • 高度:height = y2' - y1'

交集矩形的面积则为:

  • 面积 = width * height,但是如果宽度或高度小于等于 0,面积就为 0。

因此,计算交集的面积时,我们需要确保 width > 0height > 0,否则交集的面积为 0。

结果

完整的面积 = 两个矩形面积之和 - 重叠面积

代码示例

class Solution {
    public int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
        int rect1 = rectangleArea(ax1, ay1, ax2, ay2);
        int rect2 = rectangleArea(bx1, by1, bx2, by2);

        int overlap = rectangleOverlapArea(new int[]{ax1, ay1, ax2, ay2}, new int[]{bx1, by1, bx2, by2});

        return rect1-overlap+rect2;
    }

    private int rectangleArea(int ax1, int ay1, int ax2, int ay2) {
        return (ax2-ax1) * (ay2-ay1);
    }

    public int rectangleOverlapArea(int[] rec1, int[] rec2) {
        // 计算交集矩形的左下角和右上角
        int x1 = Math.max(rec1[0], rec2[0]);
        int y1 = Math.max(rec1[1], rec2[1]);
        int x2 = Math.min(rec1[2], rec2[2]);
        int y2 = Math.min(rec1[3], rec2[3]);

        // 计算交集的宽度和高度
        int width = x2 - x1;
        int height = y2 - y1;

        // 如果交集的宽度和高度都大于 0,说明有重叠
        if (width > 0 && height > 0) {
            return width * height;
        }

        // 没有重叠
        return 0;
    }
}

效果

2ms 击败21.43%

小结

这种解法相对对比较自然。

v2-扫描线

二维

思路

按照 x 轴,将整体的矩形面积,按照每一段 x 拆分为小矩形。

最后的和就是整体矩形之和。

解法

public int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
    int[][] arr = new int[2][];
    arr[0] = new int[]{ax1, ay1, ax2, ay2};
    arr[1] = new int[]{bx1, by1, bx2, by2};
    Arrays.sort(arr, (o1, o2) -> o1[1] == o2[1] ? o1[3] - o2[3] : o1[1] - o2[1]);
    List<Integer> xList = Arrays.asList(ax1, ax2, bx1, bx2);
    Collections.sort(xList);
    int ans = 0;
    for (int i = 1; i < 4; i++) {
        int width = xList.get(i) - xList.get(i-1);
        for (int[] ints : getLine(xList.get(i-1), xList.get(i), arr)) {
            ans += width * (ints[1] - ints[0]);
        }
    }
    return ans;
}

private List<int[]> getLine(int x1, int x2, int[][] arr) {
    List<int[]> list = new ArrayList<>();
    for (int[] ints : arr) {
        if (x1 >= ints[0] && x2 <= ints[2]) {
            if (list.isEmpty()) {
                list.add(new int[]{ints[1], ints[3]});
            } else {
                int[] tmp = list.get(list.size() - 1);
                if (tmp[1] < ints[1]) {
                    list.add(new int[]{ints[1], ints[3]});
                } else if (tmp[1] < ints[3]) {
                    tmp[1] = ints[3];
                }
            }
        }
    }
    return list;
}

效果

6ms 击败 4.76%

小结

整体上而言,我比较喜欢重叠面积的方式,这种比较好想到,而且可以扩展。

当然扫描线也是一种很通用的解法。

这一题的巧思属于维度投影的解法,很巧妙。

开源地址

为了便于大家学习,所有实现均已开源。欢迎 fork + star~

https://github.com/houbb/leetcode

LOGIN

扫描线专题

leetcode 扫描线专题 06-扫描线算法(Sweep Line Algorithm)

leetcode 扫描线专题 06-leetcode.218 the-skyline-problem 力扣.218 天际线问题

leetcode 扫描线专题 06-leetcode.252 meeting room 力扣.252 会议室

leetcode 扫描线专题 06-leetcode.253 meeting room ii 力扣.253 会议室 II

leetcode 扫描线专题 06-leetcode.1851 minimum-interval-to-include-each-query 力扣.1851 包含每个查询的最小区间

leetcode 扫描线专题 06-leetcode.223 rectangle-area 力扣.223 矩形面积

leetcode 扫描线专题 06-leetcode.3047 find-the-largest-area-of-square-inside-two-rectangles 力扣.3047 求交集区域的最大正方形面积

leetcode 扫描线专题 06-leetcode.391 perfect-rectangle 力扣.391 完美矩形

leetcode 扫描线专题 06-leetcode.836 rectangle-overlap 力扣.836 矩形重叠

leetcode 扫描线专题 06-leetcode.850 rectangle-area 力扣.850 矩形面积 II


http://www.kler.cn/a/401998.html

相关文章:

  • 软件测试之测试用例扩展
  • 小鹏汽车大数据面试题及参考答案
  • 联通光猫(烽火通信设备)改桥接教程
  • 5G的SUCI、SUPI、5G-GUTI使用场景及关系
  • 智谱AI清影升级:引领AI视频进入音效新时代
  • Relaxcert SSL证书申请与自动续签之IIS
  • Github 2024-11-19 Python开源项目日报 Top9
  • Ubuntu Linux使用前准备动作 配置SSH
  • SQL 语句基础与实用技巧(DDL DML)
  • CH03_反射
  • 基于信号量与共享内存实现客户与服务器进程通信
  • Efficient One-stage Video Object Detection byExploiting Temporal Consistency
  • 数据结构——AVL树
  • python: generator IDAL and DAL using sql server 2019
  • 时间类的实现
  • 【Flutter 问题系列第 84 篇】如何清除指定网络图片的缓存
  • sql数据库-权限控制-DCL
  • 第二十四章 TCP 客户端 服务器通信 - 当前 TCP 设备
  • 大公司如何实现打印机共享的?如何对打印机进行管控或者工号登录后进行打印?异地打印机共享的如何实现可以帮助用户在不同地理位置使用同一台打印机完成打印任务?
  • 【LeetCode面试150】——49字母异位分词
  • PHP进阶-CentOS7部署LNMP服务架构的项目
  • 【苍穹外卖】学习日志-day1
  • 网络安全常见练习靶场
  • 使用ajax-hook修改http请求响应数据,篡改后再返回给正常的程序
  • 【Docker】快速部署 Pikachu:一个包含常见 Web 安全漏洞的渗透测试练习靶场
  • C++系列之继承