區間排程問題共寫了3片部落格,前兩篇重疊區間和區間合併分別講了區間的最大不相交子集和重疊區間的合併
,今天再寫乙個演算法,可以快速找出兩組區間的交集
。
一、解題思路
解決區間問題的思路一般是先排序
,以便操作,不過題目說已經排好序了,那麼可以用兩個索引指標在 a 和 b 中游走,把交集找出來
,**大概是這樣的:
不難,我們先老老實實分析一下各種情況。# a, b 形如 [[0,2],[5,10]...]
defintervalintersection
(a, b)
: i, j =0,
0 res =
while i <
len(a)
and j <
len(b)
:# ...
j +=
1 i +=
1return res
首先,對於兩個區間,我們用 [a1,a2] 和 [b1,b2] 表示在 a 和 b 中的兩個區間,那麼什麼情況下這兩個區間沒有交集呢:
只有這兩種情況,寫成**的條件判斷就是這樣:
那麼,什麼情況下,兩個區間存在交集呢?根據命題的否定,上面邏輯的否命題就是存在交集的條件:if b2 < a1 or a2 < b1:
[a1,a2] 和 [b1,b2] 無交集
接下來,兩個區間存在交集的情況有哪些呢?# 不等號取反,or 也要變成 and
if b2 >= a1 and a2 >= b1:
[a1,a2] 和 [b1,b2] 存在交集
窮舉
出來:
這很簡單吧,就這四種情況而已。那麼接下來思考,這幾種情況下,交集是否有什麼共同點呢?
我們驚奇地發現,交集區間是有規律的!如果交集區間是 [c1,c2],那麼 c1=max(a1,b1),c2=min(a2,b2)!這一點就是尋找交集的核心,我們把**更進一步:
最後一步,我們的指標 i 和 j 肯定要前進(遞增)的,什麼時候應該前進呢?while i <
len(a)
and j <
len(b)
: a1, a2 = a[i][0
], a[i][1
] b1, b2 = b[j][0
], b[j][1
]if b2 >= a1 and a2 >= b1:
[max
(a1, b1)
,min
(a2, b2)])
# ...
是否前進,只取決於 a2 和 b2 的大小關係
。**:
完整**:while i <
len(a)
and j <
len(b)
:# ...
if b2 < a2:
j +=
1else
: i +=
1
c++**:# a, b 形如 [[0,2],[5,10]...]
defintervalintersection
(a, b)
: i, j =0,
0# 雙指標
res =
while i <
len(a)
and j <
len(b)
: a1, a2 = a[i][0
], a[i][1
] b1, b2 = b[j][0
], b[j][1
]# 兩個區間存在交集
if b2 >= a1 and a2 >= b1:
# 計算出交集,加入 res
[max
(a1, b1)
,min
(a2, b2)])
# 指標前進
if b2 < a2: j +=
1else
: i +=
1return res
總結一下,區間類問題看起來都比較複雜,情況很多難以處理,但實際上通過觀察各種不同情況之間的共性可以發現規律,用簡潔的**就能處理。class solution
//i和j兩個下標索引
int i =0;
int j =0;
while
(i < a.
size()
&& j < b.
size()
));}
//更新i和j下標索引,b2 < a2 就代表i所在的區間大於j所在的區間,更新j
//是因為i區間長於j區間的部分還可能和j的下乙個區間繼續重疊,還需要繼續判斷
//所以更新j而不是更新i
if(b2 < a2)
else
//反之同理
}return ret;}}
;
區間排程之區間合併問題
還是先看一道題 一 解題思路 乙個區間可以表示為 start,end 區間重疊區間排程問題,需要按 end 排序,以便滿足貪心選擇性質。而對於區間合併問題,其實按 end 和 start 排序都可以,不過為了清晰起見,我們選擇按 start 排序。顯然,對於幾個相交區間合併後的結果區間 x,x.st...
區間排程問題之區間合併
上篇文章用貪心演算法解決了區間排程問題 給你很多區間,讓你求其中的最大不重疊子集。我們解決區間問題的一般思路是先排序,然後觀察規律。乙個區間可以表示為 start,end 前文聊的區間排程問題,需要按end排序,以便滿足貪心選擇性質。而對於區間合併問題,其實按end和start排序都可以,不過為了清...
區間排程之區間 合併
思路按照區間的左端點,右端點從小道大排序。遍歷每乙個區間,若當前區間curr.start last.end,證明區間有可能有交集,需要更新上乙個區間last.end的值。若curr.start last.end 證明兩個區間不可能有交集。include include include using n...