1751. Maximum Number of Events That Can Be Attended II
1751. Maximum Number of Events That Can Be Attended II
這個題目算是滿好的面試題目,因為雖然他的難度是 Hard ,但是完全是可以透過推理的方式去找出答案,而且其實這滿容易在工作情的業務邏輯出現的。
這個題目會被歸類在 Hard 是因為題目可以從多個難度為 Medium 的題目出發,例如:
- 不考慮會議的重要性,找出所有可以參加的會議
 - 不考慮最多可以參加幾個會議,最後參加會議的權重要最重...等
 
這個題目是給出,題目給定多個會議時間,以及會議的重要性,並且還限制上最多只能參加 k 個會議,找出最後的加權會議重要值為多少。
以下是我的第一個版本:
這個題目又是一個選擇的問題,因此很適合使用動態規劃的方式來寫,我的想法是,在每次選擇的時候我們考量的點是
- 目前我們是不是已經選到足夠的會議數量 
k - 如果還有會議可以選,我可以考慮
- 選擇這個會議,那如果要選擇這個會議要滿足
- 前一個會議的結束時間不能比當前會議晚
 
 
 - 選擇這個會議,那如果要選擇這個會議要滿足
 - 不選擇這個會議
 
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)