找出所有给定数组中常见元素的最佳算法

时间:2014-01-02 11:18:12

标签: c# c++ arrays algorithm

假设有10个数组,我们必须找出给定数组中的所有常见元素。

目前我正在选择第一个数组,并且对于第一个数组中的每个元素,我遍历所有剩余的数组,但这会增加时间复杂度。

有没有任何好的算法可以做到最少没有比较?

3 个答案:

答案 0 :(得分:5)

我假设你想要数组的intersection

基于哈希的方法:

这假定每个单独数组中有唯一的元素。

将第一个数组中的所有元素插入到要计数的元素的哈希映射中,计数从1开始。

然后遍历剩余的数组,增加每个遇到元素的计数。

最后,输出计数等于数组数的所有元素。

您可以在C#中使用Dictionary或在C ++ 11中使用unordered_map。您也可以在此处使用有序地图(例如,C ++中的map)。

基于排序的方法:

单独对所有数组进行排序。

同时遍历所有数组,保持每个数组中包含一个元素的heapbinary search tree。在每个步骤中,从结构中删除最小值,并从该元素所在的数组中添加下一个元素。

每当最小值=最大值时,输出该值。

我的猜测是,这可能与set_intersection非常相似。

处理每个单独数组中的非唯一值:
(即1 2 2 3 42 2 4 5的“交叉点”应输出2 2 4

  • 您需要记住上次输出值的时间,并且只在插入了大于或等于数组数的元素后才输出值。

    如果你不这样做,你会得到太多结果。查看交叉1, 11, 1以及1, 1的简单示例。预期输出为1, 1,但这会发生:

    结构:1, 1, 1
    最小值=最大值= 1,输出1
    删除第1个阵列中的1并插入第2个1 结构:1, 1, 1
    最小值=最大值= 1,输出1
    删除第二个数组中的1并插入第二个1
    结构:1, 1, 1
    最小值=最大值= 1,输出1
    删除第3个阵列中的1并插入第2个1 结构:1, 1, 1
    Min = max = 1,输出1

    现在输出为1, 1, 1, 1

  • 插入时,请确保始终在所有其他相等值之后插入(即将其视为大于它们)。为此,您只需将自动递增的唯一ID作为辅助比较值。

    如果你不这样做,你可以继续从同一个数组中删除元素,这会很快将你带到另一个元素,因此你不一定会输出正确数量的非唯一值。

    例如,如果我们将1, 1, 1, 21, 1, 1相交,您可能会碰巧从第一个数组中重复删除,分3步进入2,但是,由于在上面,我们只输出每两步,因此我们只有2而不是3 1

答案 1 :(得分:4)

在c ++中有一个标准算法std::set_intersection。它适用于两个已排序的序列。我想你几乎不会比这更好。对所有数组进行排序,然后按顺序调用set_intersection以获得结果。总体复杂度为O(N*log(N)),其中N是数组的长度(如果长度不同,则为最大长度)。

答案 2 :(得分:0)

如果您是关于C#的,那么有一个名为language-integrated query的好东西,它可以尽可能简化查询集合并提供并行执行(PLINQ)。在C#中,您只需write inner join query即可获得多个数组。