給定兩個左閉右開時間段 [A, B)、[X, Y),如何判斷它們是否有交集?
由於時間可以轉換為時間戳,時間戳是一個數字,所以我們可以將問題轉換為:如何判斷兩個左閉右開的數字區間是否有交集。
結論是如果 X < B AND A < Y
,那么有交集,證明過程見下方。
數軸示意圖
這是一個不完善的、不容易思考的證明。
我將他們想象成數軸上的兩段:
-------A.------B。------X.-------Y。------
“.” 表示閉區間,“。”表示開區間。
然后令 [A, B) 不動,向左一直移動 [X, Y)。先是 X 進入 [A, B),然后是 X 離開 [A, B),Y 進入 [A, B)。所以只要 X 或 Y 在 [A, B) 間,那么兩者有交集。
上述算法遺漏了兩種情況,[X, Y) 完全在 [A, B) 中或者[A, B) 完全在 [X, Y) 中:
[X, Y) 完全在 [A, B):
-----A.-----X.----Y。----B。-----
所以這種證明方法不好,雖然比較形象,但是因為變量太多,容易遺漏。
使用排列組合[1]
使用排列組合獲取所有的可能情況,並定義當前數小於等於下一個數字(因為這樣定義就能包含所有的情況):
Python 代碼:
from itertools import permutations
for x in list(permutations('ABXY')):
# 由於 A < B,X < Y,所以 A 的位置一定在 B 前面,X 的位置一定在 Y 前面
if x.index('A') < x.index('B') and x.index('X') < x.index('Y'):
print(x)
上方的輸出為:
('A', 'B', 'X', 'Y') # 因為 [A, B) 的最大值 < B 然后 B < X,然后 X 是 [X, Y) 的最小值,所以 [A, B) 的最大值小於 [X, Y) 的最小值,所以兩者無交集。
('A', 'X', 'B', 'Y') # 當 X = B 時,無交集,其余情況有交集。
('A', 'X', 'Y', 'B') # 有交集
('X', 'A', 'B', 'Y') # 有交集
('X', 'A', 'Y', 'B') # 當 A = Y 時,無交集,其余情況有交集
('X', 'Y', 'A', 'B') # 無交集,與第一個的證明類似
所以無交集的所有可能情況是,A <= B <= X <= Y、X = B、A = Y、X <= Y <= A <= B。由於 A < B、X < Y,所以只要 B <= X,那么 A <= X,所以 A <= B <= X <= Y 變為 B <= X <= Y,同理可得 X <= Y <= A <= B => Y <= A <= B。去除條件自帶的 A < B、X < Y 的情況后,為 B <= X、X = B、A = Y、Y <= A,由於 B <= X 包含 X = B,Y <= A 包含 Y= A,所以 B <= X 或 Y <= A,對其取反,得到有交集的情況:X < B AND A < Y
。
這里的證明是通過排列組合,獲取了所有的情況,然后從整理所有沒有交集的情況(更少的情況),然后推導出規律。