# 1334. 阈值距离内邻居最少的城市 # 题目地址(1334. 阈值距离内邻居最少的城市) <https://leetcode-cn.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/> ## 题目描述 ``` <pre class="calibre18">``` 有 n 个城市,按从 0 到 n-1 编号。给你一个边数组 edges,其中 edges[i] = [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边,距离阈值是一个整数 distanceThreshold。 返回能通过某些路径到达其他城市数目最少、且路径距离 最大 为 distanceThreshold 的城市。如果有多个这样的城市,则返回编号最大的城市。 注意,连接城市 i 和 j 的路径的距离等于沿该路径的所有边的权重之和。 示例 1: ``` ``` ![](https://img.kancloud.cn/71/2f/712fd0b69de8737cdd68fc0440eb2ce4_960x720.jpg) ``` <pre class="calibre18">``` 输入:n = 4, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]], distanceThreshold = 4 输出:3 解释:城市分布图如上。 每个城市阈值距离 distanceThreshold = 4 内的邻居城市分别是: 城市 0 -> [城市 1, 城市 2] 城市 1 -> [城市 0, 城市 2, 城市 3] 城市 2 -> [城市 0, 城市 1, 城市 3] 城市 3 -> [城市 1, 城市 2] 城市 0 和 3 在阈值距离 4 以内都有 2 个邻居城市,但是我们必须返回城市 3,因为它的编号最大。 示例 2: ``` ``` ![](https://img.kancloud.cn/b7/bf/b7bf5a43ae30be1c18b11d32e3559ca3_960x720.jpg) ``` <pre class="calibre18">``` 输入:n = 5, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]], distanceThreshold = 2 输出:0 解释:城市分布图如上。 每个城市阈值距离 distanceThreshold = 2 内的邻居城市分别是: 城市 0 -> [城市 1] 城市 1 -> [城市 0, 城市 4] 城市 2 -> [城市 3, 城市 4] 城市 3 -> [城市 2, 城市 4] 城市 4 -> [城市 1, 城市 2, 城市 3] 城市 0 在阈值距离 4 以内只有 1 个邻居城市。 提示: 2 <= n <= 100 1 <= edges.length <= n * (n - 1) / 2 edges[i].length == 3 0 <= fromi < toi < n 1 <= weighti, distanceThreshold <= 10^4 所有 (fromi, toi) 都是不同的。 ``` ``` ## 前置知识 - 动态规划 - Floyd-Warshall ## 公司 - 暂无 ## 思路 这道题的本质就是: 1. 在一个无向图中寻找每两个城镇的最小距离,我们使用 Floyd-Warshall 算法(英语:Floyd-Warshall algorithm),中文亦称弗洛伊德算法,是解决任意两点间的最短路径的一种算法。 2. 筛选最小距离不大于 distanceThreshold 的城镇。 3. 统计每个城镇,其满足条件的城镇有多少个 4. 我们找出最少的即可 Floyd-Warshall 算法的时间复杂度和空间复杂度都是O(N3)O(N^3)O(N3), 而空间复杂度可以优化到O(N2)O(N^2)O(N2)。Floyd-Warshall 的基本思想是对于每两个点之间的最小距离,要么经过中间节点 k,要么不经过,我们取两者的最小值,这是一种动态规划思想,详细的解法可以参考[Floyd-Warshall 算法(wikipedia)](https://zh.wikipedia.org/wiki/Floyd-Warshall%E7%AE%97%E6%B3%95) ## 代码 代码支持:Python3 Python3 Code: ``` <pre class="calibre18">``` <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">findTheCity</span><span class="hljs-params">(self, n: int, edges: List[List[int]], distanceThreshold: int)</span> -> int:</span> <span class="hljs-title"># 构建dist矩阵</span> dist = [[float(<span class="hljs-string">'inf'</span>)] * n <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(n)] <span class="hljs-keyword">for</span> i, j, w <span class="hljs-keyword">in</span> edges: dist[i][j] = w dist[j][i] = w <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(n): dist[i][i] = <span class="hljs-params">0</span> <span class="hljs-keyword">for</span> k <span class="hljs-keyword">in</span> range(n): <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(n): <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(n): dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]) <span class="hljs-title"># 过滤</span> res = <span class="hljs-params">0</span> minCnt = float(<span class="hljs-string">'inf'</span>) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(n): cnt = <span class="hljs-params">0</span> <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> dist[i]: <span class="hljs-keyword">if</span> d <= distanceThreshold: cnt += <span class="hljs-params">1</span> <span class="hljs-keyword">if</span> cnt <= minCnt: minCnt = cnt res = i <span class="hljs-keyword">return</span> res ``` ``` **复杂度分析** - 时间复杂度:O(N3)O(N^3)O(N3) - 空间复杂度:O(N2)O(N^2)O(N2) ## 关键点解析 - Floyd-Warshall 算法 - 你可以将本文给的 Floyd-Warshall 算法当成一种解题模板使用 大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:<https://github.com/azl397985856/leetcode> 。 目前已经 37K star 啦。 大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。 ![](https://img.kancloud.cn/cf/0f/cf0fc0dd21e94b443dd8bca6cc15b34b_900x500.jpg)