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

详细介绍:LeetCode 391 完美矩形

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 代码解析
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

在做矩形覆盖的题目时,很多人第一反应就是「遍历 + 合并区间」,但 LeetCode 的 完美矩形 题目可没那么简单。它不仅要求所有小矩形刚好拼出一个大矩形,而且不能有重叠、不能有缝隙,就像拼图一样必须严丝合缝。本文会带你逐步拆解问题,分析为什么简单的遍历不够用,并给出一个基于 面积校验 + 顶点校验 的高效解法。

描述

题目给你一组小矩形,每个矩形由左下角 (xi, yi) 和右上角 (ai, bi) 表示,矩形都是和坐标轴平行的。现在你要判断这些矩形是否能 完美拼接成一个更大的矩形

判断标准主要有两个:

  1. 拼接后的整体区域必须是一个完整的大矩形。
  2. 小矩形之间不能重叠,也不能留下空隙。

换句话说,我们不仅要保证拼出来的总面积等于大矩形的面积,还要保证小矩形的边界刚好吻合。

实际场景类比:
可以想象一下装修时铺瓷砖:如果你要用一堆小方砖铺满一个长方形的地板,那么这堆砖必须正好覆盖整个地板,不能多也不能少,更不能有两块砖重叠。

题解答案

核心思路是 面积校验 + 顶点唯一性

  1. 面积校验:所有小矩形的面积和必须等于大矩形的面积。
  2. 顶点校验:大矩形的四个顶点必须只出现一次,其它所有中间拼接的点必须出现偶数次(因为它们会被相邻矩形共享)。

一旦两个条件同时满足,就说明所有矩形能完美拼成一个大矩形。

题解代码分析

下面是完整的 Swift 实现代码:

import Foundation
class PerfectRectangle {
func isRectangleCover(_ rectangles: [[Int]]) -> Bool {
var minX = Int.max, minY = Int.max
var maxX = Int.min, maxY = Int.min
var areaSum = 0
var points = Set<String>()func addOrRemovePoint(_ x: Int, _ y: Int) {let key = "\(x),\(y)"if points.contains(key) {points.remove(key)} else {points.insert(key)}}for rect in rectangles {let x1 = rect[0], y1 = rect[1]let x2 = rect[2], y2 = rect[3]// 更新外接矩形边界minX = min(minX, x1)minY = min(minY, y1)maxX = max(maxX, x2)maxY = max(maxY, y2)// 累加面积areaSum += (x2 - x1) * (y2 - y1)// 处理矩形四个顶点addOrRemovePoint(x1, y1)addOrRemovePoint(x1, y2)addOrRemovePoint(x2, y1)addOrRemovePoint(x2, y2)}// 计算外接矩形的面积let expectedArea = (maxX - minX) * (maxY - minY)if areaSum != expectedArea {return false}// 外接矩形的四个顶点let expectedPoints = ["\(minX),\(minY)","\(minX),\(maxY)","\(maxX),\(minY)","\(maxX),\(maxY)"]// 校验点集合是否只剩下四个顶点if points.count != 4 {return false}for p in expectedPoints {if !points.contains(p) {return false}}return true}}

代码解析

  1. 边界计算:通过遍历所有矩形,记录整个覆盖区域的最小 (x, y) 和最大 (x, y),得到大矩形的外接边界。

  2. 面积验证:小矩形的面积总和必须和外接矩形的面积一致。

  3. 顶点处理

    • 对每个小矩形的四个顶点执行「异或」式的操作:如果顶点第一次出现就加入集合,如果再次出现就删除。
    • 最终应该只剩下外接矩形的四个顶点。
  4. 返回结果:如果面积对上,顶点集合正确,就返回 true

示例测试及结果

let solver = PerfectRectangle()
print(solver.isRectangleCover([[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]]))
// 输出: true
print(solver.isRectangleCover([[1,1,2,3],[1,3,2,4],[3,1,4,2],[3,2,4,4]]))
// 输出: false
print(solver.isRectangleCover([[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]]))
// 输出: false

结果解释:

  • 第一个示例,小矩形严丝合缝拼成大矩形,返回 true
  • 第二个示例有间隙,返回 false
  • 第三个示例有重叠,返回 false

时间复杂度

  • 遍历所有矩形一次,每个矩形只处理 4 个顶点。
  • 时间复杂度为 O(n),其中 n 是矩形的数量。

空间复杂度

总结

这道题如果直接用模拟的方法去拼接,复杂度会非常高,尤其是 n 可以达到两万的时候,根本不可行。

真正的突破点在于 把二维覆盖问题转化成面积 + 顶点唯一性验证

  • 面积保证了整体没有缝隙;
  • 顶点唯一性保证了没有重叠。

这种解法思路非常优雅,既避免了暴力模拟,又保证了正确性。日常开发中,如果你遇到「多个区域拼接是否能完美组成大区域」的需求,比如地图划分、UI 布局检查,其实也可以借鉴这种「全局面积 + 局部边界」的思路来解决。

http://www.zskr.cn/news/15650.html

相关文章:

  • 实用指南:Transformer模型:深度解析自然语言处理的革命性架构——从预训练范式到产业级实践
  • Flutter + Ollama:开启本地AI的全平台新纪元 —— 从零剖析一款现代化AI客户端的技能奥秘
  • 股票资料API接口全解析:从技术原理到多语言实战(含实时行情、MACD、KDJ等技术指标数据与API文档详解)
  • 实用指南:开源 C# 快速开发(十四)进程--内存映射
  • 实用指南:ArcGIS JSAPI 高级教程 - 高亮效果优化之开启使用多高亮样式
  • 10月北京中学集训随笔
  • 使用100%缩放比例重新启动Visual Studio 界面模糊的解决方案
  • 4_查询flutter版本信息
  • 3_flutter简单教程
  • 2_gradle配置加速
  • 九月回忆
  • US$88 BW9 Key Clamp SN-CP-JJ-15 for BMW Motor Keys for SEC-E9 Key Cutting Machine
  • 数论中的欧拉函数
  • 何为“类”?(Java基础语法) - 教程
  • NOI 七
  • 三霍尔BLDC——已知霍尔元件输出与相线输入电压的关系表,如何写程序
  • ZSH 安装配置
  • Spring事务管理:-rollbackFor
  • 微信图片批量保存的办法
  • 从DQN到Double DQN:分离动作选择与价值评估,解决强化学习中的Q值过估计问题
  • CF1916G Optimizations From Chelsu
  • 【游记】北京师范大学讲课
  • Vue之刷新页面会触发的生命周期函数
  • 深入解析:App Store 上架完整流程解析,iOS 应用发布步骤、ipa 文件上传工具、TestFlight 测试与苹果审核经验
  • 傅里叶的一生
  • 实用指南:AI Agent开发平台如何设计?核心架构与工作流实战案例详解
  • 实用指南:OpenAI Sora 2重磅发布:AI视频生成进入“GPT-3.5时刻”
  • 题解:AT_agc038_f [AGC038F] Two Permutations
  • 详细介绍:Java基础
  • 20250929给PRO-RK3566开发板在Buildroot系统下裁剪内核【已关闭摄像头ov4689为例子】 - 指南