news 2026/4/16 17:29:58

LeetCode 3531 – Count Covered Buildings 题解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 3531 – Count Covered Buildings 题解

LeetCode 3531 – Count Covered Buildings 题解

给定一个正整数 n 表示一座 n x n 的城市网格,以及一个数组 buildings,其中 buildings[i] = [x, y] 表示在坐标 (x, y) 上有一栋建筑,且所有坐标互不相同。leetcode

如果某栋建筑在四个方向上都至少有一栋其他建筑(左、右、上、下),则称这栋建筑是「被覆盖的」。形式化地说,对建筑 (x, y):

  • 同一行 x 上,存在列坐标小于 y 的建筑(左边);
  • 同一行 x 上,存在列坐标大于 y 的建筑(右边);
  • 同一列 y 上,存在行坐标小于 x 的建筑(上边或下边,取决于坐标系约定);
  • 同一列 y 上,存在行坐标大于 x 的建筑(与上一个相反方向)。

问:共有多少栋建筑是被覆盖的?leetcode


朴素直觉:从每栋建筑向四个方向扫

一开始很自然的想法是:

  • 遍历每一个建筑 (x, y);
  • 向左、向右、向上、向下在整个 n x n 网格上「扫」一条线,看看能不能找到其他建筑;
  • 如果四个方向都找到了,就把答案加一。

这个思路在正确性上其实没问题,因为定义就是这样:四个方向上只要能找到至少一栋建筑就行。问题在于效率。

约束中 n 最多可以到 10^5,buildings.length 也可以到 10^5。leetcode

如果你真在网格上按行、按列一路扫到边界,最坏情况下:

  • 对每栋建筑,向某个方向扫描要走 O(n);
  • 有 4 个方向,因此大约 O(4n);
  • 一共有 m = buildings.length 栋建筑,总复杂度约是 O(m · n)。

在 n 和 m 都到 10^5 量级时,O(m · n) 接近 10^10 级别,完全超出可接受范围,这就是面试官会否掉这种方案的原因。


换个视角:真正「需要」的信息是什么?

关键问题是:判断 (x, y) 是否被覆盖,真的需要在网格上一个格子一个格子地扫吗?

观察定义可以发现,只关心「有没有建筑」,而且只在同一行和同一列上:youtube algo

对水平方向:

  • 是否存在 (x, y_left),使得 y_left < y?
  • 是否存在 (x, y_right),使得 y_right > y?

对垂直方向:

  • 是否存在 (x_up, y),使得 x_up < x?
  • 是否存在 (x_down, y),使得 x_down > x?

换句话说,只要知道:

  • 在行 x 里,所有建筑的列坐标的最小值和最大值;
  • 在列 y 里,所有建筑的行坐标的最小值和最大值;

就可以知道 (x, y) 是否被「夹在中间」。algo youtube


核心思路:按行按列维护最小/最大坐标

下面是一个非常高效、又很「面试友好」的做法:

第一步:按行、按列收集坐标

对每一栋建筑 (x, y):

  • 在「按行」的结构里,把该行的 y 放进去;
  • 在「按列」的结构里,把该列的 x 放进去。

可以用两种方式来实现:

  1. 使用 map + 排序,维护每一行/每一列的一个排序后的坐标列表;algo
  2. 或者更直接地,为每行维护 minY[x] 和 maxY[x],为每列维护 minX[y] 和 maxX[y]。linkedin

只维护最小/最大更轻量,这里用这种版本来说明思路。

初始化:

  • minY[x] 初始为一个极大值,maxY[x] 初始为一个极小值;
  • minX[y] 和 maxX[y] 同理。

遍历所有建筑 (x, y) 时:

  • minY[x] = min(minY[x], y);
  • maxY[x] = max(maxY[x], y);
  • minX[y] = min(minX[y], x);
  • maxX[y] = max(maxX[y], x)。youtube linkedin

这一趟遍历是 O(m)。

直觉上:

  • minY[x] 就是这一行最左边的建筑;
  • maxY[x] 就是这一行最右边的建筑;
  • minX[y] 是这一列最上/下边(取决于坐标系)的建筑;
  • maxX[y] 是这一列最下/上边的建筑。

第二步:判断每栋建筑是否「被夹住」

再遍历一遍 buildings,对于每个 (x, y),检查:youtube algo

  • 左边是否有建筑:minY[x] < y;
  • 右边是否有建筑:maxY[x] > y;
  • 上边是否有建筑:minX[y] < x;
  • 下边是否有建筑:maxX[y] > x。

如果四个条件全部满足,就说明 (x, y) 在行上被左右夹住、在列上被上下夹住,是一个被覆盖的建筑,答案加一。algo youtube

从更直观的角度看:

  • minY[x] < y < maxY[x] ⇒ 同一行里它不是最左也不是最右,两侧都有建筑。
  • minX[y] < x < maxX[y] ⇒ 同一列里它不是最上/最下,两侧都有建筑。

复杂度分析

  • 第一次遍历:更新每行/每列的最小值和最大值,时间 O(m)。algo
  • 第二次遍历:对每栋建筑做 O(1) 判断,时间也是 O(m)。algo
  • 总时间复杂度O(m),空间复杂度是 O(n) 级别用来存储这些最值信息,非常适合在面试中展示。

细节补充:一些边界与剪枝

还可以做一个小优化:

  • 要在一行里有「左和右」两个方向,至少得有 3 栋建筑;
  • 要在一列里有「上和下」两个方向,同样至少得有 3 栋建筑。algo

所以在第二次遍历建筑时,可以:

  • 统计每行 cntRow[x] 和每列 cntCol[y] 的建筑数量;
  • 如果 cntRow[x] < 3 或 cntCol[y] < 3,这栋建筑肯定不可能被覆盖,可以直接跳过判断。algo

这个剪枝在数据比较分散时很划算,也能给面试官展示你对条件的深入理解。


参考代码示例(伪代码风格)

下面是接近实际代码的伪代码结构,和上面描述一致:

function countCoveredBuildings(n, buildings): // 假设行和列都是 1..n INF = +∞ // 用数组或哈希表都可以 minY = array[1..n] filled with INF maxY = array[1..n] filled with -INF minX = array[1..n] filled with INF maxX = array[1..n] filled with -INF cntRow = array[1..n] filled with 0 cntCol = array[1..n] filled with 0 // 第一次遍历:更新最值和计数 for (x, y) in buildings: minY[x] = min(minY[x], y) maxY[x] = max(maxY[x], y) minX[y] = min(minX[y], x) maxX[y] = max(maxX[y], x) cntRow[x] += 1 cntCol[y] += 1 ans = 0 // 第二次遍历:判断是否覆盖 for (x, y) in buildings: // 剪枝:行或列少于 3 栋,直接不可能 if cntRow[x] < 3 or cntCol[y] < 3: continue if minY[x] < y and y < maxY[x] and minX[y] < x and x < maxX[y]: ans += 1 return ans

这一解法的核心在于:把「是否有建筑」抽象成「是否在最小值和最大值之间」,避免对网格做任何无谓的扫描。linkedin youtube

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 10:17:02

8、量子计算中的光子干涉与超导回路技术解析

量子计算中的光子干涉与超导回路技术解析 1. 双光子量子干涉 双光子量子干涉,也被称为洪 - 欧 - 曼德尔效应,由罗切斯特大学的物理学家钟启鸿、欧泽宇和伦纳德曼德尔于1987年证实。当两个相同的单光子进入一个1:1分束器时,就会出现这种效应。这里的1:1意味着光子有50:50的…

作者头像 李华
网站建设 2026/4/16 10:18:13

LobeChat商业计划书撰写辅助工具

LobeChat&#xff1a;构建企业级商业智能助手的技术实践 在创业项目密集孵化的今天&#xff0c;一份逻辑严密、数据扎实、表达专业的商业计划书往往是决定融资成败的关键。然而&#xff0c;对于许多初创团队而言&#xff0c;撰写这样一份文档不仅耗时耗力&#xff0c;还常常因缺…

作者头像 李华
网站建设 2026/4/15 16:30:17

LobeChat API文档自动生成方案

LobeChat API文档自动生成方案 在AI应用快速迭代的今天&#xff0c;一个智能聊天系统能否高效落地&#xff0c;往往不只取决于模型能力本身&#xff0c;更在于其工程化程度——尤其是前后端协作的透明度与接口维护的可持续性。LobeChat 作为一款基于 Next.js 的开源大语言模型&…

作者头像 李华
网站建设 2026/4/16 10:17:41

20、量子计算高级算法:从搜索到因式分解

量子计算高级算法:从搜索到因式分解 1. Simon 算法相关 1.1 Simon 预言机构建规则 构建 Simon 预言机时,需遵循以下两条关键规则: 1. 将第一个寄存器的状态复制到第二个寄存器,即对第一个寄存器的所有量子比特应用 CX 门到第二个寄存器的对应量子比特。 2. 找到字符串…

作者头像 李华
网站建设 2026/4/16 10:21:10

ncmdumpGUI终极指南:3步解锁网易云音乐加密文件的神奇魔法

还在为下载的网易云音乐ncm文件无法在其他播放器中打开而苦恼吗&#xff1f;&#x1f3b5; 今天我要向你隆重介绍一个能彻底解决这个痛点的神器——ncmdumpGUI&#xff01;这款基于C#开发的Windows图形界面工具&#xff0c;能够轻松转换那些被加密的音乐文件&#xff0c;让你的…

作者头像 李华
网站建设 2026/4/16 12:07:27

解锁VS Code的终极生产力:消除干扰的通知徽章

在日常的编程工作中,Visual Studio Code(简称VS Code)因其轻量、快速和丰富的插件生态而深受开发者的喜爱。然而,对于一些用户来说,VS Code的活动栏中的通知徽章(尤其是文件保存时的蓝色徽章)可能会成为视觉干扰,影响工作效率。本文将详细介绍如何在不影响自动保存功能…

作者头像 李华