zoukankan      html  css  js  c++  java
  • 中位数

    求给定整数数据中的第i小的数

    如果数据量很大,不能一次读入内存,可以将数据分区间储存。具体而言,就是讲数据分为...-2^20~-1,0~2^20-1, 2^20~2*2^20-1,2*2^20~3*2^20-1....并统计每个区间有多少个数据。这样就可以判断第i小的数在哪个区间。并且可以判断它在该区间是第几小。

    每个区间的大小是2^20,一共有2^32/2^20=2^12个区间,每个区间的数存放在一个文件中。2^20 * 4byte = 4MB,可以读入内存。

    现在问题转化为了求4MB数据中的第j位数。

    采用随机选取算法,最差时间复杂度为O(n^2),平均时间复杂度为O(n)

    该算法的思路是,通过快速排序的分割方式,一次可以将数据分为两部分,主元最后的位置m就是一个m分割,前m个数小于主元,后面的数大于主元,主元是所有数中第m+1大的。如果m+1 = j,则问题就解决了。

    如果m+1 < j,说明第j位数在第一次分割的后半部分,此时以m+1下标作为begin,以len-1作为end,继续分割。得到主元的位置s,则主元前面的s个数都小于主元,主元后面的数都大于主元,主元是所有数中的第s+1大。判断s+1和j的关系。

    如果m+1>j,说明第j位数在第一次分割的前半部分,此时以下标0作为begin,以m-1作为end,继续分割。

    最终可以得到j

    注意,每次需要记录下begin和end。

    /*
    *求一组数据中的第i小的数
    */
    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    int RandomPartition(int *A,int beg,int end)
    {
        int k = beg+rand()%(end-beg+1);
        int temp = A[beg];
        A[beg] = A[k];
        A[k] = temp;
        
        int s=A[beg];
        int i=beg;
        int j=end;
        while(j>i)
        {
            while(A[j]>s && j>i)
            {
                j--;
            }
            if(j>i)
            {
                A[i]=A[j];
                i++;
            }
            while(A[i]<s && i<j)
            {
                i++;
            }
            if(i<j)
            {
                A[j]=A[i];
                j--;
            }
        }
        A[i] = s;
        return i;
    }
    
    int Median(int *A,int len,int i)
    {
        if(i>len || i<1)
        {
            printf("i>len
    ");
            exit(0);
        }
        else
        {
            int k;
            int beg =0;
            int end = len-1;
            k=RandomPartition(A,beg,end);
            while((k+1)!=i)
            {
                if((k+1)>i)
                {
                    end = k-1;
                    k=RandomPartition(A,beg,end);
                }
                else
                {
                    beg = k+1;
                    k=RandomPartition(A,beg,end);
                }
            }
            return A[k];
        }
    }
    
    int main()
    {
        int A[]={1,45,43,65,23,42,63,22,18,9};
        srand((unsigned int)time(NULL));
        printf("%d
    ",Median(A,10,2));
        return 0;
    }
  • 相关阅读:
    AGC037F Counting of Subarrays
    AGC025F Addition and Andition
    CF506C Mr. Kitayuta vs. Bamboos
    AGC032D Rotation Sort
    ARC101F Robots and Exits
    AGC032E Modulo Pairing
    CF559E Gerald and Path
    CF685C Optimal Point
    聊聊Mysql索引和redis跳表
    什么是线程安全
  • 原文地址:https://www.cnblogs.com/johnsblog/p/3946952.html
Copyright © 2011-2022 走看看