線性時間查詢
問題描述:
給定線性序集中n個元素和一個整數k,1 <= k <= n
,要求找出這n個元素中第k小的元素,即如果將這n個元素以其線性序列排列時,排在第k個位置的元素係為要找的元素。當k = 1
時,就是要找最小元素,當k = n
時,就是要找最大元素;當k = (n + 1) / 2
時,稱為找中位數。
分析:
先考慮一個時間要求不嚴格的演算法,由快速排序可以得到啟發:
- 每次依照某個基準元素將序列劃分為兩部分
(1)
:一部分小於等於基準(2)
:一部分大於基準- 接下來就可以只處理這兩部分中的一部分,如果:
|(1)| < k
,則k一定在(2)
中,問題變成(2)
中的k - |(1)|
選擇。- 否則問題變成
(1)
中的k選擇。
- 這樣問題就可以遞迴求解了。
但是這個問題和快速排序有同樣的弊端:最壞情況下會有O(n ^ 2)
的時間複雜度。這主要取決於基準的選擇。
針對這樣的問題,第一種應對辦法也是與快速排序一樣,隨機化基準選擇。但(從最壞分析的形況看)這不能根本解決問題。
現在考慮如何能夠縮小劃分基準,實際上,我們不必希望劃分基準能夠總是均分序列,只要能夠保證總是將序列至少划走某一比例(0 < e < 1
)就行了。
於是,有k = 1
, m = e^-1
:
T(1) = O(1) (n = 1)
T(n) = T(n * e) + O(n) (n > 1)
因為k為1,即將T(n)
完全展開有:
O(n) + O(n * e) + O(n * e ^ 2) + O(n * e ^ 3) + ... + O(1)
這是一個幾何級數,其加和與n同階,即演算法複雜度為O(n)
。
如何尋找這樣一個基準?
方法是建立一種二級機制選中位數機制(以下討論假設沒有重複元素):
- 先將問題序列P按某常數a分割為
|P| / a
組,即每組a個元素(最後一組可能不足a個元素) - 對這些組分別排序,因為a是常數,每組的排序時間消耗也為
O(1)
,總時間消耗為O(n)
- 選出這
|P| / a
組的中位數,用本演算法找出它們的中位數(mid),這一部分的複雜度為T(n / a)
因為上述步驟的mid大於一半的中位數,也大於對應小陣列的一半,即保證mid大於P中1 / 4
的元素,即保證劃分後至少將P縮減1 / 4
,而整個演算法有
T(1) = O(1) (n = 1)
T(n) = T(n / a) + T(n * 3 / 4) + O(n) (n > 1)
根據前面的討論:e = 1 / a + 3 / 4 < 1
,即a > 4
重複情況分析:
剛才的討論中要求元素不重複,實際上,如果元素重複,演算法有可能失效(等於基準的元素過多則不保證能夠划走至少1 / 4
,比如當所有元素相同時,演算法將無法終止)。不過修正這一點也不困難,只要在劃分完成後,且進入(1)中部分,則對等於基準的元素進行考察,設有x個等於基準的元素集中在(1)
的尾部,如果|(1)| - x < k
,則返回k,否則將(1)
中等於基準的元素去掉再求解。
補充
可以看到這個演算法常數比較大,所以,可以考慮當n小於某個閾值後將演算法改為排序+取第k位。
疑惑
書上說(書上取a = 5
且有閾值 = 75
作為分界):
由於演算法將每一組的大小定為5,並去75作為是否進行遞迴呼叫的分界點。這兩點保證了T(n)的遞迴式中兩個自變數之和
n / 5 + 3n / 4 = 19n / 20 = an, 0 < a < 1
。這是使T(n) = O(n)
的關鍵之處。
對於這裡75的作用我還不理解,對於T(n) = T(n / a) + T(n * 3 / 4) + O(n) (n > 1)
到e = 1 / a + 3 / 4 < 1
也不能講清楚。
相關文章
- 查詢與排序01,線性查詢,時間複雜度,演算法排序時間複雜度演算法
- JPA時間段查詢
- MySQL查詢時間段MySql
- SQL時間段查詢SQL
- 線性查詢演算法演算法
- Mysql 查詢時間轉換MySql
- Oracle日期時間範圍查詢Oracle
- Mysql中查詢系統時間MySql
- 查詢時間從前7天到當前時間
- Laravel MongoDB 時間區間查詢的問題LaravelMongoDB
- 陣列的查詢(搜尋):線性查詢和二分法查詢陣列
- 線性時間構造最大堆
- ssl證書到期時間查詢方法
- 查詢https證書到期時間HTTP
- 如何實現模糊查詢時間段
- 使用.NET查詢日出日落時間
- JN專案-時間查詢,結束時間比開始時間小給提示
- 查詢一個表插入資料的時間,按BLOCK時間BloC
- 芻議線段樹 2 (區間修改,區間查詢)
- Oracle查詢回滾大事務所需時間Oracle
- 查詢某個表最後修改時間
- vue+element-ui根據時間查詢VueUI
- 離線查詢與線上查詢
- 臨時表空間的空間使用情況查詢
- 查詢時若時間為空,開始時間取今天的零點,結束時間取當前時間
- 連線查詢
- 關於日期及時間欄位的查詢
- mysql查詢最近時間的一組資料MySql
- Mysql按時間分組查詢(每天|每月|每年)MySql
- JN專案-時間查詢條件驗證
- 關於Oracle資料庫的時間查詢Oracle資料庫
- 查詢某時間段的統計資料
- Oracle下查詢臨時表空間佔用率Oracle
- oracle 表空間,臨時表空間使用率查詢Oracle
- 蘋果啟用時間怎麼查詢?蘋果iPhone XR查詢保修日期的方法蘋果iPhone
- 透過DMV查詢CPU時間最長的語句和查詢計劃
- mysql-分組查詢-子查詢-連線查詢-組合查詢MySql
- openGauss 檢查時間一致性