周賽 400。

題目

輸入正整數 days,代表你從第 1 天到第 days 天都要工作。
另外輸入二維整數陣列 meetings,其中 meetings[i] = [start_i, end_i],代表第 i 次開會的起始日期 (包含首尾)。

求有多少工作日是不用開會的。

注意:會議期間可能重疊。

解法

將 meeting 排序之後,可以知道哪場會議先開始。
但多場會議可能在同天開始、不同天結束。為確保知道最晚的結束日期,需要再以結束日期遞減排序。

維護空閒的起始日期 curr,並遍歷排序好的 meetings。
從 curr 到開始日 s 的前一天是空閒的,將空閒日數加入答案。
而直到結束日 e 的都沒空,以結束日的下一天 e + 1 更新下次的空閒日起始。

別忘記所有會議結束後,一直到第 days 天都是空閒的!

時間複雜度 O(N log N)。
空間複雜度 O(1)。

class Solution:
    def countDays(self, days: int, meetings: List[List[int]]) -> int:
        meetings.sort(key=lambda x:(x[0], -x[1]))
        ans = 0
        curr = 1
        for s, e in meetings:
            # [curr, s - 1] is free
            ans += max(0, s - 1 - curr + 1)
            # [s, e] is not free
            curr = max(curr, e + 1)
            
        # no more meetings
        # [curr, days] is free
        ans += max(0, days - curr + 1)
        
        return ans

會議日期可能重疊,不如先找出哪幾天有開會。
問題轉換成區間合併

合併完之後,從 days 扣掉有會議的天數即可。

時間複雜度 O(N log N)。
空間複雜度 O(N)。

class Solution:
    def countDays(self, days: int, meetings: List[List[int]]) -> int:
        meetings.sort()
        
        a = []
        for s, e in meetings:
            if a and a[-1][1] >= s:
                a[-1][1] = max(a[-1][1], e)
            else:
                a.append([s, e])
               
        ans = days
        for s, e in a:
            ans -= e - s + 1
            
        return ans