快速選擇排序 Quick select 解決Top K 問題
阿新 • • 發佈:2018-12-17
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