區間問題的貪心方法

R_0nnie發表於2020-12-03

一.區間選點

題目描述

給定N個閉區間[ai,bi],請你在數軸上選擇儘量少的點,使得每個區間內至少包含一個選出的點,輸出選擇的點的最小數量。
(位於區間端點上的點也算作區間內。)

問題解法

1)將區間的右端點從小到大排序
2)從前往後列舉每個區間,如果這個區間包含已經選擇的點,則跳過。否則,將該區間的右端點加入選擇點的集合。

問題證明

選擇到某個區間時,如果已經選擇點都不在區間中,說明該區間與之前的所有選擇點的區間都沒有相交的部分(區間左端點在已經選定的點右邊),則加入選擇點的集合。如果在區間中,則無需作操作。因為區間是根據右端點來進行排序的,所以選擇點時,當前區間必然都是與前面各個選擇點時的區間互不相交的。假設最後選擇了n個點,則必然有這n段互不相交的區間,這n段區間至少需要n個點來包含,根據最優性,最少選擇n個點即可被所有區間包含。



二.最大不相交區間數量

題目描述

給定N個閉區間[ai,bi],請你在數軸上選擇若干區間,使得選中的區間之間互不相交(包括端點),輸出可選取區間的最大數量。

問題解法(與第一題相同)

1)將區間的右端點從小到大排序
2)從前往後列舉每個區間,如果這個區間包含已經選擇的點,則跳過。否則,將該區間的右端點加入選擇點的集合。

問題證明

設最大不相交區間的數量為ans,由上述解法,可得不相交區間的數量為n。
顯然可得①ans>=n
下面證明②ans<=n, 反證ans>n是錯誤的
如果ans>n,即有至少n+1段互不相交的區間,則要至少n+1個點才能需要覆蓋所有區間,而又有第一題得,上述解法得到只需n個點即可覆蓋所有區間。所以ans>n是錯誤的

綜上可得ans == n



三.區間分組

題目描述

給定N個閉區間[ai,bi],請你將這些區間分成若干組,使得每組內部的區間兩兩之間(包括端點)沒有交集,並使得組數儘可能小。輸出最小組數。

問題解法

1)將區間的左端點從小到大排序
2)從前往後列舉每個區間,判斷這個區間能否加入已有的組中。即記錄每個已有組中的各個區間的最大右端點max_r。判斷當前區間的左端點L,如果存在區間max_r<L,則加入當前組(對於滿足條件的組,當前區間加入其中任何一個都可以,因為列舉下一個區間的時候,下一個區間的L一定大於當前區間的L)。如果不存在,則開一個新組。

問題證明

假設需要的最少組數為ans,上述解法得到的最少組數為cnt
①易得ans<=cnt
下面證明②ans>=cnt.
假設當前已經列舉到了某段區間,目前已經有了cnt - 1個組,且這cnt-1個組都不滿足當前區間可以加入的條件,即可以得到對於當前區間的端點L,都有cnt-1個組的max_r>=L,又因為每個區間都是從左端點小到大列舉,所以從[L, max_r]這段座標,必有cnt個區間有重合。這cnt個區間需要放在不同的 組,所以ans>=cnt
因此ans == cnt



四.區間覆蓋

題目描述

給定N個閉區間[ai,bi]以及一個線段區間[s,t],請你選擇儘量少的區間,將指定線段區間完全覆蓋。
輸出最少區間數,如果無法完全覆蓋則輸出-1。

問題解法

1)將區間的左端點從小到大排序
2)從前往後列舉每個區間,從所有能夠覆蓋start的區間中,選出右端點最大的那個區間,並更新start為右端點的值



– 思路源自yxc大佬

相關文章