算法之线性时间选择(最坏情况下)
轉載自:https://www.cnblogs.com/Not-Famous/p/3653945.html
也可參考:https://www.jianshu.com/p/bf47d7b4a43d 或 https://www.bbsmax.com/A/D854V0EQzE/
線性時間選擇(Linear Select): 這個名字不太好理解,什么叫線性時間選擇?一句話,在線性時間內完成選擇。一般情況下是這樣的,我們想要找出一個數組中的最大值或最小值,那就只需要一次排列,然后輸出第一個或最后一個元素就行了,但如果是要找出一個數組中的第 k 小的元素呢?
在一般情況下,可以用 RandomizedSelect 方法來找出第 k 小的元素,平均時間是 O (n),但在最壞情況下,所用的時間則是 n^2,因此,本文討論的就是在最壞情況下,如何在 O (n) 時間內完成選擇。算法的思路總體有些復雜,但每一步其實不難,下面即給大家介紹最壞情況下的線性時間選擇算法。
(1):將 n 個輸入元素以每組 5 個地劃分,共劃分出 (n/5) 個組,每個組分別進行排列,找出中位數,然后按照每個組的順序,把每個組的中位數與整個數組的前 (n/5) 個數交換;
(2):那么,前 (n/5) 個數就是各組的中位數了,然后,我們通過 select 方法找出這些中位數的中位數,以這個中位數的中位數為基準,調用 partition 方法;
(3):調用了 partition 方法后的基準元素正是處于數組的正確位置(前邊的元素都比基準元素小,后邊的元素都比基準元素大),記下基準元素前邊的元素個數 leftNum,如果 k 小于或等于 leftNum,則在基準位置前的這部分調用 select 方法即可,如果在 k 大于 leftNum,則在基準位置后的這部分調用 select 方法。
下面,我直接把代碼貼出,讀者可以通過我的注釋來理解每一步的意義。
復制代碼
復制代碼
到此大家也可以看出,這里的 partition 方法與前邊講到過的快速排序所用到的 partition 方法稍有不同,參數個數都變了,但其實變化只是很小,只是取消了一開始定義基準位置的步驟而已,代碼如下:
復制代碼
復制代碼
下面是 select 方法中,如果輸入規模小于 75 時用到的插入排序算法代碼:
復制代碼
復制代碼
適用于數組元素之間的 swap 方法如下:
1 private static void swap(int[] a,int i,int j){ 2 int temp = a[i]; 3 a[i] = a[j]; 4 a[j] = temp; 5 }各位可能有個疑問,為什么輸入規模不足 75 時調用插入排序而不用線性時間選擇呢?那是因為當輸入規模不足 75 時,因為輸入規模太小,時間復雜度幾乎是一個常量,因此沒有必要用到比較復雜的線性時間選擇算法。
我還看到一個比較好懂的學習線性時間選擇的動畫,能形象地看到線性時間選擇的執行過程,鏈接如下:
http://resource.jingpinke.com/details?uuid=ff808081-22e8911b-0122-e8912643-048d&objectId=oid:ff808081-22e8911b-0122-e8912643-048e
如果有不足之處或者對該算法有更好的建議,請提出!
總結
以上是生活随笔為你收集整理的算法之线性时间选择(最坏情况下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [html] 举例说明实现文字贯穿线的
- 下一篇: [html] 请说说input的inp