题目描述
公司有编号为 1
到 n
的 n
个工程师,给你两个数组 speed
和 efficiency
,其中 speed[i]
和 efficiency[i]
分别代表第 i
位工程师的速度和效率。请你返回由最多k
个工程师组成的最大团队表现值,由于答案可能很大,请你返回结果对 10^9 + 7
取余后的结果。
团队表现值的定义为:一个团队中「所有工程师速度的和」乘以他们「效率值中的最小值」。
样例
输入: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 。
输入: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 。
输入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 4
输出:72
提示:
1 <= n <= 10^5
speed.length == n
efficiency.length == n
1 <= speed[i] <= 10^5
1 <= efficiency[i] <= 10^8
1 <= k <= n
算法分析
核心思想:
由于直接枚举所有工程师速度的和不好枚举,因此可以枚举每个效率值中的最小值,求出当前效率值中最大的速度和,比较所有的情况的效率值对应的团队表现值,取最大
-
1、若求当前效率值对应的团队表现值,则需要用到效率值大于等于这个最小值且速度之后最大的
k
个,因此需要用到小根堆,小根堆维护的是效率值大于等于当前效率值的最大k
个速度,sum
维护的是小根堆中k
个速度的和 -
2、若小根堆中小于
k
个,则进队,更新ans1
,若小根堆等于k
个,则堆顶速度小于当前工程师的速度,则堆顶poll
出,当前工程师的速度入队,用sum * 当前工程师的效率
更新ans
时间复杂度$O(nlogn)$
Java 代码
class Solution {
static int mod = 1000000000 + 7;
static int N = 100010;
static Pair[] pairs = new Pair[N];
public int maxPerformance(int n, int[] speed, int[] efficiency, int k) {
for(int i = 0;i < n;i ++)
{
pairs[i] = new Pair(speed[i],efficiency[i]);
}
//对效率值从大到小排序
Arrays.sort(pairs,0,n);
PriorityQueue<Long> q = new PriorityQueue<Long>();
long sum = 0,ans = 0;
for(int i = 0;i < n;i ++)
{
sum += pairs[i].s;
q.add(pairs[i].s);
while(q.size() > k)
{
sum -= q.poll();
}
ans = Math.max(ans,sum * pairs[i].e);
}
return (int)(ans % mod);
}
}
class Pair implements Comparable<Pair>
{
long s,e;
Pair(long s,long e)
{
this.s = s;
this.e = e;
}
@Override
public int compareTo(Pair o)
{
return Long.compare(o.e,e);
}
}