leetcode-最大的团队表现值

 题目是LeetCode第180场周赛的第四题,链接:最大的团队表现值。具体描述为:公司有编号为 1 到 n 的 n 个工程师,给你两个数组 speed 和 efficiency ,其中 speed[i] 和 efficiency[i] 分别代表第 i 位工程师的速度和效率。请你返回由最多 k 个工程师组成的 ​​​​​​最大团队表现值 ,由于答案可能很大,请你返回结果对 10^9 + 7 取余后的结果。团队表现值 的定义为:一个团队中「所有工程师速度的和」乘以他们「效率值中的最小值」。

 示例1:

输入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 2
输出:60
解释:
我们选择工程师 2(speed=10 且 efficiency=4)和工程师 5(speed=5 且 efficiency=7)。他们的团队表现值为 performance = (10 + 5) * min(4, 7) = 60 。

 示例2:

输入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 3
输出:68
解释:
此示例与第一个示例相同,除了 k = 3 。我们可以选择工程师 1 ,工程师 2 和工程师 5 得到最大的团队表现值。表现值为 performance = (2 + 10 + 5) * min(5, 4, 7) = 68 。

 示例3:

输入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 4
输出:72

 这是个hard难度的题目,一开始也是以为就是个动态规划的公式,陷了进去愣是找不到递推公式。后来比赛结束后才在评论区看到这压根就不是动态规划的题目,而是贪心算法。。。

 因为效率取决于k个人中的最小效率,所以直接对效率降序排序(此时对应的速度也会被排序),那么可以看到,只要指定最小效率为降序数组的第i个效率,那么当前最大团队表现值就一定是前面的min(k, i)个最大speed之和乘以这个最小效率,也就是说,只需遍历一遍降序数组就可以得到结果了。具体过程为:

  • 对于一个二维数组(speed, efficiency)按efficiency降序排序得到s
  • 初始化一个大小为k的最小堆topk用以维护k个最大speed
  • 对于前k个efficiency,直接将speed加入最小堆,同时统计全部speed之和totalSpeed,更新最大团队表现值
  • 对于k个之后的efficiency,只有当对应的speed小于k个speed中的最小值(即堆顶元素)时才有必要继续更新totalSpeed以及最大团队表现值,否则可以跳过

 因为排序的时间复杂度为 O ( n l o g n ) O(nlogn) ,遍历过程则只需要 O ( n l o g k ) O(nlogk) l o g k logk 为将数据加入最小堆所需时间),所以总的时间复杂度为 O ( n l o g n ) + O ( n l o g k ) O(nlogn)+O(nlogk) ,空间复杂度为 O ( n ) O(n) (存储排序后数据)。

 JAVA版代码如下:

class Solution {
    public int maxPerformance(int n, int[] speed, int[] efficiency, int k) {
        int[][] speedAndEff = new int[n][2];
        for (int i = 0; i < n; ++i) {
            speedAndEff[i][0] = speed[i];
            speedAndEff[i][1] = efficiency[i];
        }
        Arrays.sort(speedAndEff, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o2[1] - o1[1];
            }
        });

        Queue topk = new PriorityQueue<Integer>(k);
        long maxResult = 0, totalSpeed = 0;
        for (int i = 0; i < k; ++i) {
            topk.offer(speedAndEff[i][0]);
            totalSpeed += speedAndEff[i][0];
            maxResult = Math.max(maxResult, totalSpeed * speedAndEff[i][1]);
        }
        for (int i = k; i < n; ++i) {
            if (speedAndEff[i][0] > (int)topk.peek()) {
                totalSpeed = totalSpeed - (int)topk.poll() + speedAndEff[i][0];
                topk.offer(speedAndEff[i][0]);
                maxResult = Math.max(maxResult, totalSpeed * speedAndEff[i][1]);
            }
        }
        return (int)(maxResult % 1000000007);
    }
}

 提交结果如下:


 Python版代码如下:

class Solution:
    def maxPerformance(self, n: int, speed: List[int], efficiency: List[int], k: int) -> int:
        speedAndEff = list(zip(speed, efficiency))              #组成(speed, efficiency)
        speedAndEff.sort(key=lambda x : x[1], reverse=True)     #按efficiency降序排序

        import heapq
        topk = []
        maxResult, totalSpeed = 0, 0
        for i in range(k):                                      #前k个全部加入最小堆中,同时计算最大表现值(可以小于k个人)
            heapq.heappush(topk, speedAndEff[i][0])
            totalSpeed += speedAndEff[i][0]
            maxResult = max(maxResult, totalSpeed * speedAndEff[i][1])

        for i in range(k, n):                                   #对于k个之后的,只有speed大于当前最小speed的才有必要继续计算
            if speedAndEff[i][0] > topk[0]:
                totalSpeed = totalSpeed - topk[0] + speedAndEff[i][0]
                heapq.heapreplace(topk, speedAndEff[i][0])
                maxResult = max(maxResult, totalSpeed * speedAndEff[i][1])
        
        return maxResult % 1000000007

 提交结果如下:


发布了68 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/JR_Chan/article/details/104967640