LeetCode5359.最大的团队表现值——小顶堆与PriorityQueue

文章目录

引入

在本周周赛中,有这么一道题🔗

公司有编号为 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:

首先看到这道题的时候,很容易明白这道题与0,1背包问题有相似之处,不同之处在于是乘以效率的最小值,而不是分别乘以效率。

所以直接想到使用排序,将efficiency从小到大的排序,依次从小到大选择,不过这样做的难点在于选取speed我们很容易想到是从大到小的选取,所以如何排除小efficiency大speed是值得思考的问题。

在本题题解中, 我们使用了另外一种思路,将efficiency从大到小的排序,为此,我们用到了小顶堆,Java里我们使用PriorityQueue这个数据结构。

另外用到了优先队列的题在leetcode上还有很多,比如合并K个排序链表数组中的第K个最大元素滑动窗口最大值丑数II等等,用了优先队列(堆)后问题就迎刃而解了。

解法

Java中实现了自己的优先队列java.util.PriorityQueue,Java中内置的为小顶堆,也就是说最小的值是优先出队的。

利用这个特点,我们有如下的代码:

public class Solution {
    public int maxPerformance(int n, int[] speed, int[] efficiency, int k) {
        List<Employee> employees=new ArrayList<>();
        for(int i=0;i<n;i++){
            employees.add(new Employee(speed[i],efficiency[i]));
        }
        Collections.sort(employees,(o1, o2) -> o2.effciency-o1.effciency);
        PriorityQueue<Integer> queue=new PriorityQueue<>();
        long res=0,sum=0;
        for(int i=0;i<n;i++){
            int sp=employees.get(i).speed;
            int ef=employees.get(i).effciency;
            queue.add(sp);
            sum+=sp;
            if (queue.size()>k){
                sum-=queue.poll();
            }
            res=Math.max(res,sum*ef);
        }
        return (int)(res % ((int)1e9 + 7));
    }
    class Employee{
        int speed;
        int effciency;

        public Employee(int speed, int effciency) {
            this.speed = speed;
            this.effciency = effciency;
        }
    }
}

首先,我们将speed和efficiency进行排序,当然两者要同时排序,可以使用二维数组,也可以使用类,当然也可以自己实现排序算法。
这里我们选择使用一个Employee类来表示这个二元组,并对efficiency进行从大到小的排序。

然后依次按照efficiency的大小入优先队列(也可以说是放入堆中),放入队列中的元素不是efficiency本身,而是speed,这样出队的时候,我们可以把最小的speed排除出去,这样保证我们堆中的speed是最大的。

这样做是不是会有这样的隐患呢?我们试想一下,上面的操作有下面的两种结果。

  1. 进入最小的speed。
  2. 进入非最小的speed。

如果是进入的最小的speed,那么这个speed会被马上排除出去,按道理来说speed被排除出去,此时乘以的efficiency不是应该存在的,因为speed没有被采纳,但是由于我们取得是最大值Math.max,efficiency是递减的,结果必然会比之前的值res要小,所以不会被采纳。

如果是进入的非最小speed,那么有一个更高efficiency的小speed被排除出去,由于我们这步没有依赖其他efficiency,所以结果不受影响。

这样,使用一个小顶堆的优先队列就能完成题解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值