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

LeetCode 317 最短距离选址问题详解(Swift 实现 + BFS 多源遍历)

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

文章目录

    • 摘要
    • 描述
      • 示例 1:
    • 题解答案
      • 遍历方式:
    • 题解代码分析(Swift 实现)
    • 题解代码解析
      • 核心结构
      • 遍历每一栋建筑
      • BFS 细节逻辑
      • 最后从所有“被所有建筑都访问过的空地”中选出最小距离:
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结
      • 实际应用场景:

摘要

如果你在城市规划系统里工作,或者搞一个模拟经营类游戏,那你肯定遇到过这样的需求:找一个最优位置建房子,让它到所有已有建筑的总距离最短

LeetCode 317 就是这么一道“建房选址”的题,表面是 BFS 遍历地图,实际是一个网格图上的多源路径搜索 + 最小和策略的组合题。

这篇文章用 Swift 带你分析如何高效地选出“最适合造房子”的格子位置,既有运行逻辑讲解,也有完整 Demo 和测试案例,适合用来刷题、面试、或做模拟业务模型的参考。

描述

题目是这样说的:

给你一个 m x n 的网格地图 grid,每个格子可能是:

  • 0:空地,可以建房子
  • 1:建筑,不能通过
  • 2:障碍物,不能通过

你需要从这些空地中选一个点建房子,要求:

该点到所有建筑的曼哈顿距离之和最小

如果不存在这样的位置可以访问所有建筑,则返回 -1

示例 1:

输入:
[[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]]输出:
7解释:
选中 [1,2] 这个位置,到三个建筑的距离是:
(1,2) -> (0,0): 3
(1,2) -> (0,4): 3
(1,2) -> (2,2): 1
总和为 7,是所有可选位置中最小的。

题解答案

为了找出一个“能到所有建筑”的空地,并且使得总路径最短,我们可以反向思考:

遍历方式:

  • 不是从空地出发去看能到哪些建筑。

  • 而是从每一栋建筑出发去 BFS 扫空地,记录每个空地的:

    • 累计路径总和(sumDistance)
    • 被访问建筑数量(reachCount)

最后检查哪些空地被所有建筑都访问到,再从这些里选一个总距离最小的。

题解代码分析(Swift 实现)

func shortestDistance(_ grid: [[Int]]) -> Int {let rows = grid.countlet cols = grid[0].countvar distanceSum = Array(repeating: Array(repeating: 0, count: cols), count: rows)var reachCount = Array(repeating: Array(repeating: 0, count: cols), count: rows)let directions = [(-1,0), (1,0), (0,-1), (0,1)]var totalBuildings = 0for i in 0..<rows {for j in 0..<cols {if grid[i][j] == 1 {totalBuildings += 1bfs(i, j, grid, &distanceSum, &reachCount, rows, cols, directions)}}}var minDist = Int.maxfor i in 0..<rows {for j in 0..<cols {if grid[i][j] == 0 && reachCount[i][j] == totalBuildings {minDist = min(minDist, distanceSum[i][j])}}}return minDist == Int.max ? -1 : minDist
}func bfs(_ row: Int, _ col: Int, _ grid: [[Int]],_ distanceSum: inout [[Int]],_ reachCount: inout [[Int]],_ rows: Int, _ cols: Int,_ directions: [(Int, Int)]) {var visited = Array(repeating: Array(repeating: false, count: cols), count: rows)var queue: [(Int, Int, Int)] = [(row, col, 0)]visited[row][col] = truewhile !queue.isEmpty {let (x, y, dist) = queue.removeFirst()for (dx, dy) in directions {let newX = x + dxlet newY = y + dyif newX >= 0, newX < rows, newY >= 0, newY < cols,!visited[newX][newY], grid[newX][newY] == 0 {visited[newX][newY] = truedistanceSum[newX][newY] += dist + 1reachCount[newX][newY] += 1queue.append((newX, newY, dist + 1))}}}
}

题解代码解析

核心结构

  • distanceSum[i][j]: 表示空地 (i, j) 到所有建筑的距离之和;
  • reachCount[i][j]: 表示这个空地目前能被多少个建筑访问到;
  • bfs():从每一栋建筑出发,把可以走到的空地进行更新。

遍历每一栋建筑

if grid[i][j] == 1 {bfs(i, j, ...)
}

每次都从建筑出发跑一轮 BFS,让这栋建筑“把它能访问的空地都更新一遍”。

BFS 细节逻辑

  • 维护一个 visited 数组防止重复遍历;

  • 遇到空地就:

    • 更新它的 distanceSum 累加路径长度;
    • 更新它的 reachCount 加 1;
    • 加入下一轮队列。

最后从所有“被所有建筑都访问过的空地”中选出最小距离:

if reachCount[i][j] == totalBuildings

这句话的意思是,这块空地被所有建筑都走到过,才是合法候选地。

示例测试及结果

我们来验证下主例题:

let input = [[1, 0, 2, 0, 1],[0, 0, 0, 0, 0],[0, 0, 1, 0, 0]
]
let result = shortestDistance(input)
print(result)  // 输出:7

解释:

选中 [1,2] 位置,离三栋建筑的距离为:3 + 3 + 1 = 7
而其他空地虽然能访问一部分建筑,但总距离更大或不满足“可达所有建筑”的条件。

时间复杂度

  • 对于每个建筑(共 b 个),执行一次 BFS;
  • 每次 BFS 最多遍历所有空地(最多 m * n 个);

所以总时间复杂度是 O(b × m × n),对于题目给定的规模是可以接受的。

空间复杂度

  • distanceSumreachCountvisited 都是 m x n 的二维数组;
  • 每次 BFS 使用的队列空间也最多为 O(mn)

所以整体空间复杂度为 O(m × n)

总结

LeetCode 317 是一道典型的“网格图上多源最短路径累加”问题,技巧核心是:

  • 多次从“源点”出发进行 BFS;
  • 用额外数组记录“累加状态”和“覆盖次数”;
  • 最后从所有可选项中选最优解。

实际应用场景:

  • 城市交通:选择公交站点或医院位置;
  • 游戏地图:找玩家基地或资源点的最优投放位置;
  • 后端服务部署:计算请求源覆盖范围、延迟等指标汇总选址;
http://www.lryc.cn/news/579677.html

相关文章:

  • 从 TCP/IP 协议栈角度深入分析网络文件系统 (NFS)
  • MySQL的窗口函数介绍
  • 基于SpringBoot+Vue的酒类仓储管理系统
  • 【网络协议】WebSocket简介
  • 【tensorflow2.6.0 一系列相关报错记录】
  • 关于微前端框架micro,子应用设置--el-primary-color失效的问题
  • Linux性能分析工具
  • Oracle:报错jdbc:oracle:thin:@IP地址:端口:实例名, errorCode 28001, state 99999
  • Spark 4.0的VariantType 类型以及内部存储
  • 打造一个可维护、可复用的前端权限控制方案(含完整Demo)
  • 2025年4月SCI-吕佩尔狐优化算法Rüppell’s fox optimizer-附Matlab免费代码
  • 苹果手机扫描PDF:整理课堂笔记、保存重要文件
  • Intellij IDEA中Maven的使用
  • H3C-备件流程
  • EXCEL 基础函数
  • 论文阅读笔记——Autoregressive Image Generation without Vector Quantization
  • 构建引擎: 打造小程序编译器
  • 工业路由器赋能智慧电力储能柜实时通讯,构建电力智能化新生态
  • x搜索新增了x-client-transaction-id的验证
  • 网络工具如何帮助消除网络安全风险
  • 通达信 主力资金与成交量分析系统 幅图
  • 机器学习-03(机器学习任务攻略)
  • 边缘计算解决方案:数据中心机房IT设备数据采集与调优
  • STM32-PWM驱动无源蜂鸣器
  • 使用numpy的快速傅里叶变换的一些问题
  • AI+软件测试——03软件的缺陷及管理
  • 一、Docker:一场颠覆应用部署与运维的容器革命
  • 数学建模_时间序列
  • 月更!2025年7月鼠标入门及选购推荐(含无线鼠标、游戏鼠标)
  • 百度文心大模型 4.5 系列全面开源 英特尔同步支持端侧部署