给定O(n)集,找出其中的不同集合有什么复杂性?

时间:2019-07-16 05:05:02

标签: algorithm data-structures time-complexity complexity-theory

我有一个应用,其中有O(n)个列表。

每个集合Set(i)是一个n-vector。例如,假设n=4

Set(1)可能是[0|1|1|0]

Set(2)可能是[1|1|1|0]

Set(3)可能是[1|1|0|0]

Set(4)可能是[1|1|1|0]

我想处理这些集合,以便仅将其中的唯一集合作为输出。因此,在上面的示例中,我将得到以下输出:

Set(1), Set(2), Set(3)。请注意,Set(4)Set(2)相同,因此已被丢弃。

一种相当蛮力的方法可以解决这个问题,这给了我O(n^3)的最坏情况:

Given: Input List of size O(n)
Output List L = Set(1)

for(j = 2 to Length of Input List){ // Loop Outer, check if Set(j) should be added to L
    for(i = 1 to Length of L currently){ // Loop Inner
       check if Set(i) is same as Set(j) //This step is O(n) since Set() has O(n) elements
       if(they are same) exit inner loop
       else
            if( i is length of L currently) //so, Set(j) is unique thus far
                  Append Set(j) to L               
    }
 }

n上没有先验约束:它可以任意大。这似乎排除了使用简单的哈希函数(将二进制集映射到十进制)的可能性。我可能是错的。

除了O(n^3)以外,还有其他方法可以在最坏的情况下更好地运行吗?

4 个答案:

答案 0 :(得分:3)

长度为n的

O(n)个序列的大小为O(n ^ 2)。您不会比这更好的复杂性,因为可能至少需要您阅读所有输入。例如,所有序列都可能是相同的,但是您必须全部阅读它们才能知道这一点。

可以将长度为n的二进制序列插入到trie或基数树中,同时在O(n)时间内检查是否已经存在。对于所有序列来说,它们的总和都是O(n ^ 2),因此简单地使用trie或基数树查找重复项是最佳选择。

请参阅:https://en.wikipedia.org/wiki/Trie 和:https://en.wikipedia.org/wiki/Radix_tree

答案 1 :(得分:2)

您可以考虑使用平衡的二叉树实现集合。在这样的树中插入新节点的成本为O(lgm),其中m是树中元素的数量。重复将被隐式删除,因为如果我们检测到这样的节点已经存在,那么就不会添加它。

在您的示例中,查找/插入操作的总数为n*n,因为有n个集合,每个集合都有n个值。因此,总时间可能会缩放为O(n^2*lg(n^2))。胜过O(n^3)

答案 2 :(得分:1)

首先,这些不是集合而是位串。

接下来,对于每个位串,您都可以将其转换为数字并将该数字放入哈希集中(或简单地存储原始位串,大多数哈希集实现都可以做到这一点)。之后,您的哈希集将包含所有唯一项。 O(N)时间,O(N)空间。如果需要保持字符串的原始顺序,则在第一个循环中检查每个字符串是否已经在哈希集中,如果不是,则将其输出并插入哈希集中。

答案 3 :(得分:0)

如果您可以使用O(n)多余的空间,则可以尝试以下操作:

首先,让我们假设向量是二进制数,因此0110变为6。

  • 如果矢量中的数字为[0,1],则可以乘以10而不是2。

将所有矢量转换为小数将花费O(4n)。 对于每个转换后的数字,我们将通过十进制数字映射向量。为了实现这一点,我们将使用一个n大小的哈希图。

  1. HM <-n大小的哈希图
  2. 对于每个向量v: num <-v转换的十进制数 将num映射v到HM
  3. 在HM上循环,每个索引只取一个

按步骤运行:

  1. O(n)
  2. O(n *(4 + 1)),当映射时间为1时,向量长度为​​4
  3. O(n)