【发布时间】:2010-10-14 13:41:41
【问题描述】:
我有一个很大的整数列表(数千个),我想从中提取前 N 个(大约 10-20 个)唯一元素。列表中的每个整数大约出现 3 次。
为此编写一个算法是微不足道的,但我想知道什么是速度和内存效率最高的方法。
在我的案例中还有一些额外的限制和信息:
在我的用例中,我在数组上多次提取我的唯一值,每次都从头开始跳过一些元素。我跳过的元素数量在唯一提取期间是未知的。我什至没有上限。因此排序效率不高(我必须保留数组的顺序)。
整数到处都是,所以位数组作为查找解决方案是不可行的。
我想不惜一切代价避免在搜索期间进行临时分配。
我目前的解决方案大致如下:
int num_uniques = 0;
int uniques[16];
int startpos = 0;
while ((num_uniques != N) && (start_pos < array_length))
{
// a temporary used later.
int insert_position;
// Get next element.
int element = array[startpos++];
// check if the element exist. If the element is not found
// return the position where it could be inserted while keeping
// the array sorted.
if (!binary_search (uniques, element, num_uniques, &insert_position))
{
// insert the new unique element while preserving
// the order of the array.
insert_into_array (uniques, element, insert_position);
uniques++;
}
}
binary_search / insert into array 算法完成了工作,但性能不是很好。 insert_into_array 调用会大量移动元素,这会减慢一切。
有什么想法吗?
编辑
很好的答案,伙计们!每个人都应该得到一个公认的答案,但我只能给出一个。我将实现你的一些想法,并使用一些典型数据进行性能测试。具有导致最快实施的想法的人得到了公认的答案。
我将在现代 PC 和嵌入式 CortexA8-CPU 上运行代码,并以某种方式对结果进行加权。也将发布结果。
编辑:点球大战的结果
Core-Duo 上的时序,在 160kb 测试数据集上进行 100 次迭代。
Bruteforce (Pete): 203 ticks
Hash and Bruteforce (Antti): 219 ticks
Inplace Binary Tree (Steven): 390 ticks
Binary-Search (Nils): 438 ticks
http://torus.untergrund.net/code/unique_search_shootout.zip(C 源和测试数据)
补充说明:
就地二叉树绝对适合真正的随机分布(我的测试数据有上升的趋势)。
二分搜索在我的测试数据上运行良好,超过 32 个唯一值。它的执行几乎是线性的。
【问题讨论】:
-
是否必须将找到的元素保持在原来的顺序?
-
您是否认为需要处理超出起始位置的唯一值不足并且您需要再次换行到源开头的情况? (例如,如果您是随机选择起点,或者来源可能有大量重复(您没有指定))
-
找到的元素的顺序不是问题。
-
我不想回绕,以防我找不到足够的唯一性。在这种情况下,我对少于 N 个唯一身份感到满意。
-
所以你让我们都悬而未决! :)