返回

LeetCode 630:课程表 III

后端

题目

给你一个整数 n 和一个整数数组 times,其中 times[i] = [startTimei, endTimei] 表示第 i 门课程的开始时间和结束时间。

课程只能按照它们的 开始时间 排序进行。如果你在第 i 门课程的开始时间之前完成了第 i-1 门课程,你就可以参加第 i 门课程。

如果可以安排课程,使得你参加每门课程都 不迟于 其结束时间,请你返回 true;否则,返回 false。

示例 1:

输入:n = 3, times = [[1,3],[6,10],[11,15]]
输出:true

示例 2:

输入:n = 2, times = [[1,2],[2,3]]
输出:false

示例 3:

输入:n = 3, times = [[1,3],[2,4],[3,5]]
输出:true

提示:

  • 1 <= n <= 10^4
  • 1 <= times.length <= 10^5
  • 1 <= startTimei <= endTimei <= 10^9

思路分析

贪心算法

这道题的本质是,选择一种课程安排策略,使得尽可能多的课程在课程结束之前完成。我们可以使用 贪心算法 来解决这个问题。

贪心算法的基本思想是,在每个决策点上做出局部最优的选择,希望最终得到全局最优解。在这道题中,我们可以在每个时刻选择一个课程来参加,使得这个课程的结束时间最小。

实现步骤

使用有序队列或大顶堆来存储所有课程的结束时间。

  1. 初始化一个有序队列或大顶堆,并将其中的元素设置为所有课程的结束时间。
  2. 循环进行以下操作,直到有序队列或大顶堆为空:
    • 从有序队列或大顶堆中取出最小的结束时间。
    • 检查这个结束时间是否大于或等于当前时间。
      • 如果是,则将当前时间更新为这个结束时间。
      • 否则,返回 false。
  3. 如果有序队列或大顶堆为空,则返回 true。

代码示例

def scheduleCourse(times):
    """
    :type times: List[List[int]]
    :rtype: bool
    """
    # 将课程按结束时间升序排序
    times.sort(key=lambda x: x[1])

    # 使用有序队列存储所有课程的结束时间
    pq = []

    # 当前时间
    current_time = 0

    # 循环进行以下操作,直到有序队列为空
    while pq:
        # 从有序队列中取出最小的结束时间
        end_time = heapq.heappop(pq)

        # 检查这个结束时间是否大于或等于当前时间
        if end_time >= current_time:
            # 更新当前时间
            current_time = end_time
        else:
            # 返回 false
            return False

    # 如果有序队列为空,则返回 true
    return True

复杂度分析

  • 时间复杂度:O(n log n),其中 n 为课程的数量。这是因为我们使用有序队列或大顶堆来存储所有课程的结束时间,而有序队列或大顶堆的操作时间复杂度为 O(log n)。
  • 空间复杂度:O(n),这是因为我们使用有序队列或大顶堆来存储所有课程的结束时间。