基於快速排序思想partition查找第K大的數或者第K小的數。


快速排序

下面是之前實現過的快速排序的代碼。

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現在所在的下標返回
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM