由於專案中直播間實際會控制最大人數在6人,而直播間存續時長一般也不會超過24小時,所以開始時偷了點懶,採用暴力方式處理。
暴力解法
顯然這是乙個n²複雜度的演算法,如果每乙個時間段,都會被其他所有時間段分割,那麼輸入的n個時間段最終會產生2n-1個時間段,所以實際上會比n²還要耗時,開始以為偷懶的暴力方法,事實證明,一點也不省事兒,實現**如下
type timesectionlist struct
type timesection struct
func
(this *timesectionlist)
mergets
(us, ue int64
)else
if e > t.s && e < t.e
) t.overlap, t.e = t.overlap+
1, e
return s, t.s,0,
0}else
if e == t.e
}else
if s > t.s
) this.tss =
(this.tss,
×ection
) t.s, t.e, t.overlap = s, e, t.overlap+
1return0,
0,0,
0}else
if s < t.e && e > t.e
) t.overlap++
t.s = s
return0,
0, t.e, e
}else
if e == t.e
) t.s = s
t.overlap++
return0,
0,0,
0}}else
else
if e < t.e
) t.overlap++
t.e = e
return0,
0,0,
0}else
if e == t.e }}
this.tss =
(this.tss,
×ection
)return0,
0,0,
0}hs, ht, ts, te :=
check
(us, ue)
if hs !=
0if ts !=0}
func
(this *timesectionlist)
getmaxduration
() timesecion
else
if ts.overlap == max }}
return timesecion
}
除了效能不高外,實際的實現過程,需要考慮九種情況,包含各種起止時間重疊的情形。好在業務規模有限,也勉強撐著了。
優化思路
雖然這個功能不就就被下線了,但是心裡有塊石頭始終放不下,實在是對n²複雜度不滿意。
一開始考慮能否使用查詢樹來解決,但是由於時間段包含起始結束時間兩個元素,所以這將會是乙個定製的查詢樹,實現起來比暴力方法複雜,所以放棄了這個思路。
某日突然發覺,似乎棧非常適合用來解決這個問題。開始時間對應壓棧,離開時間對應彈棧,棧內元素最多時,不就是想要的結果嗎?
重複上一動作,lend被清空,此時n=2,stime=9:18,etime=9:20,至此演算法結束
優化分析
綜合來看,排序部分為nlogn的複雜度,出入棧操作為n,整體複雜度從暴力演算法的n²下降到nlogn,實際專案應用中,起止時間儲存在資料庫中,如果庫中對在時間列上有b+tree索引,則排序部分複雜度可以下降為n,那麼整體的複雜度就是線性複雜度了。
排序部分**就不寫了,下面是棧操作**
func
maxtimeduration
(start, end [
]time.time)
(int
, time.time, time.time)
else
if l == max
}else}}
forlen
(start)
>
0else
if s.
after
(e)}
closetime
(end[0]
)return max, ts, te
}
關於sql語句中,統計時間重疊和時間不重疊
我們在開發過程中總會遇到這樣的情況,一行資料中,有id 組 開始時間 結束時間。但是開始時間和結束時間肯定會出現時間重疊問題,比如說下面這種情況。我們先找出時間重疊的公式 可以發現 公式如下 a.alarm type id b.alarm type id and a.start time b.sto...
KMP演算法計算出現次數(包含重疊部分)
kmp演算法 返回模式串在文字串 現的次數。例如 abdabdababdab 中 abdab 在 0,4 3,7 8,12 出現,則返回3 主要的改動在kmp函式中的while迴圈 include using namespace std void getnext const char ps,int ...
關於遞迴次數的計算
有這樣乙個題目 遞迴函式 1 int x intn 2 7else 811 計算x x 8 遞迴呼叫次數。大多數可能覺得這是乙個很簡單的題目,的確很簡單。但是要想在沒有編譯器的情況下正確的算出這個遞迴 呼叫次數其實還是需要點耐心.x x 8 我們先計算x 8 我們用count 0計數遞迴呼叫次數 1...