输入:未排序的整数数组A[1..n]
,只有O(d) :(d < < n)
个不同的元素。
输出:所有出现两次的元素。
要求两种算法,一种是O(Nd)
,另一种是O(Nlogd)
。最大数量可能非常大,因此计算频率的大小为n
的数组可能不是一个好主意。有什么想法吗?
澄清一下,“只有O(d) :(d < < n)
个不同的元素”意味着所有其他元素(不是那些O(d)
元素)出现两次或更多。
答案 0 :(得分:1)
O(nd)
基本上迭代所有可能的元素(O(d)
)并计算它重复的次数。每次迭代都是O(n)
O(nlogd)
是构建一个histogram (map:int->int
),它计算每个元素在一次迭代中出现在列表中的次数。地图为balanced Binary Search Tree,以确保O(nlogd)
。请注意,如果您使用hash map而不是树,则可以将其增加到O(n)
平均大小写(但O(nd)
最差情况)
Psuedo代码 - O(nlogd):
map <- new tree map
for each element x in list:
if x is in map:
map.put(x,map.get(x)+1)
else:
map.put(x,1)
for each (key,value) in map:
if value == 2:
print key
答案 1 :(得分:0)
对数组进行排序。 O(nlogn) 扫描数组以找到仅出现两次的元素.O(n)
重复元素将并排。
为O(n)+ O(nlogn)。
答案 2 :(得分:0)
使用平衡树计算所有值的频率。因为只有d dinstinct值,所以树的大小只有d,并且它上面的所有操作都将被记录。我们将所有元素插入到树中,并计算树中节点的频率,总复杂度为O(N * logd)。
C++ code:
vector<long long> solve()
{
vector<long long> ans;
map<long long, int> cnt;
for(int i = 0; i < n; ++i)
cnt[a[i]] += 1; // O(logd)
for(map<long long, int>::iterator it = cnt.begin(); it != cnt.end(); ++it)
if(it -> second == 2) ans.push_back(it -> first);
return ans;
}