【每日一题Day323】LC630课程表 III | 动态规划 反悔贪心

简介: 【每日一题Day323】LC630课程表 III | 动态规划 反悔贪心

课程表 III【LC630】](https://leetcode.cn/problems/course-schedule-iii/)

这里有 n 门不同的在线课程,按从 1 到 n 编号。给你一个数组 courses ,其中 courses[i] = [durationi, lastDayi] 表示第 i 门课将会 持续 上 durationi 天课,并且必须在不晚于 lastDayi 的时候完成。

你的学期从第 1 天开始。且不能同时修读两门及两门以上的课程。

返回你最多可以修读的课程数目。

interesting

动态规划
  • 思路

image.png

实现

class Solution {
    public int scheduleCourse(int[][] courses) {
        Arrays.sort(courses, (o1, o2) -> o1[1] - o2[1]);
        int n = courses.length;
        int maxTime = courses[n - 1][1];
        int[] dp = new int[maxTime + 1];// 截至日期为i时最多可以完成的课程数
        for (int[] course : courses){
            for (int j = course[1]; j >= course[0]; j--){
                dp[j] = Math.max(dp[j - course[0]] + 1, dp[j]);
            }
        }
        int res = 0;
        for (int count : dp){
            res = Math.max(res, count);
        }
        return res;
    }
}

复杂度

时间复杂度:O(n \log n+n^2)

空间复杂度:O ( log ⁡ n + n )

反悔贪心
  • 思路
  • 局部最优:结束时间较早的课程优先进行
  • 反悔贪心:当某一时刻能够完成的课程数量相同时,优先完成时长较短的课程,以使后续能完成更多的课程
  • 全局最优:相同时间上更多的课
  • 实现
    使用大顶堆存储每门课程的耗时,并记录当前所有课程的总耗时time
  • 如果能完成当前课程,那么time增加course[0],将该课程放入堆中
  • 如果不能完成当前课程,那么判断能否减少总耗时
  • 如果能将堆顶元素移除,将该课程放入堆中
  • 如果不能,不做任何操作
  • 最后返回堆中元素个数
class Solution {
    public int scheduleCourse(int[][] courses) {
        Arrays.sort(courses, (a, b) -> a[1] - b[1]); // 按照 lastDay 从小到大排序
        PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a); // 最大堆
        int day = 0; // 已消耗时间
        for (int[] c : courses) {
            int duration = c[0], lastDay = c[1];
            if (day + duration <= lastDay) { // 没有超过 lastDay,直接学习
                day += duration;
                pq.offer(duration);
            } else if (!pq.isEmpty() && duration < pq.peek()) { // 该课程的时间比之前的最长时间要短
                // 反悔,撤销之前 duration 最长的课程,改为学习该课程
                // 节省出来的时间,能在后面上完更多的课程
                day -= pq.poll() - duration;
                pq.offer(duration);
            }
        }
        return pq.size();
    }
}
作者:灵茶山艾府
链接:https://leetcode.cn/problems/course-schedule-iii/solutions/2436667/tan-xin-huan-neng-fan-hui-pythonjavacgoj-lcwp/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度

时间复杂度:O ( n log ⁡ n )

空间复杂度:O ( n )

目录
相关文章
|
监控 数据可视化 前端开发
高效管理团队表现:构建可视化的贡献度面板组件
高效管理团队表现:构建可视化的贡献度面板组件
233 0
|
11月前
|
存储 网络协议 Java
【网络】UDP回显服务器和客户端的构造,以及连接流程
【网络】UDP回显服务器和客户端的构造,以及连接流程
226 3
|
10月前
|
缓存 NoSQL 中间件
redis高并发缓存中间件总结!
本文档详细介绍了高并发缓存中间件Redis的原理、高级操作及其在电商架构中的应用。通过阿里云的角度,分析了Redis与架构的关系,并展示了无Redis和使用Redis缓存的架构图。文档还涵盖了Redis的基本特性、应用场景、安装部署步骤、配置文件详解、启动和关闭方法、systemctl管理脚本的生成以及日志警告处理等内容。适合初学者和有一定经验的技术人员参考学习。
725 7
|
10月前
|
存储 小程序 API
深入调查研究Memos
【11月更文挑战第1天】
230 7
|
安全 物联网 数据安全/隐私保护
车联网
对于车联网的操作,我们可以按照以下步骤进行,这些步骤涵盖了从初始设置到日常使用的大部分关键流程。请注意,具体步骤可能会因车型、汽车制造商以及所选的服务提供商而有所不同。
|
开发者
🔥揭秘JSF导航:如何轻松驾驭页面跳转与流程控制?🎯
【8月更文挑战第31天】在 JavaServer Faces(JSF)中,导航规则是控制页面跳转和流程的关键。本文详细介绍 JSF 的导航规则,包括转发和重定向等跳转方式,并通过 `faces-config.xml` 文件配置示例展示如何实现不同场景下的页面跳转及流程控制,帮助开发者有效管理应用程序的页面流和用户交互,提升应用质量。
141 0
|
网络协议 安全 文件存储
Potplayer结合cpolar内网穿透实现公网访问群晖WebDAV
Potplayer结合cpolar内网穿透实现公网访问群晖WebDAV
267 1
|
数据可视化 数据挖掘 C++
数据分析综合案例讲解,一文搞懂Numpy,pandas,matplotlib,seaborn技巧方法
数据分析综合案例讲解,一文搞懂Numpy,pandas,matplotlib,seaborn技巧方法
416 2
|
Linux
CentOS yum源设置为国内aliyun yum源
CentOS yum源设置为国内aliyun yum源
8119 0
|
负载均衡 算法 云计算
深入理解负载均衡:优化你的网络性能
在今天的数字时代,网络性能和可用性对于任何企业或组织都至关重要。负载均衡是一个关键的网络架构组件,可以帮助分散流量、提高可靠性和确保系统的高可用性。本文将深入探讨负载均衡的概念、工作原理以及在现代网络中的应用。