初学python记录:力扣1235. 规划兼职工作

news2024/10/7 10:24:51

题目:

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

这里有 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

思考:

解法一——动态规划(以时间作为划分)

设f(x)为在时间为x时能获得的最大报酬,

设正好在x结束的工作开始于时间m,报酬为p,那么

f(x) = max(f(x-1), f(m_1)+p_1, f(m_2)+p_2, ......) 

代码如下:

class Solution:
    def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
        # 动态规划:dp[i]表示在时间为i时能获得的最大报酬
        # f(x) = max(f(x-1), f(m)+p)   设正好在x结束的所有工作开始于m,报酬为p
        n = max(endTime)
        dp = [0 for _ in range(n+1)]
        for i in range(2, n+1):
            candidate = []  # 记录所有"f(m)+p"
            for index, value in enumerate(endTime):
                if value == i:
                    candidate.append(dp[startTime[index]] + profit[index])
            if candidate:
                dp[i] = max(dp[i - 1], max(candidate))
            else:
                dp[i] = dp[i - 1]
        return dp[n]
            

超时,卡在第 21 / 35 个例子:

 

优化 

可以将遍历endtime数组找到刚好在x结束的所有工作这一步提到最前面,避免每次计算f(x)时都要遍历一次。代码如下:

from collections import defaultdict
class Solution:
    def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
        # 动态规划:dp[i]表示在时间为i时能获得的最大报酬
        # f(x) = max(f(x-1), f(m)+p)   设正好在x结束的所有工作开始于m,报酬为p
        n = max(endTime)
        dp = [0 for _ in range(n+1)]
        end_index = defaultdict(list)   # 键为结束时间,值为这份工作的索引
        for index, time in enumerate(endTime):
            end_index[time].append(index)

        for i in range(2, n+1):
            if not end_index[i]:
                dp[i] = dp[i - 1]
            else:
                candidate = []  # 记录所有"f(m)+p"
                for index in end_index[i]:
                    candidate.append(dp[startTime[index]] + profit[index])
                dp[i] = max(dp[i - 1], max(candidate))

        return dp[n]

时间上确实加快了,但是卡在一个特殊的测试例子上,超内存了:

原因是只有四项工作待选,但是用时间划分的话,dp数组的长度有1000000001,显然在这种情况下仍然按时间划分造成了内存极大浪费。

解法二——动态规划(以工作作为划分)

那么换一个思路,将所有工作按结束时间排序,以是否选择每一项工作作为划分。

设f(x)表示在第x个结束的工作结束时,能获得的最大报酬,即 选择工作x 或者 不选择工作x 这两种决策得到的报酬更大值。公式如下,其中y是满足endtime(y) <= starttime(x) 条件的工作索引最大值,如果不存在这样的y,则f(y)取0:

 f(x) = max(f(x-1), f(y)+profit(x))

为了减少耗时,这里找y使用二分查找。代码如下:

from collections import defaultdict
class Solution:
    def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
        # 动态规划:f(x)表示在第x个结束的工作结束时,能获得的最大报酬,即 选择工作x 或者 不选择工作x 的报酬更大值
        # 公式如下,其中y是满足endtime(y) <= starttime(x) 条件的工作索引最大值,如果不存在这样的y,则f(y)取0
        # f(x) = max(f(x-1), f(y)+profit(x))

        # 将所有工作按结束时间排序
        combined_list = list(zip(startTime, endTime, profit))
        combined_list = sorted(combined_list, key = lambda x : x[1])
        n = len(profit)
        dp = [-1 for _ in range(n)]
        dp[0] = combined_list[0][2]
        for x in range(1, n):
            # 找到工作y:满足endtime(y) <= starttime(x) 条件的最大值
            left = 0
            right = x - 1
            f_y = 0
            while left <= right:
                mid = (left + right) // 2
                if combined_list[mid][1] <= combined_list[x][0]:
                    f_y = dp[mid]
                    left = mid + 1
                else:
                    right = mid - 1
            # f(x) = max(f(x-1), f(y)+profit(x))
            dp[x] = max(dp[x-1], f_y + combined_list[x][2])

        return dp[n-1]

提交通过,耶耶耶: 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1642217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

水仙花数问题

问题描述&#xff1a; 求出0&#xff5e;100000之间的所有“水仙花数”并输出。 “水仙花数”是指一个n位数&#xff0c;其各位数字的n次方之和确好等于该数本身&#xff0c;如:153&#xff1d;1^3&#xff0b;5^3&#xff0b;3^3&#xff0c;则153是一个“水仙花数”。 #in…

对链表进行插入排序(详细解析)

对链表进行插入排序&#xff08;详解&#xff09; 题目&#xff1a; 对链表进行插入排序 给定单个链表的头 head &#xff0c;使用 插入排序 对链表进行排序&#xff0c;并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的&#xff0c;每次只移动一个元素&a…

CUDA和显卡驱动

1.安装显卡驱动 https://www.nvidia.com/download/index.aspx?langen-us 由于我的显卡是RTX4060&#xff0c;因此先选择RTX40系列&#xff0c;然后选择RTX4060&#xff0c;进行安装 2.查看显卡对应的CUDA CUDA安装地址&#xff1a;https://developer.nvidia.com/cuda-toolk…

数据库(MySQL)—— 事务

数据库&#xff08;MySQL&#xff09;—— 事务 什么是事务事务操作未控制事务测试异常情况 控制事务一查看/设置事务提交方式&#xff1a;提交事务回滚事务 控制事务二开启事务提交事务回滚事务 并发事务问题脏读&#xff08;Dirty Read&#xff09;不可重复读&#xff08;Non…

小红书流量机制解析

小红书流量机制解析 前言 大家好&#xff0c;我自2020年5月起&#xff0c;开始专注于小红书平台&#xff0c;帮助品牌商家在小红书上经营。在这段时间里&#xff0c;我深入研究了小红书的流量机制&#xff0c;并结合自己的实践经验&#xff0c;为大家带来了这份全网最硬核的小…

【面试经典 150 | 字典树】实现 Trie (前缀树)

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;前缀树 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回…

复旦微JFM7VX690计算后IO接口模块,用于雷达信号处理、数据处理等需要高速密集计算的应用场景

计算后IO接口模块 1 介绍 1.1 产品概述 计算后IO接口模块主要由复旦微JFM7VX690型FPGA、国产以太网收发器YT8521、国产BMC芯片GD32F450、国产CPLD芯片EF2L45BG256B、国产内存颗粒等主要芯片组成&#xff0c;采用标准6U VPX尺寸设计。 本计算后IO接口模块主要用于雷达信号处…

实习与就业|基于Springboot+vue的实习与就业管理系统(源码+数据库+文档)

实习与就业目录 基于Springbootvue的实习与就业管理系统 一、前言 二、系统设计 三、系统功能设计 管理员登录 就业管理 企业公告信息管理 企业公告类型管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主…

SDB2F5 首鼎1.2MHz 输入5V 输出28V 100mA升压DC-DC转换器

SDB2F5是一款固定频率&#xff0c;内部的软启动有很小脉冲电流可延长电池寿命。SDB2F5最低输入电压为2.5V&#xff0c;在输入电压为5V的时候可升压到28V 100mA。SDB2F5在轻负载时自动转成脉冲频率调制模式。SDB2F5有欠压锁定&#xff0c;限流和热过载保护。 特点&#xff1a; …

链舞算法谱---链表经典题剖析

前言&#xff1a;探究链表算法的奥秘&#xff0c;解锁编程新世界&#xff01; 欢迎来到我的链表算法博客&#xff0c;这将是您深入了解链表算法&#xff0c;提升编程技能的绝佳机会。链表作为数据结构的重要成员之一&#xff0c;其动态性和灵活性在实现某些功能上发挥不可替代的…

深入理解 Java 并发:AbstractQueuedSynchronizer 源码分析

序言 在多线程编程中&#xff0c;同步机制是保障线程安全和协调线程之间操作顺序的重要手段。AQS 作为 Java 中同步机制的基础框架&#xff0c;为开发者提供了一个灵活且高效的同步工具。本文将通过对 AQS 源码的分析&#xff0c;解读 AQS 的核心实现原理&#xff0c;并深入探…

同步互斥问题模型

目录 一. 生产者-消费者问题二. 多生产者-多消费者问题三. 吸烟者问题四. 读者-写者问题五. 哲学家进餐问题 \quad 一. 生产者-消费者问题 \quad 问题分析 \quad 如何实现 \quad \quad V操作不会导致进程阻塞&#xff0c;因此两个v操作顺序可以交换。 \quad 二. 多生产者-多消费…

前端 -- 基础 表单标签 - 表单元素 < Select > < textarea >

在表单域中可以定义各种表单元素&#xff0c;这些表单元素就是允许用户在表单中输入或者选择的内容控件。 在之前&#xff0c;我们就讲过 表单元素 分了 三类来讲 &#xff1a; 1 input 输入表单元素 2 select 下拉表单元素 3 textarea 文本域元素 input 表单元素 我们…

AGI要闻:斯坦福李飞飞首次创业,瞄准“空间智能”;OpenAI下周发布搜索产品挑战谷歌;新的开源 AI 眼镜来了|钛媒体AGI | 最新快讯

多方消息证实&#xff0c;OpenAI将会在北京时间5月10日&#xff08;周五&#xff09;凌晨2点公布搜索引擎新产品消息。 斯坦福大学首位红杉讲席教授 李飞飞 通用人工智能&#xff08;AGI&#xff09;领域又公布了一系列重磅消息。 5月4日凌晨&#xff0c;据路透社&#xff0c…

宝塔怎么配置nginx

宝塔怎么配置nginx 1.找到nginx配置位置 2.修改nginx.conf文件 3.重启nginx

在视频中使用时间卷积和半监督训练进行三维人体姿态估计

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;在视频中使用时间卷积和半监督训练进行三维人体姿态估计1、文献摘要2、提出方法2.1、时间扩张卷积模型2.2、半监督方法2.3、与传统…

Mac OS系统如何更新

用了好几年的Mac Book安装软件经常提示需要更高的系统版本&#xff0c;因此要升级系统版本&#xff0c;但是开始在系统设置里面找了一下没有找到升级的按钮&#xff0c;找了资料后才知道如何升级。有以下两种入口 一、App Store搜索MacOs&#xff0c;在出现的搜索结果中选择下载…

力扣例题(接雨水)

链接&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 思路&#xff1a; 判断一块地方是否可以接到雨水&#xff0c;只需要判断他是否有左右边界使他可以接到水 左右边界分别为此处左侧的最高点和右侧的最高点 同时此处可接雨水的高度为左右两…

离散数学之命题逻辑思维导图+大纲笔记(预习、期末复习,考研,)

大纲笔记&#xff1a; 命题逻辑的基本概念 命题与联结词 命题 命题是推理的基本单位 真命题&#xff0c;假命题 特征 陈述句 唯一的真值 是非真即假的陈述句 非命题 疑问句 祈使句 可真可假 悖论 模糊性 三个基本概念 复合命题 真值取决于原子命题的值和逻辑联结词 原子命题 逻…

微图乐 多种装B截图一键制作工具(仅供娱乐交流)

软件介绍 采用exe进程交互通信。全新UI界面&#xff0c;让界面更加清爽简约。支持zfb、VX、TX、Yin行、Dai款、游戏等图片生成&#xff0c;一键超清原图复制到剪辑板&#xff0c;分享给好友。适用于提高商家信誉度&#xff0c;产品销售额度。装逼娱乐&#xff0c;用微图乐。图…