我想实现一个字符串列表,然后检查列表中的所有元素是否有任何元素是列表中其他元素的前缀。例如
[abc, cde, efg, cdetgh]
在上面的列表中,"cde"
(一个元素)是其他元素"cdetgh"
的前缀。
如果可能的话,我不想迭代整个列表。
答案 0 :(得分:3)
您必须迭代整个列表。天真的方法将强制您为列表中的每个元素迭代整个列表。这是一个O(N ^ 2)算法。
根据列表的大小和执行此操作所需的频率,这可能是可以接受的。你可以做一个权衡,以节省空间为代价。遍历每个元素,并为每个元素创建每个前缀的哈希集,然后查看前缀中元素的检查。
final Map<String, List<String>> prefixes = new HashMap<>();
for (final String element : list) {
// Go through every prefix that is at least 1 in length,
// but shorter than the current element).
for (int len = 1; len < element.length() - 1; ++len) {
final String prefix = element.substring(0, len);
List<String> hasPrefix = prefixes.get(prefix);
if (hasPrefix == null) {
hasPrefix = new ArrayList<>();
prefixes.put(prefix, hasPrefix);
}
hasPrefix.add(element);
}
}
for (final String element : list) {
if (prefixes.containsKey(element)) {
System.out.printf("The element \"%s\" is a prefix of the following elements:\n%s", element, prefixes.get(element).toString());
}
}
该算法的时间为O(N * M),其中N是列表大小,M是平均元素长度。但占用更多的空间。对此有更有效的解决方案,但它们变得越来越复杂,涉及有限状态机构造或前缀树。