超过百万字符串列表中的成对字符串是否相反?

时间:2011-09-29 23:23:19

标签: string reverse

最近在一些采访中被问到“如果存在于超过百万字符串的列表中,如何找到所有字符串的反转?”

例如str [1] =“abc”,我需要准确检查“cba”,没有字谜。

方法1.将所有字符串存储在散列集中,从第一个字符串开始遍历并检查Hashset中是否存在反转形式。如果是,那么对else移动到下一个元素。

如果内存是约束,你能建议任何方法吗?

6 个答案:

答案 0 :(得分:4)

如果允许,您可以就地对字符串进行排序,这样当您查找字符串的反向时,您可以进行二进制搜索。

答案 1 :(得分:1)

您可以使用Bloom Filter来告诉您字符串是否已存在于类似哈希表的结构中,但每个存储桶只有0或1,因此使用的空间非常小。

恰好1 000 000位== 125 KB

答案 2 :(得分:1)

首先,我会使用与方向无关的散列来散列字符串。这可能是一个简单的字符总和,虽然肯定有更好的方案可以从两端散列。为了“使交易更加甜蜜”,可以将字符串长度附加到哈希值,或以其他方式将其合并到哈希值中。

然后,当您将字符串分解为相同的哈希组时,请执行“长手”比较。

请注意,使用此方案或您只是向前或向后使用方向相关哈希的方案,要做的是不立即将字符串插入哈希集,而是检查它(使用反向哈希如果需要)首先,如果你得到一个匹配(并且随后的长比较为真),删除已经散列的字符串并将两者配对。第二个字符串永远不会进入集合,并且,如果所有字符串最多匹配,则哈希集中只有500,000个条目,如果字符串是随机的,则可能接近250,000(我没有坐过下来计算概率)。

所以你只需要通过一组字符串来完成整个事情。

答案 3 :(得分:1)

<击> 使用“内存作为约束”然后我甚至不会使用HashSet(其中,afaik也将删除原始列表中的重复字符串)因为您将使用其他结构需要一些记忆的HashSet。

排序,也不会改善内存使用情况。

我会使用原始列表(已经存在,因此不会使用额外的内存)+一个3字节的整数变量来迭代列表。 3个字节可以遍历2 ^ 24 = 16777216个字符串的列表

以“内存作为约束”,我会选择2 for循环。我认为C-Like伪代码更容易理解我的简单英语。

注意:

  1. 从问题中提供的示例中,它实际上不是List而是Array,因此我将对结构进行操作,就好像它是一个数组
  2. 问题不清楚是否如何配对“abc”,“def”,“cba”,“abc”。我将第一个“abc”与“cba”配对,并将“cba”与“第二个”abc配对“(意图在问题中不清楚)
  3. 我假设我们无法修改原始列表
  4. 这是我能想到的内存消耗最少的代码:

    // "list" holds the original list (array)
    for (int i = 0; i < length(list) - 1; i++) {
        for (int j = i + 1; j < length(list); j++) {
            if (list[i] == reverse(list[j])) {
                print(list[i] + " reversed is " list[j])
            }
        }
    }
    

    关于内存使用情况,此解决方案将采用2个整数变量(通常每个4个字节)+原始列表,我认为我们无法摆脱它。

    关于CPU使用率(实际上,根据问题不相关),字符串将被反转的次数将是:(N *(N + 1))/ 2其中N是列表的长度

答案 4 :(得分:1)

您可以选择HashTable并使用存储桶来减少哈希冲突。我们现在需要对特定查询字符串做的只是反转它,哈希它并在HashTable中找到而不是从开始到结束遍历。

答案 5 :(得分:1)

这是我的意见:

我会用

创建一个哈希

key = character

value =以该字符开头的字符串列表

  • 现在开始一个循环,你需要从第一个字符串开始。
  • 反转它
  • 取第一个字符并在哈希
  • 中搜索该键
  • 然后在其值中,它包含字符串列表并在该列表中找到字符串