求n个数字的前K个数或者求中位数

中位数
public class median {

    private boolean bOdd;//是否奇偶数
    private int kv;//k值
    private double medium;
    int partition(double a[], int low, int high) {
        double tmp = a[low];
        int i = low, j = high;
        while (i < j) {
            while (i < j && a[j] >= tmp){
                j--;
            }
            while (i < j && a[i] <= tmp){
                i++;
            }
            swap(a, i, j);
        }
        a[low] = a[i];
        a[i] = tmp;
        return i;
    }

    void swap(double a[], int i, int j) {
        if(i == j){
            return;
        }
        double tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
    void findMedium(double a[]){
        bOdd = a.length % 2 == 0;
        kv = a.length / 2 + 1;
        medium = 0;
        findK(a, 0, a.length - 1, kv, -1);
    }

    /**
     * 需求第K小
     * @param a
     * @param low
     * @param high
     * @param k
     * @param prePart  上回分裂中将该中位数分到右边的分裂点
     */
    void findK(double a[], int low, int high, int k, int prePart){
        if(low > high){
            return;
        }
        int pos = partition(a, low, high);
        int left = pos - low + 1;//左边个数
        if(k > left){//中位数在分裂点右边,将该分裂点作为下次迭代的prePart
            findK(a, pos + 1, high, k - left, pos);
        }
        else if(k < left){//中位数在分裂点左边,本次的prePart作为下次迭代的prePart
            findK(a, low, pos - 1, k, prePart);
        }
        else{
            if(bOdd){//偶数时的中位数处理,取两个中位数的均值
                double v1 = a[pos];
                double v2 = 0;
                if(low >= pos){
                    v2 = a[prePart]; //左边无值时取prePart
                }else{
                    v2 = findMax(a, low, pos - 1);//左边有值时取左边最大值
                }
                medium = (v1 + v2) / 2;
                System.out.println(medium);
            }else{
                medium = a[pos];
                System.out.println(medium);
            }
        }
    }

    double findMax(double a[], int low, int high){
        double max = a[low];
        for(int i = low + 1; i <= high; i ++){
            if(a[i] > max){
                max = a[i];
            }
        }
        return max;
    }

    double getMedium(){
        return medium;
    }

    public static void main(String[] args) {
        median m = new median();
        double a[] = {6,1,2,3,7,8,5,4,9};
        m.findMedium(a);
        m.findK(a,0,a.length - 1, 9, -1);
    }
}

// 求前K个数

public class medianK {

    private int kv;//k值
    private double medium;
    int partition(double a[], int low, int high) {
        double tmp = a[low];
        int i = low, j = high;
        while (i < j) {
            while (i < j && a[j] >= tmp){
                j--;
            }
            while (i < j && a[i] <= tmp){
                i++;
            }
            swap(a, i, j);
        }
        a[low] = a[i];
        a[i] = tmp;
        return i;
    }

    void swap(double a[], int i, int j) {
        if(i == j){
            return;
        }
        double tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }


    /**
     * 需求第K小
     * @param a
     * @param low
     * @param high
     * @param k
     * @param prePart  上回分裂中将该中位数分到右边的分裂点
     */
    void findK(double a[], int low, int high, int k, int prePart){
        if(low > high){
            return;
        }
        int pos = partition(a, low, high);
        int left = pos - low + 1;//左边个数
        if(k > left){//中位数在分裂点右边,将该分裂点作为下次迭代的prePart
            findK(a, pos + 1, high, k - left, pos);
        }
        else if(k < left){//中位数在分裂点左边,本次的prePart作为下次迭代的prePart
            findK(a, low, pos - 1, k, prePart);
        }else {
            for (int i=0;i<k;i++){
                System.out.println(a[i]);
            }
        }
    }

    double findMax(double a[], int low, int high){
        double max = a[low];
        for(int i = low + 1; i <= high; i ++){
            if(a[i] > max){
                max = a[i];
            }
        }
        return max;
    }

    double getMedium(){
        return medium;
    }

    public static void main(String[] args) {
        medianK m = new medianK();
        double a[] = {6,1,2,3,7,8,5,4,9};
//        m.findMedium(a);
        m.findK(a,0,a.length - 1, 5, -1);
    }
}

猜你喜欢

转载自blog.csdn.net/willlu10/article/details/82845454