LeetCode 317 离建筑物最近的距离
LeetCode 317 题的详细题目信息如下:
题目名称
Shortest Distance from All Buildings(中文译名:离建筑物最近的距离)
题目描述
给你一个由 0、1 和 2 组成的二维网格,其中:
- 0 代表空地
- 1 代表建筑物
- 2 代表障碍物
你需要找到一个空地,使其到所有建筑物的总曼哈顿距离之和最小。如果不存在这样的空地(即没有任何空地能到达所有建筑物),则返回 -1。
曼哈顿距离的计算方式为:对于两个点 (x1, y1) 和 (x2, y2),其距离为 |x1 - x2| + |y1 - y2|。
示例
输入:
[[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]
]
输出:7
解释:
网格中共有 3 个建筑物。位于 (1,2) 的空地到所有建筑物的总距离为 7(到 (0,0) 的距离为 3,到 (0,4) 的距离为 3,到 (2,2) 的距离为 1,总和 3+3+1=7),是所有符合条件的空地中最小的。
约束条件
- 网格的行数和列数均不超过 100。
- 网格中至少有一个建筑物。
LeetCode 317. 离建筑物最近的距离 详细解题代码
/*** @param {number[][]} grid* @return {number}*/
var shortestDistance = function(grid) {// 边界条件判断:网格为空或行数/列数为0if (!grid || grid.length === 0 || grid[0].length === 0) {return -1;}const rows = grid.length;const cols = grid[0].length;let buildingCount = 0; // 记录建筑物的总数量// 存储每个空地到所有建筑物的距离之和const distanceSum = Array.from({ length: rows }, () => Array(cols).fill(0));// 存储每个空地能到达的建筑物数量const reachCount = Array.from({ length: rows }, () => Array(cols).fill(0));// 遍历网格中的每个单元格for (let i = 0; i < rows; i++) {for (let j = 0; j < cols; j++) {// 当遇到建筑物时,执行BFS计算距离if (grid[i][j] === 1) {buildingCount++;const queue = [[i, j, 0]]; // BFS队列,元素为[行, 列, 距离]const visited = Array.from({ length: rows }, () => Array(cols).fill(false));visited[i][j] = true; // 标记建筑物自身为已访问// BFS循环while (queue.length > 0) {const [curRow, curCol, dist] = queue.shift(); // 取出队首元素// 遍历四个方向(上、下、左、右)const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];for (const [dr, dc] of directions) {const newRow = curRow + dr;const newCol = curCol + dc;// 检查新坐标是否有效:在网格范围内、未访问过、且是空地if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && !visited[newRow][newCol] && grid[newRow][newCol] === 0) {visited[newRow][newCol] = true; // 标记为已访问distanceSum[newRow][newCol] += dist + 1; // 累加距离reachCount[newRow][newCol]++; // 增加可到达的建筑物数量queue.push([newRow, newCol, dist + 1]); // 加入队列继续BFS}}}}}}// 寻找最小的距离和let minDistance = Infinity;for (let i = 0; i < rows; i++) {for (let j = 0; j < cols; j++) {// 只有空地且能到达所有建筑物时,才参与最小距离计算if (grid[i][j] === 0 && reachCount[i][j] === buildingCount) {minDistance = Math.min(minDistance, distanceSum[i][j]);}}}// 如果没有符合条件的空地,返回-1,否则返回最小距离return minDistance === Infinity ? -1 : minDistance;
};// 测试用例
const grid = [[1, 0, 2, 0, 1],[0, 0, 0, 0, 0],[0, 0, 1, 0, 0]
];
console.log(shortestDistance(grid)); // 输出:7
代码思路解析
- 初始化:创建两个二维数组
distanceSum
和reachCount
,分别用于记录每个空地到所有建筑物的距离总和以及能到达的建筑物数量。 - BFS 遍历:对每个建筑物执行 BFS,计算其到所有可达空地的距离,并更新
distanceSum
和reachCount
。 - 筛选最优解:遍历所有空地,找到能到达所有建筑物(
reachCount[i][j]
等于建筑物总数)且距离总和最小的空地。 - 边界处理:若不存在符合条件的空地,返回 -1,否则返回最小距离。
该解法通过 BFS 保证了距离计算的准确性,时间复杂度为 O (B×N×M)(其中 B 为建筑物数量,N 和 M 为网格的行数和列数),适用于题目给定的约束条件。