【问题标题】:Count the number of similar words having same letters [duplicate]计算具有相同字母的相似单词的数量[重复]
【发布时间】:2015-09-19 19:41:20
【问题描述】:

问题:

如何识别或统计具有相同的相似词的数量 字母(字母的数量应该相同,顺序可以是任何东西)。

例如,以下是单词:

aabb, aaab, abbb, abaa, abab, aabc, caba, babb, baaa

以下是相似词:

aabb, abab
aaab, abaa, baaa
abbb, babb
aabc, caba

以下是我得到的基本逻辑:

方法一: 首先对单个单词中的字母进行排序。 比较排序后的单词。

方法二: 比较剩余单词中每个单词的每个字母。 (这将是最高的迭代次数)

请提出一些更好的解决逻辑..

【问题讨论】:

  • 方法1有什么问题?
  • 需要更高效的逻辑..他们不值得..
  • 排序并不是真正需要的,我只会使用一组多重集。如果没有可用的多集实现,您只需要一个Set<Set<Pair<Character,Integer>>>
  • 有很多方法可以做到这一点。您是否尝试过至少实现您提到的两种方法之一?
  • 为每个算法找到大 O,并选择更好的一个

标签: java algorithm logic


【解决方案1】:

好吧,如果您有效地使用排序的单词,您的方法 1 几乎可以有效地解决问题。

首先,对单词进行排序。

现在您已将问题简化为Element Distinctness Problem,“相似词”刚刚变得相同。

可以通过以下两种方式之一完成:

  • 对(排序的)单词列表进行排序,并迭代所有“相似”单词 将彼此相邻。
  • 在维护哈希表的同时进行迭代,该哈希表计算您看到每个单词的次数。 (这种方法不需要第二类)。

您可以使用直方图,其中每个直方图计算每个字符的出现次数。每个单词都有这样的直方图,并检查相同的直方图。

【讨论】:

  • 我不明白您为什么要尝试基于排序的“复杂”解决方案,而根本不需要它。只需使用一些哈希集就可以了。我错过了什么吗?
  • @Dici Hashing 并不比排序复杂,而是不同。我还提到了如何在不进行排序的情况下进行操作,如果您阅读了整个答案(或者如果您不知道直方图是什么,请要求澄清),您会看到它
  • 散列比排序快,HashMap 的内存开销很小。感觉这不是这里的自然方法,如果你问任何非程序员,他们只会计算每个单词中的字母并比较结果。我没有明确指出您提出了一个不基于排序的解决方案,因为您以 first, sort the words 开头,但我现在可以看到您在最后一句话中这样做了
  • @Dici 如果字符串很短 - 那么散列中涉及的常量可能会克服 log(n) 因素(与排序相比,散列的常量很差)。如果它们不短 - 额外的内存可能是一个问题。这是一个经典问题,人们必须在现有的权衡中选择哪个更可取。
  • 在实践中,重要的变量是单词的数量而不是它们的长度。在这方面,散列可以更好地扩展。但无论如何,你给出了两个答案,所以很好:)
【解决方案2】:

首先,你需要有一个LetterCluster 的类。在那个类中,您应该存储一个字符和数字的Map,一个长度数字以及找到的符合该组的单词。然后,想法是在每次迭代中为每个单词迭代所有单词和所有存在的组:

  1. 您将String 的长度与组的字符数进行比较。如果不匹配,则无需进一步分析,因为不同长度的字符串不可能有相同的字母

  2. 如果长度相同。如果String的Map与组的map等价,则将String加入组的词集合并停止迭代

  3. 如果没有找到该单词的兼容组,则创建一个新组,将单词的长度、其Map 及其自身存储在集合中。

请注意,此分组有效地划分了您的单词,您可以在同一组中看到具有相同字母表的单词。

【讨论】:

    【解决方案3】:

    我会说:计算每个不同的字母。然后比较计算出来的数字。

    像'aabb' => a = 2, b = 2; 'abab' => a = 2, b = 2; 'aaab' => a = 3, b = 2。

    时间复杂度应该不错,但内存复杂度与您正在使用的字母表中包含的字母数量成线性关系。

    【讨论】:

    • 字母表中的字母个数是恒定的,复杂度无法在此表达!你的解决方案(和我的)的内存复杂度是O(number of anagrams),更糟糕的是O(number of words)。因此,它确实是线性的,但与字母表中的字母数量无关
    【解决方案4】:

    我不应该给你一个完整的答案,但我有一个简洁的功能解决方案:

    Stream.of("aabb", "aaab", "abbb", "abaa", "abab", "aabc", "caba", "babb", "baaa")
          .map(s -> s.chars().boxed().collect(Collectors.groupingBy(i -> (char) i.intValue(), Collectors.counting())))
          .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
    

    【讨论】:

      【解决方案5】:

      首先以某种精确的方式定义相似度。

      如果满足以下条件,您可以说两个词相似:

      A1。它们是由相同的字母构成的

      A2。单词 w1 在位置 p 的字母可以在 word2 的位置 (p-N ... p+N) 找到

      以上两个 defs 都可以匹配您的请求,但不同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-08-25
        • 2020-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多