最近在一些采访中被问到“如果存在于超过百万字符串的列表中,如何找到所有字符串的反转?”
例如str [1] =“abc”,我需要准确检查“cba”,没有字谜。
方法1.将所有字符串存储在散列集中,从第一个字符串开始遍历并检查Hashset中是否存在反转形式。如果是,那么对else移动到下一个元素。
如果内存是约束,你能建议任何方法吗?
答案 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伪代码更容易理解我的简单英语。
注意:
这是我能想到的内存消耗最少的代码:
// "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 =以该字符开头的字符串列表