上周一个面试,一开始让我写个快速排序,写出来了。
后来让我分析快速排序的时间复杂度,,,,忘了怎么分析。。。。
再后来问我知不知道快速排序的第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