1. 思想
Quick select算法通常用来在未排序的数组中寻找第k小/第k大的元素。
Quick select和Quick sort类似,核心是partition。
1. 什么是partition?(如下图,选44为pivot,把数组分为2部分,左边比44小,右边比44大)
从数组中选一个数据作为pivot,根据每个数组的元素与该pivot的大小将整个数组分为两部分:
左半部分,都比pivot大,右半部分,都比pivot小 。
2. 用分治思路实现排序
pivotIndex 是pivot在数组的下标
pivotIndex大于k,说明array[pivotIndex]左边的元素都大于k,只递归array[0, pivotIndex-1]第k大的元素即可;
pivotIndex小于k,说明第k大的元素在array[pivotIndex]的右边,只递归array[pivotIndex +1, n]第k-pivotIndex大的元素即可;
逻辑如下:
function quickSelect(list, left, right, k)
if left = right
return list[left]
Select a pivotIndex between left and right
pivotIndex := partition(list, left, right,
pivotIndex)
if k = pivotIndex
return list[k]
else if k < pivotIndex
right := pivotIndex - 1
else
left := pivotIndex + 1
2.code in java
import java.util.Arrays;
public class QuickSelect {
public static void main(String[] args) {
int arr[] = {7, 10, 4, 3, 20, 15 };
int pivotIndex = quickSelect(arr,4, 0, arr.length - 1 );
System.out.println("pivotIndex="+pivotIndex);
}
private static int getPivotByPartition(int[] elements, int start, int end) {
int pivot = start;
int lessThan = start;
for (int i = start; i <= end; i++) {
int currentElement = elements[i];
if (currentElement < elements[pivot]) {
lessThan++;
int tmp = elements[lessThan];
elements[lessThan] = elements[i];
elements[i] = tmp;
}
}
int tmp = elements[lessThan];
elements[lessThan] = elements[pivot];
elements[pivot] = tmp;
//System.out.println(" --- array = " +Arrays.toString(elements));
return lessThan;
}
private static int quickSelect(int[] elements, int k, int start, int end) {
int pivot = getPivotByPartition(elements, start, end);
if (k == (pivot - start + 1)) {
System.out.println("pivot value="+elements[pivot]);
return pivot;
} else if (k < (pivot - start + 1)) {
return quickSelect(elements, k, start, pivot - 1);
} else {
return quickSelect(elements, k - (pivot - start + 1), pivot + 1, end);
}
}
}
3. 分析
与Quick sort不同的是,Quick select只考虑所寻找的目标所在的那一部分子数组,而非像Quick sort一样分别再对两边进行分 割。正是因为如此,Quick select将平均时间复杂度从O(nlogn)降到了O(n)
最坏时间复杂度: О(n²)
平均时间复杂度: О(n)
最坏空间复杂度: О(n) total, O(1) auxiliary
4. 参考
https://www.geeksforgeeks.org/quickselect-algorithm/
https://blog.csdn.net/wufaliang003/article/details/82940218