順序統計中值---無序找第k大/小值

問題描述:無序找第k小的數?算法

一、解法一數組

  先排好序,再找第k小個數;返回A[k-1];此解法的時間複雜度爲:O(nlogn);ide


二、解法二性能

  狀況一:k = 1 和 k = n 就是找數組的最小值和最大值;spa

  狀況二:找出中位數3d


三、找中位數(隨機選擇算法)
blog

  利用快速排序的原理,一輪排序,有2種狀況:排序

  if i = k-1;返回a[i];遞歸

  if i != k-1;左邊/右邊遞歸查找,時間複雜度爲:O(n);get

具體思想:

wKioL1ioPv7C-DZtAAA01mEEhbQ513.png-wh_50

  分析:在大多數狀況下的時間複雜度是:O(n);可是最壞狀況,徹底順序下找第k = n-1大數,此時的時間複雜度是:O(n^2);


四、無序找第k小值

  快排的升序實現思想,在加上遞歸查找;

  (1)、代碼實現

#include<stdio.h>

void findKSmall(int *a, int start, int end, int key);

void findKSmall(int *a, int start, int end, int key){
    int i = start;
    int j = end;
    int tmp = a[i];
//快排中的升序
    while(i < j){
        while(i < j && a[j] > tmp){
            j--;
        }
        if(i < j){
            a[i++] = a[j];
        }
        while(i < j && a[i] < tmp){
            i++;
        }
        if(i < j){
            a[j--] = a[i];
        }
    }
    a[i] = tmp;

    if(key-1 < i){
        findKSmall(a, 0, i-1, key);
    }else if(key-1 > i){
        findKSmall(a, i+1, end, key);
    }else{
        return;
    }
}

void main(void){
    int a[] = {8, 4, 6, 9, 2, 3, 7, 9, 11, 10};
    int count = sizeof(a)/sizeof(int);
    int k;
    int i;

    printf("請輸入要查找的第k小的數:");
    scanf("%d", &k);
    findKSmall(a, 0, count-1, k);
    for(i = 0; i < count; i++){
        printf("%d ", a[i]);
    }

    printf("\n%d\n", a[k-1]);

}

  結果截圖

wKiom1irdVXwiEUjAAAMn-YA6yI720.png-wh_50

 

五、無序找第k大值

  快排的降序實現思想,在加上遞歸查找;

  (1)、代碼實現

#include<stdio.h>

void findKBigger(int *a, int start, int end, int key);

void findKBigger(int *a, int start, int end, int key){
    int i = start;
    int j = end;
    int tmp = a[i];
//快排中的降序
    while(i < j){
        while(i < j && a[j] < tmp){
            j--;
        }
        if(i < j){
            a[i++] = a[j];
        }
        while(i < j && a[i] > tmp){
            i++;
        }
        if(i < j){
            a[j--] = a[i];
        }
    }
    a[i] = tmp;

    if(key-1 < i){
        findKBigger(a, 0, i-1, key);
    }else if(key-1 > i){
        findKBigger(a, i+1, end, key);
    }else{
        return;
    }
}

void main(void){
    int a[] = {8, 4, 6, 9, 2, 3, 7, 9, 11, 10};
    int count = sizeof(a)/sizeof(int);
    int k;
    int i;

    printf("請輸入要查找的第k大的數:");
    scanf("%d", &k);
    findKBigger(a, 0, count-1, k);
    for(i = 0; i < count; i++){
        printf("%d ", a[i]);
    }

    printf("\n%d\n", a[k-1]);

}

  (2)、結果截圖

wKioL1irdqfyCPphAAAXbYrvuJc382.png-wh_50

六、線性算法

  (1)、劃分爲5個一組的元素,在找出每一組的中值(對這5個數進行排序,找出中值),時間複雜度:O(n)

  (2)、用遞歸去找這些中值中的那一箇中值(中值中的中值);

  (3)、此時用這個最中值的下標和k做比較,以後和上面的隨機選擇算法同樣!!!

具體模型以下:

wKioL1ioW82A6RD9AAATBBoL_6A108.png-wh_50


算法分析

  找中值和第k小數時間複雜度均爲:O(n);比較好的解決了上述最壞時間複雜度爲O(n^2)的狀況;

  3個元素一組的話,結果不成立;

  5是這個算法能成功的最小數字,7個元素爲一組算法也能成立,可是性能不會有所提升;

相關文章
相關標籤/搜索