计算大数组中的唯一元素

时间:2011-02-07 19:58:40

标签: arrays algorithm unique

我的一位同事在接受采访时被问到了问题。

给定一个存储unsigned int的巨大数组。数组长度为100000000.找到计算数组中唯一元素数的有效方法。  
例如,{2,34,5,6,7,2,2,5,1,34,5} O / p:2的计数是3,34的计数是2,依此类推。

执行此操作的有效算法是什么?我认为首先字典/哈希将是一个选项,但由于数组非常大,它是无效的。有没有办法做到这一点?

谢谢, 乔塔

8 个答案:

答案 0 :(得分:10)

堆排序是O(nlogn)和就地。处理大型数据集时就地是必要的。排序后,您可以通过数组进行一次计算,计算每个值的出现次数。因为数组已经排序,所以一旦值发生变化,您就会知道您已经看到所有出现的前一个值。

答案 1 :(得分:7)

许多其他海报建议对数据进行排序,然后查找相邻值的数量,但是没有人提到使用基数排序来使运行时变为O(n lg U)(其中U是最大值)数组)而不是O(n lg n)。由于lg U = O(lg n),假设整数占用一个机器字,这种方法渐近比heapsort快。

非比较分类在面试中总是很有趣。 : - )

答案 2 :(得分:2)

对其进行排序,然后从头开始扫描以确定每个项目的计数。

此方法不需要额外的存储空间,可以在O(n log n)时间内完成(对于排序)。

答案 3 :(得分:1)

如果int值的范围有限,那么您可以分配一个数组,用于计算每个可能值的出现次数。然后你只需遍历你的巨大阵列并增加计数器。

foreach x in huge_array {
   counter[x]++;
}

因此,您可以在线性时间(O(n))中找到解决方案,但代价是内存消耗。也就是说,如果你的整数跨越32位整数允许的整个范围,你需要分配一个4G整数的数组,这是不切实际的......

答案 4 :(得分:1)

如何使用BloomFilter impl:如http://code.google.com/p/java-bloomfilter/ 首先执行bloom.contains(element)如果为true,则返回false bloom.add(element)。

最后计算添加的元素数量。 Bloomfilter需要大约。 250mb内存,每个元素10位存储100000000个元素。

问题是BloomFilters中可能出现误报,并且只能通过增加每个元素的位数来最小化。这可以通过两个需要同意的具有不同散列的BloomFilter来解决。

答案 5 :(得分:0)

在这种情况下散列并不合适。对于迭代数组,成本大约为O(N)O(N),对于哈希表迭代,成本约为O(N)。由于您需要O(N)来检查每个元素,因此复杂性很高。

答案 6 :(得分:0)

排序是一个好主意。但是,排序类型取决于可能值的范围。对于小范围计数排序会很好。在处理如此大的阵列时,使用多个核心会很有效 - 基数排序可能会很好。

答案 7 :(得分:-2)

查看它的变体,它可能会帮助您找到“否”。不同的元素。

#include <bits/stdc++.h>
using namespace std;

#define ll long long int
#define ump unordered_map

void file_i_o()
{
ios_base::sync_with_stdio(0); 
cin.tie(0); 
cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}

int main() {
file_i_o();
ll t;
cin>>t;
while(t--)
{
    int n,q;
    cin>>n>>q;
    ump<int,int> num;
    int x;
    int arr[n+1];
    int a,b;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        arr[i]=x;
        num[x]++;
    }
    for(int i=0;i<q;i++)
    {
        cin>>a>>b;
        num[arr[a]]--;
        if((num[arr[a]])==0)
        { num.erase(arr[a]); }
        arr[a]=b;
        num[b]++;
        cout<<num.size()<<"\n";

    }
}
return 0;
}