快速排序的第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

 

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