Skip to content

1751. Maximum Number of Events That Can Be Attended II

Coding5 min read

1751. Maximum Number of Events That Can Be Attended II

這個題目算是滿好的面試題目,因為雖然他的難度是 Hard ,但是完全是可以透過推理的方式去找出答案,而且其實這滿容易在工作情的業務邏輯出現的。

這個題目會被歸類在 Hard 是因為題目可以從多個難度為 Medium 的題目出發,例如:

  1. 不考慮會議的重要性,找出所有可以參加的會議
  2. 不考慮最多可以參加幾個會議,最後參加會議的權重要最重...等

這個題目是給出,題目給定多個會議時間,以及會議的重要性,並且還限制上最多只能參加 k 個會議,找出最後的加權會議重要值為多少。

以下是我的第一個版本:

這個題目又是一個選擇的問題,因此很適合使用動態規劃的方式來寫,我的想法是,在每次選擇的時候我們考量的點是

  1. 目前我們是不是已經選到足夠的會議數量 k

  2. 如果還有會議可以選,我可以考慮

    1. 選擇這個會議,那如果要選擇這個會議要滿足
      1. 前一個會議的結束時間不能比當前會議晚
  3. 不選擇這個會議

class Solution:
    def maxValue(self, events: List[List[int]], k: int) -> int:
        events.sort(key=lambda x: x[1])
        
        @cache
        def dp(i, lastEndDay, selected):
            if i == len(events) or selected == k:
                return 0

            startDay, endDay, val = events[i]

            skip = dp(i + 1, lastEndDay, selected)
            pick = 0
            if startDay > lastEndDay:
                pick = val + dp(i + 1, endDay, selected + 1)
            return max(skip, pick)
        return dp(0, float('-inf'), 0)

不過雖然這個解答是對的,但是由於多了一個 lastEndDay 這個變數,會導致需要記憶的數量太多,導致記憶體不足。

這裡需要換一點思路來想,那就是如果現在我們選擇當前這個 event 了,是不是可以更快速的找到下一個?先前的方式如果說一個 event 的跨度很大,其實會有非常多的浪費。

class Solution:
    def maxValue(self, events: List[List[int]], k: int) -> int:
        events.sort()
        start_days = [e[0] for e in events]
        
        @cache
        def dp(i, remaining):
            if i == len(events) or remaining == 0:
                return 0
            
            # skip this event
            res = dp(i + 1, remaining)
            
            # pick this event
            _, end, value = events[i]
            next_i = bisect_left(start_days, end + 1)
            res = max(res, value + dp(next_i, remaining - 1))
            return res

        return dp(0, k)