线性时间内求数组中第i大小的元素

一、题目描述

设有一个算法Median能在O(n)的时间内计算一个数组的中位值(即将数组的元素按大小顺序排列正好位于中间的值)。给定一个有n个元素的数组,能否以Median算法为基础设计一个算法,对任意的整数1≤i≤n,该算法在O(n)的时间内求出数组中第i大小的元素。如果能,请给出一个这样的算法并分析其最坏时间复杂性。

二、算法分析

1.将输入的数组A[n]中的n个元素分为n/5组,每组5个元素,且至多只有一组有n%5个元素;

2.调用Median算法得到每组的中位数,所有的中位数构成数组M[1,...,n/5];

3.再次调用Median算法求得数组M[1,...,n/5]的中位数Med;

4.根据Med将原数组A[n]进行划分,比Med小的元素全部放到Med左边,比Med大的元素全部置于Med的右侧,得到Med的位置k

5.如果i = k,则返回中位数Med,如果 i < k,对Med左边的所有元素重复算法,如果i < k,对Med所有右侧的元素重复算法

三、算法伪码(基于JAVA)

    public int Select_i (ArrayList<Integer> A, int index_s, int index_e, int i){
        ArrayList<Integer> M = new ArrayList<Integer>();
        //将数组划分为n/5组,每组5个元素,求得每组中位数,得到数组M
        for (int m = 0; m < A.size()/5 ; m++){
            if (m*5 + 5 < A.size() - 1){
                M.add(Median(A,m*5, m*5+5));
            }
            else{
                M.add(Median(A, m*5, A.size()));
            }
        }
        //求得数组M的中位数Med
        int Med = Median(M, 0, M.size());
        //根据中位数Med对数组A进行划分,调用函数Divede,得到Med在数组A中的位置k
        int k = Divede(A,Med);
        //结果处理
        if (i == k){
            return Med;
        }
        else if (i < k){
            return Select_i(A, 0, k-1, i);
        }
        else{
            return Select_i(A, k+1, A.size() - 1, i);
        }
    }

四、算法复杂度分析

复杂度为线性O(n)满足要求。

 

posted @ 2017-10-20 10:21  Nipo  阅读(337)  评论(0编辑  收藏  举报