快速排序
下面是之前實現過的快速排序的代碼。
function quickSort(a,left,right){ if(left==right)return; let key=partition(a,left,right);//選出key下標 if(left<key){ quickSort(a,left,key-1);//對key的左半部分排序 } if(key<right){ quickSort(a,key+1,right)//對key的右半部份排序 } } function partition(a,left,right){ let key=a[left];//一開始讓key為第一個數 while(left<right){//掃描一遍 while(key<=a[right]&&left<right){//如果key小於a[right],則right遞減,繼續比較 right--; } [a[left],a[right]]=[a[right],a[left]];//交換 while(key>=a[left]&&left<right){//如果key大於a[left],則left遞增,繼續比較 left++; } [a[left],a[right]]=[a[right],a[left]];//交換 } return left;//把key現在所在的下標返回 }
明顯我們可以看出快排的思想是每次找到一個基准數,將數組排列成基准數左邊的每個數都比基准數大,右邊的每個數都比基准數小的序列。 通過這個思想,我們可以稍微修改QuickSort函數,使它變成findKmax函數,使之擁有快速查找前k個最大的數。
基於快速排序思想查找第K大的數
function findKmax(a,k){ let left=0,right=a.length-1; let key=partition(a,left,right); let len=a.length-key; while(len!=k){ if(len>k){ key=partition(a,key+1,right); }else{ key=partition(a,left,key-1); } len=a.length-key; } return a[key]; } function partition(a,left,right){ let key=a[left];//一開始讓key為第一個數 while(left<right){//掃描一遍 while(key<=a[right]&&left<right){//如果key小於a[right],則right遞減,繼續比較 right--; } [a[left],a[right]]=[a[right],a[left]];//交換 while(key>=a[left]&&left<right){//如果key大於a[left],則left遞增,繼續比較 left++; } [a[left],a[right]]=[a[right],a[left]];//交換 } return left;//把key現在所在的下標返回 }
重點是要注意判定邊界條件,left,right,k三個都在變,因此需要檢驗
同理,還可以求第K小的數
function findKmin(a,k){//查找第K小的數 let left=0,right=a.length-1; let key=partition(a,left,right); while(key!=k-1){ if(key>k-1){ key=partition(a,left,key-1); }else{ key=partition(a,key+1,right); } } return a[key]; } function partition(a,left,right){ let key=a[left];//一開始讓key為第一個數 while(left<right){//掃描一遍 while(key<=a[right]&&left<right){//如果key小於a[right],則right遞減,繼續比較 right--; } [a[left],a[right]]=[a[right],a[left]];//交換 while(key>=a[left]&&left<right){//如果key大於a[left],則left遞增,繼續比較 left++; } [a[left],a[right]]=[a[right],a[left]];//交換 } return left;//把key現在所在的下標返回 }