我的任务是编写Java代码以从数据库读取行(其中可以有数千行),并返回数据库中每行的排列总和。例如,如果有3行:
ABCD
BACD
DCAB
然后输出应为3(ABCD == BACD
,ABCD == DCAB
,BACD == DCAB
),其中==
表示'是排列'。
一个明显的答案是(n =字典中的单词,m =单词中的字符):
O(n)
)O(1)
)
O(mlogm)
)O(1)
)i = 0 : n
)(O(n)
)
j = i + 1 : n
)(O(n)
)
array[i] == array[j]
然后count++
(O(1)
)O(1)
)总复杂性:
= 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个哈希值表我相信。)
一些信息:并非所有单词的长度都相同。没有关于分发的信息(它是一个随机排序的数据库)。
有人可以提供一些建议吗?
请不要实际代码。
答案 0 :(得分:0)
继续执行1到4,这需要时间与数据库中的行数成比例。 但在查找重复项之前,您需要对数组进行排序。排序很快。排序后,您会发现彼此相邻的重复项,因此,为了查找重复项,您只需要将每个条目与其邻居进行比较。如果您的数据库非常大,您可以在数据库本身上执行所有这些操作,但如果它只有数百行,您可以在内存中执行此操作。总而言之,这不应该花费超过几秒钟。
答案 1 :(得分:0)
快速解决此问题的最佳方法是使用哈希表。 现在,字典只包含一组有限的字符(每个英文字符通常为52)所有你需要做的就是:
生成所有可能字符的哈希值并将其存储在某个表中。 (使用具有雪崩效应的散列函数,例如SHA -2。雪崩效应确保碰撞概率非常低)。现在虽然这一步骤的复杂程度可能很高(取决于您的语言对SHA -2实现的内部工作),但只需执行固定次数,因此其复杂度为O(1)。 (你应该注意到O(1)并不意味着它最快,散列可能需要几秒钟。)
现在逐个浏览所有单词,只需添加单个字符的哈希值并将其存储为行哈希值。 O(nx)其中x是单词的平均长度。再次要注意的是,x通常是一个很小的数字,例如6-7,使得函数O(7n)=== O(n)
现在只需查看行哈希值,如果两个行哈希值相同,则它们是排列。 O(n)步骤。
O()表示法实际上不是在更精细的粒度上测量算法的快速性的最佳方法。更好的选择是〜符号。
所以我的程序将花费O(n)时间复杂度& O(n)空间复杂度。 (对于步骤1中的散列表,该空间将是常量,并且将等于步骤2中的行数,因此为O(n))。
现在所有怀疑者都相信两个不同的词可能具有相同的哈希值总和, 发生这种情况的概率低于撞击笔记本电脑的流星。
我希望这有助于你