博主介绍:✌目前全网粉丝2W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。
涵盖技术内容:Java后端、算法、分布式微服务、中间件、前端、运维、ROS等。
博主所有博客文件目录索引:博客目录索引(持续更新)
视频平台:b站-Coder长路
来源:LeetCode专题《LeetCode 75》
题目链接:LeetCode、2462. 雇佣 K 位工人的总代价
类型:数据结构/树/小顶堆
思路:双指针+最小堆
首先理解题意,有三个传参:costs、k、candidates。
其中costs中表示有n个工人的代价、k表示我们要选拔k轮,每轮选拔1个人、candidates则是每一轮在costs中的前candidates人与最后candidates人中去挑选一个最小代价,最终我们要找到k个最小代价的和。【注:若是前candidates与后candidates人当中价值相同,那么我们应该取索引最小的】
抽象上来看,每一轮我们应该取得指定candidates*2
中的一个最小代价,同时这个最小代价应该是先比较基于值,相同则是索引。有工人的数量是n个,范围为10万,那么就是在每一轮中要取得一个最小代价,想要使用n*logn
时间复杂度的,我们借助最小堆来解决。
最小堆中,我们使用一个数组来表示是分别存储的是值、索引、左右,每次移出一个最小元素时,我们可以得知是左边还是右边,最终再设置左右边界值,那么我们就可以每次去根据出堆的元素来判断添加入堆的元素是左边开始还是右边开始的。
代码:
复杂度分析:时间复杂度O(nlogn);空间复杂度O(n)
class Solution {
public long totalCost(int[] costs, int k, int candidates) {
int n = costs.length;
//维护一个优先队列 队列数组元素:元素值,索引,左右(左0右1)
PriorityQueue<int[]> queue = new PriorityQueue<>(candidates * 2, (o1, o2) -> {
//优先比较值,若是值相等比较索引
if (o1[0] == o2[0]) {
return o1[1] - o2[1];
}
return o1[0] - o2[0];
});
//遍历所有的序列(优先将前candidates、后candidates添加)
for (int i = 0; i < n; i ++) {
if (i < candidates || i >= n - candidates) {
queue.offer(new int[]{costs[i], i, i < candidates ? 0 : 1});
}
}
//设置左右端点
int left = candidates - 1, right = n - candidates;
long sum = 0L;
//进行k轮
for (int i = 0; i < k; i ++) {
//出最小元素
int[] numArr = queue.poll();
sum += numArr[0];//数组中第一元素是数值
//若是当前已经完全将所有元素添加到小顶堆时
if (left >= right - 1) continue;
//根据左右来进行补充
if (numArr[2] == 0) {
left ++;
queue.offer(new int[]{costs[left], left, 0});
}else {
right --;
queue.offer(new int[]{costs[right], right, 1});
}
}
return sum;
}
}
大家点赞、收藏、关注、评论啦~
精彩专栏推荐订阅:在下方专栏
更多博客与资料可查看获取联系方式,文末获取开发资源及更多资源博客获取
整理者:长路 整理时间:2024.1.18