• LeetCode_动态规划_困难_1235.规划兼职工作


    1.题目

    你打算利用空闲时间来做兼职工作赚些零花钱。

    这里有 n 份兼职工作,每份工作预计从 startTime[i] 开始到 endTime[i] 结束,报酬为 profit[i]。

    给你一份兼职工作表,包含开始时间 startTime,结束时间 endTime 和预计报酬 profit 三个数组,请你计算并返回可以获得的最大报酬。

    注意,时间上出现重叠的 2 份工作不能同时进行。

    如果你选择的工作在时间 X 结束,那么你可以立刻进行在时间 X 开始的下一份工作。

    示例 1:
    在这里插入图片描述
    输入:startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70]
    输出:120
    解释:
    我们选出第 1 份和第 4 份工作,
    时间范围是 [1-3]+[3-6],共获得报酬 120 = 50 + 70。

    示例 2:
    在这里插入图片描述
    输入:startTime = [1,2,3,4,6], endTime = [3,5,10,6,9], profit = [20,20,100,70,60]
    输出:150
    解释:
    我们选择第 1,4,5 份工作。
    共获得报酬 150 = 20 + 70 + 60。

    示例 3:
    在这里插入图片描述
    输入:startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]
    输出:6

    提示:
    1 <= startTime.length == endTime.length == profit.length <= 5 * 104
    1 <= startTime[i] < endTime[i] <= 109
    1 <= profit[i] <= 104

    来源:力扣(LeetCode)
    链接:https://leetcode.cn/problems/maximum-profit-in-job-scheduling

    2.思路

    (1)动态规划 & 二分搜索
    思路参考本题官方题解

    ① 先将将兼职工作按结束时间进行升序排序,定义 dp 数组,dp[i] 表示前 i 份兼职工作可以获得的最大报酬,1 ≤ i ≤ startTime.length。

     int[] dp = new int[startTime.length + 1];
    
    • 1

    状态转移方程如下:

    dp[i] = max(dp[i - 1], dp[cnt] + profit[i - 1])
    
    • 1

    其中,cnt 表示满足结束时间小于等于第 i - 1份工作开始时间的兼职数量,这可以通过二分搜索获得。

    3.代码实现(Java)

    //思路1————动态规划 & 二分搜索
    class Solution {
        public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
            int length = startTime.length;
            // jobs[i] 存储第 i 份兼职工作的startTime、endTime、profit
            int[][] jobs = new int[length][3];
            for (int i = 0; i < length; i++) {
                jobs[i] = new int[]{startTime[i], endTime[i], profit[i]};
            }
            //将兼职工作按结束时间进行升序排序
            Arrays.sort(jobs, (job1, job2) -> job1[1] - job2[1]);
            // dp[i] 表示前 i 份兼职工作可以获得的最大报酬
            int[] dp = new int[length + 1];
            dp[0] = 0;
            for (int i = 1; i <= length; i++) {
                // cnt 表示满足结束时间小于等于第 i - 1 份工作开始的兼职工作数量
                int cnt = binarySearchRightBound(jobs, i - 1, jobs[i - 1][0]);
                dp[i] = Math.max(dp[i - 1], dp[cnt] + jobs[i - 1][2]);
            }
            return dp[length];
        }
    
        public int binarySearchRightBound(int[][] jobs, int right, int target) {
            int left = 0;
            while (left < right) {
                int mid = left + (right - 1 - left) / 2;
                if (jobs[mid][1] > target) {
                    right = mid;
                } else {
                    left = mid + 1;
                }
            }
            return left;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
  • 相关阅读:
    权限系统设计学习总结(5)—— 权限系统设计全面总结
    在C++中,`sync()`是一个用于刷新缓冲区的函数,通常用于文件或流的I/O操作。调用`sync()`函数会将所有等待写入的数据立即刷新到底层设备。
    VUE框架(二)
    事务的四大特性----ACID
    链表的基本操作
    Ginger的GIAO
    Visual Studio批量删除换行
    湖北申报!2022年湖北省创新型产业集群申报条件、申报程序和考核评估
    lintcode 125 · 背包问题(二)
    【计算机视觉40例】案例07:数字手势识别
  • 原文地址:https://blog.csdn.net/weixin_43004044/article/details/127457535