输入:一个未排序的整数数组A[1..n]
,只有O(d) :(d < < n)
不同的元素。
输出:所有恰好出现两次的元素。
要求两种算法,一种是 with O(Nd)
,另一种是O(Nlogd)
。最大数量可能非常大,因此n
计算频率的大小数组可能不是一个好主意。任何想法?
澄清一下,“只有O(d) :(d < < n)
不同的元素”是指所有其他元素(不是那些元素O(d)
)出现两次或更多。
输入:一个未排序的整数数组A[1..n]
,只有O(d) :(d < < n)
不同的元素。
输出:所有恰好出现两次的元素。
要求两种算法,一种是 with O(Nd)
,另一种是O(Nlogd)
。最大数量可能非常大,因此n
计算频率的大小数组可能不是一个好主意。任何想法?
澄清一下,“只有O(d) :(d < < n)
不同的元素”是指所有其他元素(不是那些元素O(d)
)出现两次或更多。
O(nd)
基本上是迭代所有可能的元素(O(d)
其中的)并计算它重复的次数。每次迭代都是 O(n)
O(nlogd)
是建立一个直方图( map:int->int
),计算每个元素在单次迭代中出现在列表中的次数。该映射是基于平衡二叉搜索树的,以确保O(nlogd)
。请注意,如果您使用哈希映射而不是树,则可以将其增加到O(n)
平均情况(但O(nd)
最坏情况)
伪代码- 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
使用平衡树计算所有值的频率。因为只有 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;
}
对数组进行排序。O(nlogn) 扫描数组以找到只出现两次的元素。O(n)
重复元素将并排排列。
O(n)+O(nlogn)。