Medium
题目描述
有 n 个城市和一些连接这些城市的道路。每个 roads[i] = [ai, bi] 表示在城市 ai 和 bi 之间有一条双向道路。
两个不同城市的网络秩定义为连接到任一城市的道路总数。如果一条道路直接连接两个城市,则只计算一次。
基础设施的最大网络秩是所有不同城市对的网络秩的最大值。
给定整数 n 和数组 roads,返回整个基础设施的最大网络秩。
示例 1:
输入:n = 4, roads = [[0,1],[0,3],[1,2],[1,3]]
输出:4
解释:城市 0 和 1 的网络秩是 4,因为有 4 条道路连接到 0 或 1。0 和 1 之间的道路只计算一次。
示例 2:
输入:n = 5, roads = [[0,1],[0,3],[1,2],[1,3],[2,3],[2,4]]
输出:5
解释:有 5 条道路连接到城市 1 或 2。
示例 3:
输入:n = 8, roads = [[0,1],[1,2],[2,3],[2,4],[5,6],[5,7]]
输出:5
解释:城市 2 和 5 的网络秩是 5。注意不是所有城市都必须连接。
约束条件:
- 2 <= n <= 100
- 0 <= roads.length <= n * (n - 1) / 2
- roads[i].length == 2
- 0 <= ai, bi <= n-1
- ai != bi
- 每对城市最多有一条道路连接它们。
解题思路
这道题要求找出所有城市对中网络秩的最大值。网络秩的定义是两个城市连接道路数的总和,如果两个城市之间有直接连接,则需要减去1(避免重复计算)。
解题思路:
- 统计度数:首先遍历所有道路,计算每个城市的度数(连接的道路数)
- 建立连接关系:使用邻接矩阵或集合记录城市间是否直接相连
- 枚举所有城市对:对于每一对不同的城市(i,j),计算它们的网络秩
- 计算网络秩:网络秩 = degree[i] + degree[j] - (如果i和j直接相连则减1,否则减0)
- 维护最大值:记录所有城市对中网络秩的最大值
优化思路:
- 可以先找出度数最大的几个城市,优先考虑它们的组合
- 使用集合存储边的关系,便于快速查询两城市是否相连
时间复杂度是O(n²),空间复杂度是O(n²),对于n≤100的约束完全可以接受。
代码实现
class Solution {
public:
int maximalNetworkRank(int n, vector<vector<int>>& roads) {
vector<int> degree(n, 0);
set<pair<int, int>> connected;
for (auto& road : roads) {
int u = road[0], v = road[1];
degree[u]++;
degree[v]++;
connected.insert({min(u, v), max(u, v)});
}
int maxRank = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int rank = degree[i] + degree[j];
if (connected.count({i, j})) {
rank--;
}
maxRank = max(maxRank, rank);
}
}
return maxRank;
}
};
class Solution:
def maximalNetworkRank(self, n: int, roads: List[List[int]]) -> int:
degree = [0] * n
connected = set()
for u, v in roads:
degree[u] += 1
degree[v] += 1
connected.add((min(u, v), max(u, v)))
max_rank = 0
for i in range(n):
for j in range(i + 1, n):
rank = degree[i] + degree[j]
if (i, j) in connected:
rank -= 1
max_rank = max(max_rank, rank)
return max_rank
public class Solution {
public int MaximalNetworkRank(int n, int[][] roads) {
int[] degree = new int[n];
HashSet<(int, int)> connected = new HashSet<(int, int)>();
foreach (var road in roads) {
int u = road[0], v = road[1];
degree[u]++;
degree[v]++;
connected.Add((Math.Min(u, v), Math.Max(u, v)));
}
int maxRank = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int rank = degree[i] + degree[j];
if (connected.Contains((i, j))) {
rank--;
}
maxRank = Math.Max(maxRank, rank);
}
}
return maxRank;
}
}
var maximalNetworkRank = function(n, roads) {
const degree = new Array(n).fill(0);
const connected = new Set();
for (const [u, v] of roads) {
degree[u]++;
degree[v]++;
connected.add(`${Math.min(u, v)}-${Math.max(u, v)}`);
}
let maxRank = 0;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
let rank = degree[i] + degree[j];
if (connected.has(`${i}-${j}`)) {
rank--;
}
maxRank = Math.max(maxRank, rank);
}
}
return maxRank;
};
复杂度分析
| 复杂度 | 大O表示法 |
|---|---|
| 时间复杂度 | O(n² + m) |
| 空间复杂度 | O(n + m) |
其中 n 是城市数量,m 是道路数量。时间复杂度主要来自于枚举所有城市对的O(n²)操作,空间复杂度主要用于存储度数数组和连接关系。