继续前一篇文章...
相对于前一篇文章讲的算法来说,“多重集算法”比较容易理解。
我们把原始数组看成一个多重集,每次从数组中删除k个不同的元素,直到不能再删了为止。那么最后数组中剩余的元素就是候选元素。
例如 {1,2,3,3,4,4,3,5,3} ,这里n=9,k=3。我们要查找出现次数大于n/k=3的元素。
下划线表示被删除的元素:
{1,2,3,3,4,4,3,5,3} =>
{3,4,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);
}
}
}
还有一种是“决策树”算法,比“多重集”算法效率更高。我们下回再讲。