快速排序的第N大

上週一個面試,一開始讓我寫個快速排序,寫出來了。

後來讓我分析快速排序的時間複雜度,,,,忘了怎麼分析。。。。

再後來問我知不知道快速排序的第K大的數,,,,我說我沒聽說過。。。。

有點尷尬,其實超級喜歡這個公司的,關鍵是工資高啊(當然,裏面也是我喜歡做的,之前的公司不是做的很簡單,就是讓我也去做別的語言的開發。而我想先把python的搞的透透的,再去學別的語言的開發, 比如說java)。。。。。

快速排序的時間複雜度需要一個公式,感覺自己是懶得記了,什麼時候回學校看看算法導論再說吧。

今天來看看,分析分析快速排序實現獲取無序數組的第k大的數。

其實(我好像很喜歡說這個其實很簡單,但是當時爲什麼不願意讓他給我時間,我想想呢?即使沒碰到過就一定不會做的嗎?我發現我有點傻逼,,,,)這個很簡單的。

快速排序中間的關鍵一步就是下面這個部分

def divide(nums, start, end):
    l, r = start + 1, end
    while True:
        while l <= end and nums[l] < nums[start]:
            l += 1
        while nums[r] > nums[start]:
            r -= 1
        if l > r:
            break
        nums[l], nums[r] = nums[r], nums[l]
        l += 1
        r -= 1
    nums[start], nums[r] = nums[r], nums[start]
    return r

怎麼個原理呢,各位可以去搜一搜快速排序,就可以有一大堆。

我就說說結果:對於一個數組的給定部分nums[start:end+1],找到元素nums[start]的位置,於是可以把數組nums[start:end+1]分爲兩個部分,分別爲nums[start:r-1]和nums[r+1:end+1],這個r就是divide(nums, start, end)返回的結果。

也就是找到數組nums中第一個元素在有序數組中的位置,左側的元素都比它小,右側的元素都比它大。

那麼,根據這個是不是就可以找到第K大的元素呢?

答案是是的。調用divide返回的索引r等於len(nums)-k,那麼這個索引的元素是不是就是第K大了;如果返回的索引r比len(nums)-k小,那麼這個第K大的元素是不是處於索引r的右側;如果返回的索引r比len(nums)-k大,那麼這個第K大的元素是不是處於索引r的左側。

好了,到此就可以組織代碼了。

def findKth(nums, first, last, k):
    tmp = divide(nums, first, last)
    if tmp == len(nums)-k:
        print('{}第{}大的數是'.format(nums, k), nums[tmp])
        return nums[tmp]
    elif tmp < len(nums)-k:
        return findKth(nums, tmp+1, last, k)
    else:
        return findKth(nums, first, tmp-1, k)

隨便做了個測試部分,進行驗證下

import random
l = list(range(10))
random.shuffle(l)
print(findKth(l, 0, len(l)-1, 3))

輸出結果爲:

[4, 0, 3, 2, 1, 5, 6, 7, 9, 8]第3大的數是 7
7

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章