上週一個面試,一開始讓我寫個快速排序,寫出來了。
後來讓我分析快速排序的時間複雜度,,,,忘了怎麼分析。。。。
再後來問我知不知道快速排序的第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