题目很简单:要求一个算法能在一个长度为n的无序数组中找到第k小的数(k从0开始)
例如:4, 1, 2, 5 序列的第2小的数应该是4. 因为原数列排序后为1,2,4,5 所以第0小的数是1,第1小的数是2,第2小的数是4,第3小的数是5.
解法:
1)排序:
最容易想到的解法就是先把整个数组从小到大排序一遍,然后想要找哪一个数从头开始找即可。这种解法时间复杂度:O(nlogn)
2)多次查找:
第一遍遍历先找到最小的值,并标记为已访问过。第二遍再找剩下没访问过的最小值,即第二小的数。。。这样遍历k轮就能找到第k小的数。时间复杂度:O(n*k)
3)Partition算法:
Partition算法是快速排序QuickSort中的一部分,思想是选定一个值作为pivot,然后通过swap,使得最终pivot左边的数都小于pivot,pivot右边的数都大于pivot。
利用Partition算法,再结合递归,类似二分查找的分治。
即:返回pivot的index正好和k相等,则找到了第k小的数。
如果返回pivot的index小于k,则在pivot的右半段递归查找。
如果返回pivot的index大于k,则在pivot的做半段递归查找。
时间复杂度:平均:O(nlogk) 优于排序解法,但最差时(如:递减数列时)退化成 O(n^2)
具体实现看下面代码。。。
一些写的不错的文章:
http://algorithmsandme.blogspot.com/2013/08/find-kth-smallest-element-application.html
4)Median of Medians 算法:最差:O(n)
1. Divide the array into N/C columns of elements, for small odd C.
2. Find the median of each column by sorting it.
3. Take only the medians and repeat steps 1-2 recursively until only one value remains. That value is picked as the pivot.
4. Iterate through the array and count number of elements strictly smaller than the pivot (S), larger than the pivot (L) and equal to the pivot (E=N-S-L).
5. If K<S, move all