Best solution for an anagram check?

Drew L. Facchiano picture Drew L. Facchiano · Jul 6, 2016 · Viewed 13.9k times · Source

I’m going through a permutation/anagram problem and wanted input on the most efficient means of checking. Now, I’m doing this in Java land, and as such there is a library for EVERYTHING including sorting. The first means of checking if two string are anagrams of each other is to check length, sort them in some manner, then compare each index of said string. Code below:

private boolean validAnagram(String str, String pair) {
if(str.length() != pair.length()){
    return false;
}

char[] strArr = str.toCharArray();
char[] pairArr = pair.toCharArray();


Arrays.sort(strArr);
str = new String(strArr);

Arrays.sort(pairArr);
pair = new String(pairArr);

for(int i = 0; i<str.length(); i++){
    if(str.charAt(i) != pair.charAt(i)){
        return false;
    }
}
return true;
}

Alternatively, I figured it would be easier to check based on ascii value and avoid a check on every possible character. Code below:

private boolean validAnagram(String str, String pair) {
if(str.length() != pair.length()){
    return false;
}

char[] strArr = str.toCharArray();
char[] pairArr = pair.toCharArray();



int strValue = 0;
int pairValue = 0;

for(int i =0; i < strArr.length; i++){
    strValue+= (int) strArr[i];
    pairValue+= (int) pairArr[i];
}

if(strValue != pairValue){
    return false;
}
return true;
}

So, which is a better solution? I don’t know much about the sort that Arrays is giving me, however that’s the more common answer when I look around the old internets. Makes me wonder if I’m missing something.

Answer

ForguesR picture ForguesR · Jul 6, 2016

Here is a very simple implementation.

public boolean isAnagram(String strA, String strB) {
  // Cleaning the strings (remove white spaces and convert to lowercase)
  strA = strA.replaceAll("\\s+","").toLowerCase();
  strB = strB.replaceAll("\\s+","").toLowerCase();

  // Check every char of strA and removes first occurence of it in strB
  for (int i = 0; i < strA.length(); i++ ) {
    if (strB.equals("")) return false;  // strB is already empty : not an anagram
    strB = strB.replaceFirst(Pattern.quote("" + strA.charAt(i)), "");
  }

  // if strB is empty we have an anagram
  return strB.equals("");
}

And finally :

System.out.println(isAnagram("William Shakespeare", "I am a weakish speller")); // true