排序算法-線性時間復雜度


    一說到排序算法,大部分人都會說出著名的萬金油-快速排序、大數據分而治之-歸並排序、大數據排名-堆排序。這些排序無論在面試還是實際項目中,都是經常用到的一些排序算法,其平均時間復雜度都在 O(N • log2N),那今天我們就來介紹幾種 O(N)的排序算法。

    1,計數排序,輸入 n 個范圍在 0-k 區間的元素,當 !k >> n 時,排序的運行時間為 O(N)

          論點:對於輸入的任一的元素 x,如果有 s 個元素小於,則元素 x 就可以放在 s+1 的位置上,這個時間復雜度近乎 O(1),我們僅需要得出對於每個元素有多少個小於的元素的列表即可在很短的時間內排序完成。

          a.對原數組進行遍歷,計算每個元素出現的次數,時間復雜度 O(N),空間復雜度 O(K)

            原數組

            

 

     額外記錄表,下標為元素,值代表出現的次數

         b,將記錄的數組進行計算整理,數組中每個值代表小於當前下標的元素個數,時間復雜度O(K)

額外記錄表,下標為元素,值代表小於當前下標的元素個數

 

         c.遍歷原數組,並按最初提出的論點,進行最終的排序放置到最終數組,並更新記錄表中的數值(v-1),時間復雜度O(N) * O(1),空間復雜度O(N)

 

         綜上所述,所需要的時間復雜度為O(N) + O(K) + O(N)*O(1) = O(N + K),當元素的取值范圍較小時,可以達到 O(N)的時間復雜度,空間復雜度為O(N) + O(K) = O(N)

    2,基數排序,建立在計數排序(發現兩種排序的諧音完全一樣^_^)的基礎上,所以請耐心閱讀上一段的流程。

          論點:在實際項目過程中,我們需要排序的元素通常很難是在極小范圍,這里我們可以利用位數的分隔,首先對所有數值的個位數進行計數排序,以此類推對十位、百位、千位。可以預見我們僅需要對當前元素組進行最大元素的位數次計數排序即可

                     假定最大元素為 x,則進行的計數排序個數為 r = ceil(ln(x)) 取上整數,每次計數排序的時間復雜度為 O(N + K) = O(N + 10) 整個算法復雜度為 ceil(ln(x)) * O(N + 10),所以當最大一位的位數不會超過 ln(N),則整個排序算法的復雜度為 位數 * O(N + 10) = O(N),這種排序算法一般已經可以應用到很多項目場景中了,只是因為其編碼的復雜度和現代計算機的 cpu 性能提高,所以除非巨量的數據排序,否則一般還是會采用快速排序

 

    3,桶排序,與基數排序是相反的思路,先生成 n 個相同大小的子區間(桶),將所有元素分到所屬的桶內,並按插入排序的方式,放入所屬的桶里,時刻保證每個桶內部的數據是有序的。

          論點:只要數據處於散列數據,可以預見每個桶的數據不會太多,除非極端情況下,但只要保證桶的個數,同樣可以保證算法的線性時間復雜度(這里先不談這種情況,這種已經類似於數值與數組下標逆向,需要消耗大量的空間);

          a.生成 n 個桶,並設定每個桶的取值范圍(可以去最大值后,向 n 倍數取上整,便於 hash 計算),時間復雜度 O(N),空間復雜度O(N),

          b.遍歷整個數組,將元素放入所屬桶,並根據插入排序保持桶的有序,時間復雜度 ∑n-1i=0(啊~!不會用這個數學符號編輯啊)O(ni2),其中 ni 表示每次插入排序時當前桶的數量。

          綜上所述,時間復雜度的總時間為 O(N) + ... 上面的數學公式(以后學會怎么編輯再來修改)。當數據服從均勻分布時,每次的插入排序期望值為 n*O(2-1/N),驗證較為復雜,有興趣的同學可以參考算法導論第三版.114頁。

          可以得出時間復雜度為 O(N),數學驗證比較復雜,但使用邏輯推論思考,當趨近於均勻分布,幾乎每次插入排序都為常數級,則也可以得出結論

    

        相信面試或者平時的工作,總會遇到符合條件的場景,用線性時間復雜度的算法完全可以替代最常用的快速排序,無論是加分還是提高運算速度,都是一個不錯的選擇 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM