題目來源:https://leetcode.com/problems/kth-largest-element-in-an-array/description/
上週剛學完分治,週末複習一下。時時溫故,梳理一下,看看能否知新。
分治算法中的經典問題,topK肯定佔有一席之地,也是《算法概論》中的selection問題。
topK與快排的原理類似。所以先簡單複習一下快速排序:
以{4,3,5,7,8,9,2,1}爲例,
首先在這個序列中隨便找一個數作爲基準數。方便起見,找第一個數4;
分別從初始序列{3,2,5,7,8,9,2,1}兩端開始往中間走。
用兩個變量i和j,分別指向序列最左邊和最右邊。分別用i和j來記錄走過的下標,先從右往左找第一個小於4的數,再從左往右找第一個大於4的數,然後交換他們;
{4,3,5,7,8,9,2,1}
{4,3,1,7,8,9,2,5}
i和j歸回原位,分別指向序列最左邊和最右邊。重複以上過程,直至某一次i與j碰頭,即
i == j
此時,
{4,3,1,2,8,9,7,5}
i == 4
j == 4,與i碰頭,不能繼續向前
於是,將基準書和第i個數交換。到此,第一輪交換結束。
換一個基準數,重複以上過程。
topK可以算是快排的變種,利用快排的思想,將數組分爲3部分(或2部分,3部分理解起來更快些),分而治之。
首先,也是先找一個基準數。假設第v個數爲基準數。考慮到重複元素的問題,我們在這裏將數組分爲3部分,小於基準數的元素放在一起稱作SL,等於基準數的元素放在一起稱作SV,大於基準數的元素放在一起稱作SR。
然後,比較k與各個集合的大小關係。
k與各個集合的大小關係 | topK的位置 |
---|---|
k <= sizeof(SR) | 第k大的數在右半邊SR中 |
sizeof(SR) < k <= ( sizeof(SL)+sizeof(SV) ) | 這就是第k大的數 |
k <= sizeof(SR) | 第k大的數在左半邊SL中 |
與快排有所不同的是,topK一輪以後就知道第K個元素在哪一半里,下一趟只處理那一半就行了。
topK算法中比較玄妙的是v的取法,這直接決定了算法的時間複雜度。這裏就不深入討論了。
當然,此法也可求前k大的數。