【LeetCode 刷题笔记 2022-10-22】

1235. 规划兼职工作(每日一题)

1. 题目

题目

2. 示例

示例 1:

示例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:
示例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:
示例3

输入:startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]
输出:6

3. 注意事项

  • 难度:困难

    • 没有解出来,抄袭了大佬的代码,代码来源
    • 官方题解 Python3 版本实测不能使用,它使用的二分搜索中k = bisect_right(jobs, jobs[i - 1][0], hi=i, key=lambda p: p[1]) 没有 key属性。
    • 我还尝试使用官方题解 中的java 版中的二分搜索自己写了一个二分搜索的函数,但是有两个题解没有通过,不知道具体哪里有问题。
    • 虽然了解官方题解大佬的题解中的解题思路,但是代码还是写不出来,并且这两个题解中的排序结果不相同不能混用
    • 大佬的题解中的排序非常 ‘精妙’ 我没有看懂为啥都是按照 endTime 从小到大进行排序,但是两种排序的结果不一致
  • 提示:

    • 1 <= startTime.length = endTime.length = profit.length <= 5 * 10^4
    • 1 <= startTime[i] < endTime[i] <= 10^9
    • 1 <= profit[i] <= 10^4
  • 来源:力扣(LeetCode)

  • 链接:传送门

  • 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

4. Python 代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/10/22 8:51
# @Author  : David
# @File    : 1235. 规划兼职工作.py
# @Description : 1235. 规划兼职工作
from bisect import bisect_right
from typing import List

"""
    你打算利用空闲时间来做兼职工作赚些零花钱。
    这里有 n 份兼职工作,每份工作预计从 startTime[i] 开始到 endTime[i] 结束,报酬为 profit[i]。
    给你一份兼职工作表,包含开始时间 startTime,结束时间 endTime 和预计报酬 profit 三个数组,请你计算并返回可以获得的最大报酬。
    注意,时间上出现重叠的 2 份工作不能同时进行。
    如果你选择的工作在时间 X 结束,那么你可以立刻进行在时间 X 开始的下一份工作。
    
    提示:
        1 <= startTime.length == endTime.length == profit.length <= 5 * 10^4
        1 <= startTime[i] < endTime[i] <= 10^9
        1 <= profit[i] <= 10^4

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-profit-in-job-scheduling
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
"""


def func_1(start_time: List[int], end_time: List[int], profit: List[int]) -> int:
    jobs = sorted(zip(end_time, start_time, profit))  # 按照结束时间排序
    f = [0] * (len(jobs) + 1)
    for i, (_, st, p) in enumerate(jobs):
        j = bisect_right(jobs, (st, 10 ** 9 + 1), hi=i)  # hi=i 表示二分上界为 i(默认为 n)
        f[i + 1] = max(f[i], f[j] + p)  # 为什么是 j 不是 j+1:上面算的是 > st,-1 后得到 <= st,但由于还要 +1,抵消了
    return f[-1]


class Solution(object):
    def jobScheduling(self, start_time: List[int], end_time: List[int], profit: List[int]) -> int:
        return func_1(start_time, end_time, profit)

    def Main(self):
        # start_time, end_time, profit = [1, 2, 3, 4, 6], [3, 5, 10, 6, 9], [20, 20, 100, 70, 60]
        start_time, end_time, profit = [4, 3, 1, 2, 4, 8, 3, 3, 3, 9], \
                                       [5, 6, 3, 5, 9, 9, 8, 5, 7, 10], \
                                       [9, 9, 5, 12, 10, 11, 10, 4, 14, 7]
        print(self.jobScheduling(start_time, end_time, profit))


if __name__ == '__main__':
    Solution().Main()

5. 评测结果

评测结果


总结

  1. 每日一题中的题解确实很厉害,但是我没有看懂,需要花更多的时间去研究其中的原理,虽然解题思路大概清楚,但是具体实现还是存在问题
  2. 这两个题解的解题思路差不多,但是存在一些细微的差别,例如:
    1. 都是按照 end_time 从小到大排序,但是排序的结果不一致
    2. 官方的题解并没有成功运行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值