leetcode 826. 安排工作以达到最大收益

最大利润分配问题

题目描述

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

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

每个工人最多只能安排一个工作,但一个工作可以由多个工人完成。目标是将工人分配到工作岗位后,最大化总收益。

解题思路

预处理

  1. 排序工作:为了方便查找每个工人能完成的最难工作及其对应的收益,我们首先按照工作的难度进行排序。

  2. 构建最大收益数组:创建一个数组 maxProfitAtDifficulty,该数组记录了在每一个工作难度下能够获得的最大收益。这样我们可以快速查询在任意难度范围内的最大收益。

分配工人

  1. 排序工人:将工人的能力进行排序,方便按照能力逐一处理。

  2. 计算总收益:遍历排序后的工人数组,利用 maxProfitAtDifficulty 数组,通过二分查找或线性扫描快速找到每个工人能够完成的最难工作,并获取对应的最大收益,累加到总收益中。

复杂度分析

  • 排序工作的复杂度O(n log n),其中 n 是工作的数量。
  • 构建最大收益数组的复杂度O(n)
  • 排序工人的复杂度O(m log m),其中 m 是工人的数量。
  • 计算总收益的复杂度O(m + n),其中线性扫描部分总共最多执行 n 次。

因此,总的时间复杂度为 O(n log n + m log m)

代码实现

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int difficulty;
    int profit;
} Job;

int cmp(const void *a, const void *b) {
    return ((Job *)a)->difficulty - ((Job *)b)->difficulty;
}

int maxProfitAssignment(int* difficulty, int difficultySize, int* profit, int profitSize, int* worker, int workerSize) {
    // 先把所有工作按难度排序
    Job* jobs = (Job*)malloc(difficultySize * sizeof(Job));
    for (int i = 0; i < difficultySize; ++i) {
        jobs[i].difficulty = difficulty[i];
        jobs[i].profit = profit[i];
    }
    qsort(jobs, difficultySize, sizeof(Job), cmp);
    
    // 创建并填充 maxProfitAtDifficulty 数组
    int* maxProfitAtDifficulty = (int*)malloc(difficultySize * sizeof(int));
    maxProfitAtDifficulty[0] = jobs[0].profit;
    for (int i = 1; i < difficultySize; ++i) {
        maxProfitAtDifficulty[i] = jobs[i].profit > maxProfitAtDifficulty[i-1] ? jobs[i].profit : maxProfitAtDifficulty[i-1];
    }
    
    // 对每个工人的能力进行排序
    qsort(worker, workerSize, sizeof(int), cmp);
    
    // 计算总收益
    int totalProfit = 0;
    int jobIndex = 0;
    for (int i = 0; i < workerSize; ++i) {
        // 找到当前工人能胜任的最难的工作
        while (jobIndex < difficultySize && worker[i] >= jobs[jobIndex].difficulty) {
            ++jobIndex;
        }
        if (jobIndex > 0) {
            totalProfit += maxProfitAtDifficulty[jobIndex - 1];
        }
    }
    
    // 释放分配的内存
    free(jobs);
    free(maxProfitAtDifficulty);
    
    return totalProfit;
}

int main() {
    int difficultySize, profitSize, workerSize;

    printf("请输入 difficulty 数组的大小: ");
    scanf("%d", &difficultySize);
    int* difficulty = (int*)malloc(difficultySize * sizeof(int));
    printf("请输入 difficulty 数组: ");
    getchar(); // 清除换行符
    readArray(difficulty, difficultySize);

    printf("请输入 profit 数组的大小: ");
    scanf("%d", &profitSize);
    int* profit = (int*)malloc(profitSize * sizeof(int));
    printf("请输入 profit 数组: ");
    getchar(); // 清除换行符
    readArray(profit, profitSize);

    printf("请输入 worker 数组的大小: ");
    scanf("%d", &workerSize);
    int* worker = (int*)malloc(workerSize * sizeof(int));
    printf("请输入 worker 数组: ");
    getchar(); // 清除换行符
    readArray(worker, workerSize);
    
    int result = maxProfitAssignment(difficulty, difficultySize, profit, profitSize, worker, workerSize);
    printf("最大利润为 %d\n", result);

    // 释放分配的内存
    free(difficulty);
    free(profit);
    free(worker);

    return 0;
}

详细解释

  • Job 结构体:定义工作对象,包含难度和收益两个字段。
  • 排序函数 cmp:用于按难度对 Job 进行排序的比较函数。
  • maxProfitAssignment 函数:主函数,负责计算最大总收益。
    • 排序工作:使用 qsort 对工作按难度排序。
    • 构建 maxProfitAtDifficulty 数组:记录每个难度下的最大收益。
    • 排序工人:对工人的能力进行排序。
    • 计算总收益:遍历每个工人,查找其可胜任的最难工作并累加收益。
  • 主函数 main:测试样例,输出最大利润。

总结

结果

该问题通过排序和预处理数组的方式,提高了查找和计算的效率,使得整体解决方案达到了较优的时间复杂度 O(n log n + m log m)。这对于处理大规模输入数据时非常高效。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值