LeetCode Challenge Day 87 β 3531. Count Covered Buildings
Nitin Ahirwal / December 11, 2025
Hey folks π
This is Day 87 of my LeetCode streak π
Today's problem is 3531. Count Covered Buildings β a deceptively simple geometry problem once you see the boundary pattern.
π Problem Statement
You're given:
- A positive integer
n(size of the city gridn Γ n) - An array
buildingswhere each entry[x, y]represents a unique building
A building at (x, y) is covered if there exists:
- A building left of it
- A building right of it
- A building above it
- A building below it
Return the number of such covered buildings.
π‘ Intuition
You don't need to simulate the grid.
A building (x, y) is covered if:
In its row:
- There is a building with
y' < yβ left - There is a building with
y' > yβ right
In its column:
- There is a building with
x' < xβ above - There is a building with
x' > xβ below
This becomes a range boundary problem:
- Track
minYandmaxYfor each row - Track
minXandmaxXfor each column
A building is covered iff:
rowMin[x] < y < rowMax[x]
colMin[y] < x < colMax[y]
That's the key insight.
π Approach
-
Create four maps:
rowMin[x],rowMax[x]colMin[y],colMax[y]
-
Traverse all buildings once to fill these maps.
-
For each building:
- Check if it lies strictly between the min/max of its row and column.
-
Count it if all four directional requirements are met.
Efficient and elegant.
β±οΈ Complexity Analysis
-
Time Complexity:
O(m)wherem = buildings.length -
Space Complexity:
O(m)for storing row and column boundaries
π§βπ» Code (JavaScript)
/**
* @param {number} n
* @param {number[][]} buildings
* @return {number}
*/
var countCoveredBuildings = function(n, buildings) {
const rowMin = new Map(); // row x -> min y
const rowMax = new Map(); // row x -> max y
const colMin = new Map(); // col y -> min x
const colMax = new Map(); // col y -> max x
for (const [x, y] of buildings) {
if (!rowMin.has(x) || y < rowMin.get(x)) rowMin.set(x, y);
if (!rowMax.has(x) || y > rowMax.get(x)) rowMax.set(x, y);
if (!colMin.has(y) || x < colMin.get(y)) colMin.set(y, x);
if (!colMax.has(y) || x > colMax.get(y)) colMax.set(y, x);
}
let count = 0;
for (const [x, y] of buildings) {
const leftExists = rowMin.get(x) < y;
const rightExists = rowMax.get(x) > y;
const aboveExists = colMin.get(y) < x;
const belowExists = colMax.get(y) > x;
if (leftExists && rightExists && aboveExists && belowExists) {
count++;
}
}
return count;
};
π― Reflection
This problem highlights how:
-
Avoiding 2D grid simulation can save massive time
-
Tracking min/max boundaries turns spatial reasoning into simple comparisons
-
Clean preprocessing leads to clean logic
That's it for Day 87 of my LeetCode challenge!
Streak going strong π₯
Happy Coding π¨βπ»