leetcode1615
Posted zjshuster
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode1615相关的知识,希望对你有一定的参考价值。
题目描述
n 座城市和一些连接这些城市的道路 roads 共同组成一个基础设施网络。每个 roads[i] = [ai, bi] 都表示在城市 ai 和 bi 之间有一条双向道路。
两座不同城市构成的 城市对 的 网络秩 定义为:与这两座城市 直接 相连的道路总数。如果存在一条道路直接连接这两座城市,则这条道路只计算 一次 。
整个基础设施网络的 最大网络秩 是所有不同城市对中的 最大网络秩 。
给你整数 n 和数组 roads,返回整个基础设施网络的 最大网络秩 。
解题思路
设first 表示所有节点中度数的最大值,second\\textitsecondsecond 表示所有节点中度数的次大值,实际我们只需要考虑度数为最大值与次大值的城市即可,其余即可城市可以无须考虑,原因如下:
已知最大值 first 与次大值 second,则此时可以知道当前最差的情况下,假设这两城市存在连接,则最大的网络秩为 first+second−1;
假设存在度数比 second小的城市 x,则此时 degree[x]<second,此时含有 xxx 构成的城市对的最大网络秩不超过 degree[x]+first,此时一定满足degree[x]+first ≤ second+first;
综上可以得出结论选择最大或者次大度数的城市一定是最优的。我们可以求出度数为 first,first 的城市集合 firstArr,同时求出度数为 second,second 的城市集合 secondArr。设城市的总数量为 nnn,道路的总数量为 m,集合 firstArr的数量为 x,则此时该集合可以构造的城市对数量为 x(x−1)/2 ,分以下几种情况来讨论:
如果 x=1,此时我们必须选择 firstArr中唯一的城市,另一个城市只能在 secondArr中选择,枚举 secondArr中的每个城市,找到最大的网络秩即可,此时需要的时间复杂度为 O(n);
如果 x>1时,分类讨论如下:
如果满足 x(x−1)/2>m(从x个城市中选2个城市组成的道路总和大于m) 时,此时集合 firstArr 一定存在一对城市,他们之间没有道路连接,此时最大的网络秩即为 2×first;
如果满足 x(x−1)/2≤m 时,此时枚举集合 firstArr中所有不同的城市对即可,此时不需要再考虑次大的城市集合 secondArr,因为此时一定满足 2×first−1≥first+second>2×second ,此时时间复杂度不超过 O(m);
因此通过以上分析,上述解法的时间复杂度为 O(n+m)
代码实现
class Solution
public int maximalNetworkRank(int n, int[][] roads)
int[] degree = new int[n];
boolean[][] connected = new boolean[n][n];
for (int i = 0; i < roads.length; i++)
int[] edge = roads[i];
connected[edge[0]][edge[1]] = true;
connected[edge[1]][edge[0]] = true;
degree[edge[0]]++;
degree[edge[1]]++;
List<Integer> firstA = new ArrayList<>(); // 最大度数集合
List<Integer> secondA = new ArrayList<>(); // 次大度数集合
int first = -1, second = -1;
for (int i = 0; i < n; i++)
if (degree[i] > first)
second = first;
secondA = new ArrayList<>(firstA);
first = degree[i];
firstA.clear();
firstA.add(i);
else if (degree[i] == first)
firstA.add(i);
else if (degree[i] > second)
secondA.clear();
second = degree[i];
secondA.add(i);
else if (degree[i] == second)
secondA.add(i);
if (firstA.size() == 1)
int f = firstA.get(0);
for (int t :
secondA)
if (!connected[f][t])
return first + second;
return first + second - 1;
else
int m = roads.length;
if (firstA.size() * (firstA.size() - 1) / 2 > m)
return first * 2;
for (int u : firstA)
for (int v : firstA)
if (u != v && !connected[u][v])
return first * 2;
return first * 2 -1;
思路参考
以上是关于leetcode1615的主要内容,如果未能解决你的问题,请参考以下文章