【问题标题】:Searching for a particular String in an array在数组中搜索特定字符串
【发布时间】:2014-05-27 11:41:18
【问题描述】:

我想知道在String 数组中检查单词是否存在的最快方法/算法是什么。例如,如果我有一个包含 10,000 个元素的字符串数组,我想知道它是否包含“人类”一词。我可以对数组进行排序,没问题。

但是,二进制搜索 (Arrays.binarySearch()) 是不允许的。 HashSetHashMapArrayList 等其他集合类型也是不允许的。

是否有任何经过验证的算法?还是有什么其他方法?搜索的方式应该非常非常快。

【问题讨论】:

  • 是不允许二分搜索,还是仅仅使用它的库实现?同样,您是否可以滚动自己的散列数据结构?
  • @PatriciaShanahan:嗨,你是说 HashMap 吗?
  • @PatriciaShanahan:我的话已经散列了。这意味着,我有 3 个字符的格式。例如,单词“astronaut”将是“!2#”
  • 不,我的意思是自己实现一个散列数据结构,而不依赖于现有的库实现。

标签: java arrays string performance algorithm


【解决方案1】:

您可以排序的最快方式将导致 O(nLogn) 复杂度 因此,如果您要在无序数据中查找特定单词,只需使用单个 for 循环扫描数组,这将花费您 O(n)

【讨论】:

  • that will cost you O(n*length of word) for EACH WORD ...非常昂贵。
  • length_of_word 本质上不是一个变量,所以从渐近符号 O(n)=O(100000000000*n)
  • @VilenMelkumyan 当然它是一个变量。我可以很容易地想象有无限字长的字典
  • 是的,但我想这取决于您的数据以及您如何查看它,一般来说,如果您有一个字符串数组,确定有一个字符串具有最大长度,因此单词的长度是有界的.如果字符串数组不同,你是对的。
【解决方案2】:

为了获得最快的性能,您必须使用散列。
您可以使用rolling hash
它确保更少的碰撞次数。

hash = [0]*base^(n-1) + [1]*base^(n-2) + ... + [n-1]   

其中base 是质数,比如31

你还需要取模,所以整数范围不超过prime number

时间复杂度:O(number of characters) 考虑乘法和模O(1) 运算。

这里给出了很好的解释:Fast implementation of Rolling hash

【讨论】:

    【解决方案3】:

    从数组中构建一个trie。它可以在线性时间内构建(假设字母大小不变)。然后您也可以在线性时间内查询(时间与查询字长成正比)。预处理和查询时间都是渐近最优的。

    【讨论】:

    • +1 提出这个问题。创建 trie 会是一次成本吗?就像如果我想向已经创建的 trie 添加一组单词,它会再次搜索该特定节点并添加到它还是完全创建一个新的 trie?
    • @bgth 是的,您可以通过该算法直接在 trie 中插入和删除。那里的运行时间也是线性的(最优的),所以如果你最初从一个空的 trie 开始并一个接一个地添加单词,你仍然会得到整体的线性时间
    • 但它是在这个问题中查找整个字符串而不是最接近的正确工具吗?它也不会为上面的所有节点抛出匹配项吗?比如,如果你在搜索“Hum”,它不会匹配“Hum”和“Huma”以及“Human”和“Humanitarian”吗?
    • @bgth:你走到代表字符串“Human”的节点。然后你检查它是否有一个布尔标记,上面写着“输入词之一由这个节点表示”。老实说,我不认为有问题。它绝对是算法意义上的正确工具,因为它具有最佳的运行时界限。而且它在实践中也非常快(但由于缓存未命中,可能不如基于散列的方法快)。
    • 你能指点我一本书,里面有这个和其他阅读算法的细节吗?
    猜你喜欢
    • 1970-01-01
    • 2013-03-02
    • 2020-09-29
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2016-09-05
    • 1970-01-01
    相关资源
    最近更新 更多