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;
    }
  • 相关阅读:
    创建基于MailKit和MimeKit的.NET基础邮件服务
    MailKit---获取邮件
    C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法
    .net 开源 FTP 组件 edtFTPnet
    Consul1-window安装consul
    通信传输利器Netty(Net is DotNetty)介绍
    工作中,如何衡量一个人的 JavaScript 编码水平?
    10个有趣又能编译为JavaScript的语言,你用过哪些?
    一定要你明白Java中的volatile
    面试总被问到HTTP缓存机制及原理?看完你就彻底明白了
  • 原文地址:https://www.cnblogs.com/johnsblog/p/3946952.html
Copyright © 2011-2022 走看看