对于给定的数组,统计出其中最多的元素的值

来源:互联网 发布:u盘安装ubuntu黑屏 编辑:程序博客网 时间:2024/06/13 23:27

/*
问题描述:对于给定的数组,统计出其中最多的元素的值(1,3,5,4,3,3,最多的是3)
说明:对于这个问题,简单的、一般的算法很容易想到(我想到的就是这个)。有点吊的算法使劲想想,应该也能想出来。最牛逼的是第三种算法,能想出来的估计应该算是大牛的级别了。本人绞尽脑汁想出了第一种算法,但男人的第六感告诉我总觉得有更好的方法。所以又查阅了相关资料,整理出来另外两种算法。特记录如下:
算法简要描述:
TheMostNums1: 这是最普通的方法。就是顺序扫描给定的数组,用一个辅助数组记录相同元素的个数,最后在扫描一次辅助数组,找出最大的数,进而找出最多的元素。这种算法的时间复杂度是O(N2),空间的复杂度是O(N)

TheMostNums2:这种算法用了另一种思路。它把每个元素看成一种操作,那么相同的元素对应同一种操作。然后通过分析这种操作的结果,来统计最多的元素。 具体的说,在这里,使用了一个辅助数组每个元素所对应的操作就是往辅助数组中对应的位置+1。最后,统计辅助数组中那个位置被加的最多(元素值最大),那么这个辅助位置对应的下标就是所含有的最多的元素。
这种算法有个小毛病,就是原数组中元素的值不能太大,因为辅助数组个数就是原数组中最大的数。(本程序中就是待定数组的长度)
这个算法的时间复杂度是O(N),空间复杂度取决于申请辅助数组的大小。

TheMostNums3:最牛逼的算法来了。上一种算法是采用了一个辅助数组来映射原数组中元素的操作,那么能不能不用辅助空间实现呢?可以。牛逼的算法直接在原数组上操作,也就是直接映射在原数组上。但是这样就有个问题,你这映射在原数组上,原数组的值不是改变了?那怎么统计相同的元素呢?有什么方法既能够实现映射操作,又能够 保留原来元素的信息呢。这里采用了一种方法,取余。即事先规定好要增加的值大小add_val(在这里不能每次增加1了,至少要大于原数组中最大的值),每次操作就加上add_val。这样原来的值只需要对add_val取余就行。 有点像哈希映射。

详细的可以参考:

是不是挺牛逼的。不过牛逼归牛逼,但是这种算法也有一些问题,就是原数组的中元素最大的值不能大于数组的长度,否则就不够映射了。
这种算法的时间复杂度是O(N),空间复杂度是O(1)。

*/

//计算数组中最多的元素(若有多组相同数目的最多元素,则返回首个元素)int TheMostNums1(Sqlist L){    int nums[L.length];     //用来保存每个元素的个数    int the_most_index = 0;     //保存最多元素个数个下标    int the_most_nums = 0;      //保存最多元素的个数    memset(nums,1,sizeof(int)*L.length);    //每个元素初始化为1    //计算每个元素的个数(只有第一个相同元素的下标统计的是正确的,后面相同元素都比前面的少)    for(int i = 0;i<L.length;++i)    {        for(int j = i+1;j<L.length;++j)        {            if(L.data[i] == L.data[j])            {                ++nums[i];            }        }    }    //统计最多元素的下标    for(int i = 0;i<L.length;++i)    {        if(nums[i]>the_most_nums)        {            the_most_nums = nums[i];            the_most_index = i;        }    }    return L.data[the_most_index];}
int TheMostNums2(Sqlist L){    int nums[L.length];     //用来保存每个元素的个数    int the_most_index = 0;     //保存最多元素个数个下标    int the_most_nums = 0;      //保存最多元素的个数    memset(nums,0,sizeof(int)*L.length);    //每个元素初始化为1    for(int i = 0;i<L.length;++i)    {        if(L.data[i]>L.length || L.data[i]<0)        {            cout<<"data is wrong!"<<endl;            return -1;        }        else            ++nums[L.data[i]];      //把每个元素对应的nums数组的元素+1    }    //统计次数    for(int i = 0;i<L.length;++i)    {        if(the_most_nums<nums[i])        {            the_most_nums= nums[i];            the_most_index = i;        }    }    return the_most_index;      //返回值最多的下标,即最多的元素}
int TheMostNums3(Sqlist L){    int add_val = L.length;  //每次操作增加的值(只要不小于长度都行)    int temp_index = 0;     //用作中间换算用    int the_most_index = 0;     //用来保存最终的结果    int com_num = 0;        //用来保存比较的数    for(int i = 0;i<L.length;++i)    {        temp_index = L.data[i] % add_val;  //将每个元素的值映射到对应位置(这里指的是相同下标)        L.data[temp_index] += add_val;      //加上每次要操作的值    }    //统计那个元素最多    for(int i = 0;i<L.length;++i)    {        if(com_num < L.data[i])        {            com_num = L.data[i];            the_most_index = i;        }    }    return the_most_index;}
阅读全文
0 0