快速排序算法在数组中选择一个称为主元(pivot)的元素,将数组分为两部分,使得 第一部分中的所有元素都小于或等于主元,而第二部分的所有元素都大于主元。对第一部分递归地应用快速排序算法,然后对第二部分递归地应用快速排序算法。
在最差情况下,划分由 n 个元素构成的数组需要进行 n 次比较和 n 次移动。因此划分所需时间为 O(n) 。最差情况下,每次主元会将数组划分为一个大的子数组和一个空数组。这个大的子数组的规模是在上次划分的子数组的规模减 1 。该算法需要 (n-1)+(n-2)+…+2+1= O(n^2) 时间。在最佳情况下,每次主元将数组划分为规模大致相等的两部分。设 T(n) 表示使用快速排序算法对包含 n 个元素的数组排序所需的时间,因此,和归并排序的分析相似,快速排序的 T(n)= O(nlogn)。
对于快排在Top k问题中的运用,我们运用Quick Select,Quick Select [1]脱胎于快排(Quick Sort),两个算法的作者都是Hoare,并且思想也非常接近:选取一个基准元素pivot,将数组切分(partition)为两个子数组,比pivot大的扔左子数组,比pivot小的扔右子数组,然后递推地切分子数组。Quick Select不同于Quick Sort的是其没有对每个子数组做切分,而是对目标子数组做切分。其次,Quick Select与Quick Sort一样,是一个不稳定的算法;pivot选取直接影响了算法的好坏,worst case下的时间复杂度达到了O(n2)
O(n2)
Quick Select的目标是找出第k大元素,所以
下面贴上JAVA代码:
import java.util.ArrayList;
public class QuickSort {
//存放最大的k个数
public ArrayList result = new ArrayList();
public int partition(int[] a,int low,int high){
int privotKey = a[low];
while (low < high){
while (low < high && a[high] >= privotKey){
high --;
}
// swap(a[high],a[low]);
int temp = a[high];
a[high] = a[low];
a[low] = temp;
while (low < high && a[low] <= privotKey ){
low ++;
}
// swap(a[low],a[high]);
temp = a[low];
a[low] = a[high];
a[high] = temp;
}
// for (int b:a) {
// System.out.print(b + " ");
// }
// System.out.println("");
//此时,low = high
// low的位置是基准数的下标
return low;
}
//快排
public void quickSort(int[] a,int low,int high){
if (low < high){
int privotLoc = partition(a,low,high);
quickSort(a,low,privotLoc - 1);
quickSort(a,privotLoc + 1,high);
}
}
//找第k个最大的元素
public int findKthLargest(int[] nums, int k) {
return quickSelect(nums, k, 0, nums.length - 1);
}
// 快速选择找第k个最大的元素
public int quickSelect(int[] arr, int k, int left, int right) {
// if (left == right) return arr[right];
int index = partition(arr, left, right);
if (right - index + 1 > k){
return quickSelect(arr, k, index + 1, right);
}
else if (right - index + 1 == k){
for (int i = index; i <= arr.length - 1; i++) {
result.add(arr[i]);
}
return arr[index];
}
else{
return quickSelect(arr, k - right + index - 1, left, index - 1);
}
}
public static void main(String[] args){
int [] a ={47,25,16,24,15,23,1548,255,445,47,54,0,99999,2312213,1223123123,2};
QuickSort quickSort = new QuickSort();
int num = quickSort.findKthLargest(a,3);
// System.out.println(num);
for (Integer i:quickSort.result) {
System.out.println(i);
}
}
}