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的主要内容,如果未能解决你的问题,请参考以下文章

[算法] LeetCode 1.两数之和

LeetCode算法题

leetcode初级算法(数组)——从数组中删除重复项

贪心算法——leetcode455.分发饼干

leetcode1615

LeetCode——strStr