这是我和我的一个朋友之间的辩论:制作一个valiation方法的最快方法是检查给定的字符串是否有一个不允许的字符
方法I:简单
char [] invalidChars = "!@#$%^...".toCharArray();
for (int i = 0; i < myString.length(); i++) {
char ch = myString.charAt(i);
for (int j = 0; j < invalidChars.length; j++) {
if (invalidChars[j] == ch) {
return false;
}
}
}
方法II:利用地图的O(1)
Map <String,String> map = new HashMap<String, String>();
map.put("!", null);
map.put("@", null);
map.put("#", null);
map.put("$", null);
map.put("^", null);
...
for (int i = 0; i < labels.length(); i++) {
char ch = labels.charAt(i);
if (map.containsKey(ch)) {
return false;
}
return true;
}
方法I实际上是N2,但当invalidChars数量较少时,与N一样好。 第一种情况应该优先考虑:有很多无效字符,案例二:只有少数无效字符?
注意:我不是在寻找任何内置的java解决方案,而只是用于过滤少数(不是全部)非文本字符的算法
答案 0 :(得分:5)
如果您只对验证ASCII字符感兴趣,那么长度为128的布尔查找表可能比上述任何一种方法都快。
答案 1 :(得分:1)
有一种简单的方法可以为您提供O(n log(m))
时间复杂度,其中n
是输入的长度,m
是不允许的字符数。
一次扫描输入的一个字符,并使用二进制搜索在(已排序的)不允许的字符数组中查找当前字符。
答案 2 :(得分:1)
如果您使用HashSet,它会在添加时为您提供O(1)并包含:
导致O(m + n),其中m是禁止字符的数量,n是字符串的长度。但我已经看到了表现更好的答案。
但请记住,大多数事情都有开销(比如HashSet / HashMap中的“哈希”)。因此,即使渐近性能可能更好,但天真的实现可能对小输入更快。我不是说你应该使用具有O(n²)的东西,但是对于一组通用数据,将O(n log n)解决方案与O(m)解决方案进行比较可能是值得的!
答案 3 :(得分:1)
最快! HashMap是最快的解决方案,理论上它只是O(1)。
在java中: java.util.BitSet 是专为您的需求而设计的。 或者使用self unwrapped long [] / int []数组(取决于目标体系结构32/64)
为什么HashMap不好?来自访问和创建桶的额外行李高于其右侧的查找。
答案 4 :(得分:0)
构建一个hashmap并将项目放在那里相对昂贵。但是,正如您所说,在哈希映射中查找项目是O(1)。
所以我们有hashmap fill:O(n log n),查找O(1)。
或标准方式(填写O(1)查找O(n))。
然而,由于O(n)查找发生在每个字符串中,所以第一个方法总共是O(numberOfInvalidChars + strings * NumberofInValidChars),第二个方法是O(numInv log numInv + strings)。哪些方式更便宜,所以几乎总是更便宜。