算法初探LeetCode-安排工作以达到最大收益

70 阅读1分钟

安排工作以达到最大收益

你有 n 个工作和 m 个工人。给定三个数组: difficultyprofit 和 worker ,其中:

  • difficulty[i] 表示第 i 个工作的难度,profit[i] 表示第 i 个工作的收益。
  • worker[i] 是第 i 个工人的能力,即该工人只能完成难度小于等于 worker[i] 的工作。

每个工人 最多 只能安排 一个 工作,但是一个工作可以 完成多次 。

  • 举个例子,如果 3 个工人都尝试完成一份报酬为 $1 的同样工作,那么总收益为 $3 。如果一个工人不能完成任何工作,他的收益为 $0 。

返回 在把工人分配到工作岗位后,我们所能获得的最大利润

示例 1:

输入: difficulty = [2,4,6,8,10], profit = [10,20,30,40,50], worker = [4,5,6,7]
输出: 100 
解释: 工人被分配的工作难度是 [4,4,6,6] ,分别获得 [20,20,30,30] 的收益。

示例 2:

输入: difficulty = [85,47,57], profit = [24,66,99], worker = [40,25,25]
输出: 0

提示:

  • n == difficulty.length
  • n == profit.length
  • m == worker.length
  • 1 <= n, m <= 104
  • 1<=difficulty[i],profit[i],worker[i]<=1051 <= difficulty[i], profit[i], worker[i] <= 10^5

思路分析

先统计难度小于等于difficulty[i]时,选择一项工作来做能够获得最大收益;之后每一个工人都可以选择自己能力范围内的,最高收益的工作来做,即为maxProfit[i],但是并不一定是难度最高的工作,而是自己能完成的工作里面,收益最高的一个。

同一个工人,在他的能力范围内,将他安排到收益最高的工作,这样是局部最优的。 对所有的工人都如此安排,可以得到全局最优。

题目的数据量并不大,最大难度以及工人的最大能力都在1e5的范围内。 这样的话,我们可以先把difficulty和profit捆绑起来,即先建一个二维数组a,第一个元素表示难度,第二个表示收益。然后进行排序:如果难度不同,则按难度升序排序;如果难度相同,则按收益升序排序。

算法代码

public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
    int n = difficulty.length, m = worker.length;
    int[][] a = new int[n][2];
    for (int i = 0; i < n; i++) {
        a[i][0] = difficulty[i];
        a[i][1] = profit[i];
    }
    Arrays.sort(a, new Comparator < int[] > () {@
        Override
        public int compare(int[] o1, int[] o2) {
            // 如果难度不同,则按难度升序排序;如果难度相同,则按收益升序排序
            if (o1[0] == o2[0]) return o1[1] - o2[1];
            else return o1[0] - o2[0];
        }
    });

    int[] maxProfit = new int[100001];
    int nowProfit = 0;
    for (int i = 0; i < n - 1; i++) {
        int j = a[i][0];
        nowProfit = Math.max(nowProfit, a[i][1]);
        while (j < a[i + 1][0]) {
            maxProfit[j] = nowProfit;
            j++;
        }
    }
    int j = a[n - 1][0];
    nowProfit = Math.max(nowProfit, a[n - 1][1]);
    while (j <= 100000) {
        maxProfit[j] = nowProfit;
        j++;
    }

    int ans = 0;
    for (int w: worker) {
        ans += maxProfit[w];
    }
    return ans;
}

结果详情

Snipaste_2023-04-25_22-30-41.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!