【发布时间】:2015-03-14 18:05:08
【问题描述】:
我有一组长度相同的单词。我想找到此哈希集中存在的所有字谜并将它们收集到另一个称为字谜的哈希集中。这是执行此操作的循环:
public HashSet<String> getUniqueAnagramsSlow(HashSet<String> paddedWords, int areAnagramsVersion){
HashSet<String> anagrams = new HashSet<String>();
Object[] paddedWordsArr = paddedWords.toArray();
for(int i = 0; i < paddedWordsArr.length-1; i++){
boolean foundAnagram = false;
String wordOne = (String) paddedWordsArr[i];
if(!anagrams.contains(wordOne))
for(int j = i+1; j < paddedWordsArr.length; j++){
String wordTwo = (String) paddedWordsArr[j];
if(areAnagrams(wordOne, wordTwo, areAnagramsVersion)){
foundAnagram = true;
anagrams.add(wordTwo);
}
}
if(foundAnagram){
anagrams.add(wordOne);
}
}
return anagrams;
}
我编写此代码的目的是了解不同的 areAnagram() 函数如何影响运行时间。我写了两个版本的 areAnagrams()。一种对两个字符串进行排序并进行比较,另一种使用哈希图来比较字符频率。他们在这里:
public boolean areAnagramsVersionOne(String first, String second){
char[] arr1 = first.toCharArray();
Arrays.sort(arr1);
String fSorted = new String( arr1 );
char[] arr2 = second.toCharArray();
Arrays.sort(arr2);
String sSorted = new String(arr2);
return fSorted.equals(sSorted);
}
public boolean areAnagramsVersionTwo(String first, String second){
HashMap<String, Integer> wordOne = new HashMap<String,Integer>();
for(int i = 0; i < first.length(); i++){
String letOne = first.substring(i, i+1);
if(wordOne.containsKey(letOne)){
int letOneFreq = wordOne.get(letOne);
wordOne.put(letOne, letOneFreq + 1);
}else{
wordOne.put(letOne, 1);
}
}
for(int i = 0; i < second.length(); i++){
String letTwo = second.substring(i, i+1);
if(!wordOne.containsKey(letTwo))
return false;
int freq = wordOne.get(letTwo);
if(freq == 0)
return false;
wordOne.put(letTwo, freq-1);
}
return true;
}
据我了解,areAnagramsVersionOne() 将在 NlogN 时间内运行,而 areAnagramsVersionTwo() 将在 N 时间内运行。但是,当我在原始循环中测试这两个版本的查找字谜时,版本二明显变慢了。这是为什么呢?
谢谢。
这是我如何测试运行时间的示例:
long startTime = System.currentTimeMillis();
getUniqueAnagramsSlow(words, 2);
long endTime = System.currentTimeMillis();
System.out.println("exec time: " + (endTime - startTime) );
【问题讨论】:
-
你如何测试它?在开始循环之前,您是否“热身”了 JVM?还是您使用基准框架?
-
性能如何随着 N 的增加而变化?第二个函数结束时不需要检查hashmap中的计数是否为0吗?
-
@sje397 在我的 O(n) 算法中,我在减少哈希图中的值之前检查计数是否为 0。如果为 0,则返回 false,因为我知道第二个单词有一个单词中不存在的字符。
-
@ArjunPatel 但是如果第一个单词有一个不在第二个单词中的字符,您仍然可能返回 true,因为您没有检查 Map 中的所有值是否最后都为 0 .
-
@Eran 所有单词的长度都是一样的。
标签: java hashmap runtime big-o anagram