【Leetcode 每日一题】2071. 你可以安排的最多任务数目

问题背景

给你 n n n 个任务和 m m m 个工人。每个任务需要一定的力量值才能完成,需要的力量值保存在下标从 0 0 0 开始的整数数组 t a s k s tasks tasks 中,第 i i i 个任务需要 t a s k s [ i ] tasks[i] tasks[i] 的力量才能完成。每个工人的力量值保存在下标从 0 0 0 开始的整数数组 w o r k e r s workers workers 中,第 j j j 个工人的力量值为 w o r k e r s [ j ] workers[j] workers[j]。每个工人只能完成 一个 任务,且力量值需要 大于等于 该任务的力量要求值(即 w o r k e r s [ j ] ≥ t a s k s [ i ] workers[j] \ge tasks[i] workers[j]≥tasks[i])。

除此以外,你还有 p i l l s pills pills 个神奇药丸,可以给 一个工人的力量值 增加 s t r e n g t h strength strength。你可以决定给哪些工人使用药丸,但每个工人 最多 只能使用 一片 药丸。

给你下标从 0 0 0 开始的整数数组 t a s k s tasks tasks 和 w o r k e r s workers workers 以及两个整数 p i l l s pills pills 和 s t r e n g t h strength strength,请你返回 最多 有多少个任务可以被完成。

数据约束

  • n = t a s k s . l e n g t h n = tasks.length n=tasks.length
  • m = w o r k e r s . l e n g t h m = workers.length m=workers.length
  • 1 ≤ n , m ≤ 5 × 1 0 4 1 \le n, m \le 5 \times 10 ^ 4 1≤n,m≤5×104
  • 0 ≤ p i l l s ≤ m 0 \le pills \le m 0≤pills≤m
  • 0 ≤ t a s k s [ i ] , w o r k e r s [ j ] , s t r e n g t h ≤ 1 0 9 0 \le tasks[i], workers[j], strength \le 10 ^ 9 0≤tasks[i],workers[j],strength≤109

解题过程

解决问题的核心,是贪心和二分。

由于题目要要求的是完成任务的数量,那么对于同一个任务而言,用力量更强的工人还是用相对较弱的,对答案的贡献是一样的,选择会带来的区别在于是否需要用药丸。

所以让力量更强的工人去完成简单的任务,更有可能省下一颗药丸,使得原本在剩余资源中无法完成的任务在药物的加持下变得可能完成,产生更大的总数。

具体实现

java 复制代码
class Solution {
    public int maxTaskAssign(int[] tasks, int[] workers, int pills, int strength) {
        Arrays.sort(tasks);
        Arrays.sort(workers);
        int left = 1;
        int right = Math.min(tasks.length, workers.length) + 1;
        while (left < right) {
            int mid = left + ((right - left) >>> 1);
            if (check(tasks, workers, pills, strength, mid)) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        // 注意,讨论的区间端点左侧才是能实现的任务数
        return left - 1;
    }

    private boolean check(int[] tasks, int[] workers, int pills, int strength, int limit) {
        // 用双端队列记录可以完成的任务,根据是否食用药丸作不同的处理
        Deque<Integer> queue = new ArrayDeque<>();
        for (int i = 0, j = workers.length - limit; j < workers.length; j++) {
            int cur = workers[j];
            while (i < limit && cur + strength >= tasks[i]) {
                queue.addLast(tasks[i++]);
            }
            if (queue.isEmpty()) {
                return false;
            }
            if (cur >= queue.peekFirst()) {
                queue.pollFirst();
                continue;
            }
            if (pills == 0) {
                return false;
            }
            pills--;
            queue.pollLast();
        }
        return true;
    }
}
相关推荐
xin007hoyo8 分钟前
算法笔记·数学·最大公约数
笔记·算法
丶Darling.24 分钟前
Day126 | 灵神 | 二叉树 | 层数最深的叶子结点的和
数据结构·c++·算法·二叉树·深度优先
小O的算法实验室1 小时前
2025年ESWA SCI1区TOP,离散人工蜂群算法+多农场多除草机器人任务分配,深度解析+性能实测
算法·智能算法改进
2401_859049082 小时前
Git使用
arm开发·git·stm32·单片机·mcu·算法
冠位观测者3 小时前
【Leetcode 每日一题】2942. 查找包含给定字符的单词
算法·leetcode·职场和发展
蓝心湄3 小时前
C语言-枚举
c语言·开发语言·算法
轮到我狗叫了3 小时前
力扣小题, 力扣113.路径总和II力扣.111二叉树的最小深度 力扣.221最大正方形力扣5.最长回文子串更加优秀的算法:中心扩展算法
算法·leetcode·深度优先
黎明smaly3 小时前
【C语言】复习~数组和指针
c语言·开发语言·数据结构·c++·leetcode
haven-8523 小时前
最大似然估计(Maximum Likelihood Estimation, MLE)详解
算法·机器学习·概率论
逐光沧海3 小时前
排序和排列——蓝桥杯备考
算法·蓝桥杯