如何为大型数据库排列搜索选择有效的算法?

时间:2014-03-15 10:48:33

标签: algorithm data-structures hashmap permutation

我的任务是编写Java代码以从数据库读取行(其中可以有数千行),并返回数据库中每行的排列总和。例如,如果有3行:

ABCD
BACD
DCAB

然后输出应为3(ABCD == BACDABCD == DCABBACD == DCAB),其中==表示'是排列'。

一个明显的答案是(n =字典中的单词,m =单词中的字符):

  1. 循环访问数据库(O(n)
     在每一行:(O(1)
    1. 按顺序排序(O(mlogm)
    2. 添加到数组(O(1)
  2. 循环数组(i = 0 : n)(O(n)
    1. 循环数组(j = i + 1 : n)(O(n)
      1. 如果array[i] == array[j]然后count++O(1)
  3. 返回次数(O(1)
  4. 总复杂性:

    = O(n) * (O(1) * (O(mlogm) + O(1))) + O(n) * (O(n) * O(1)) + O(1)
    = O(n) * (O(mlogm)) + O(n) * (O(n)) + O(1)
    = O(nmlogm) + O(n^2) + O(1)
    = O(nmlogm + n^2)
    = O(n^2) assuming n >> m
    

    当然,对于大型数据库来说,这是有效的,所以我想看看是否有更好的算法。我曾想过使用哈希表,但不确定如何实现它。因此,在每行读取时可能会记录每个字符的出现次数,但是之后我只看到了两种单词是否相互排列的实现,而不是n个单词 - 这需要多于1个哈希值表我相信。)

    一些信息:并非所有单词的长度都相同。没有关于分发的信息(它是一个随机排序的数据库)。

    有人可以提供一些建议吗?

    请不要实际代码。

2 个答案:

答案 0 :(得分:0)

继续执行1到4,这需要时间与数据库中的行数成比例。 但在查找重复项之前,您需要对数组进行排序。排序很快。排序后,您会发现彼此相邻的重复项,因此,为了查找重复项,您只需要将每个条目与其邻居进行比较。如果您的数据库非常大,您可以在数据库本身上执行所有这些操作,但如果它只有数百行,您可以在内存中执行此操作。总而言之,这不应该花费超过几秒钟。

答案 1 :(得分:0)

快速解决此问题的最佳方法是使用哈希表。 现在,字典只包含一组有限的字符(每个英文字符通常为52)所有你需要做的就是:

  1. 生成所有可能字符的哈希值并将其存储在某个表中。 (使用具有雪崩效应的散列函数,例如SHA -2。雪崩效应确保碰撞概率非常低)。现在虽然这一步骤的复杂程度可能很高(取决于您的语言对SHA -2实现的内部工作),但只需执行固定次数,因此其复杂度为O(1)。 (你应该注意到O(1)并不意味着它最快,散列可能需要几秒钟。)

  2. 现在逐个浏览所有单词,只需添加单个字符的哈希值并将其存储为行哈希值。 O(nx)其中x是单词的平均长度。再次要注意的是,x通常是一个很小的数字,例如6-7,使得函数O(7n)=== O(n)

  3. 现在只需查看行哈希值,如果两个行哈希值相同,则它们是排列。 O(n)步骤。

  4. O()表示法实际上不是在更精细的粒度上测量算法的快速性的最佳方法。更好的选择是〜符号。

    所以我的程序将花费O(n)时间复杂度& O(n)空间复杂度。 (对于步骤1中的散列表,该空间将是常量,并且将等于步骤2中的行数,因此为O(n))。

    现在所有怀疑者都相信两个不同的词可能具有相同的哈希值总和, 发生这种情况的概率低于撞击笔记本电脑的流星。

    我希望这有助于你