查找出现次数大于n/k的重复元素 --- 多重集算法

来源:互联网 发布:淘宝网首 编辑:程序博客网 时间:2024/04/28 20:11

继续前一篇文章...

相对于前一篇文章讲的算法来说,“多重集算法”比较容易理解。

我们把原始数组看成一个多重集,每次从数组中删除k个不同的元素,直到不能再删了为止。那么最后数组中剩余的元素就是候选元素。

例如 {1,2,3,3,4,4,3,5,3} ,这里n=9,k=3。我们要查找出现次数大于n/k=3的元素。

下划线表示被删除的元素:

{123,3,4,4,3,5,3} => 

{34,4,3,5,3}=>

{4,3,3} 

然后,再检验4,3在数组中出现的次数是否大于3。算法复杂度是O(n*log(k))。

代码(不包括检验过程,执行完之后,t中就是候选元素):

struct Pair{   int v;   mutable int c;};struct Comp{   bool operator()(const Pair& lhs, const Pair& rhs)   {        return lhs.v<rhs.v;   }};void find_repeated_elements(int b[],int n,int k){    int d=0;//表示t中不同的元素个数,也就是t的大小    set<Pair,Comp> t;    for(int i=0;i<n;++i)    {        struct Pair p;        p.v=b[i];        p.c=1;        set<Pair,Comp>::iterator ret=t.find(p);        if(ret==t.end())//在t中没有找到b[i]        {            t.insert(p);            ++d;            if(d==k)//t中不同的元素数量达到了k个            {                 for(set<Pair,Comp>::iterator it=t.begin();it!=t.end();)                 {                       if(it->c>1)                       {                            --(it->c);                            ++it;                       }                       else                            t.erase(it++);                 }                 d=t.size();//如果t中某些元素被删掉,需要更新d的值            }        }        else//在t中找到了b[i]        {            ++(ret->c);        }    }}

还有一种是“决策树”算法,比“多重集”算法效率更高。我们下回再讲。