LeetCode – Group Anagrams (Java)

Given an array of strings, return all groups of strings that are anagrams.

Analysis

An anagram is a type of word play, the result of rearranging the letters of a word or phrase to produce a new word or phrase, using all the original letters exactly once; for example, Torchwood can be rearranged into Doctor Who.

If two strings are anagram to each other, their sorted sequence is the same.

Updated on 5/1/2016.

Java Solution

public List<List<String>> groupAnagrams(String[] strs) {
    List<List<String>> result = new ArrayList<List<String>>();
 
    HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
    for(String str: strs){
        char[] arr = new char[26];
        for(int i=0; i<str.length(); i++){
            arr[str.charAt(i)-'a']++;
        }
        String ns = new String(arr);
 
        if(map.containsKey(ns)){
            map.get(ns).add(str);
        }else{
            ArrayList<String> al = new ArrayList<String>();
            al.add(str);
            map.put(ns, al);
        }
    }
 
    result.addAll(map.values());
 
    return result;
}

Time Complexity

If the average length of verbs is m and array length is n, then the time is O(n*m).

Category >> Algorithms >> Interview  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • Nick. W

    Use int[] array and codePointAt to calculate a key. This also relaxes the constrain on the character range of input strings.

    int []cArry = new int[128];
    for (int i=0; i < str.length(); i++){
    cArry[str.codePointAt(i)]++;
    }
    String key = new String(cArry,0,cArry.length);

  • Nick. W

    The posted solution assumes strings in input array are all lower case between ‘a’ to ‘z’. ‘arr’ array holds the count of occurrences of characters from ‘a’ to ‘z’ for each string in input array.

  • mike

    if there are some words which have some characters appear more than 65535 times, will the char[] be a problem

  • Souradeep Barua

    I tried this but it was much slower than the solution given here. I guess the multiplication takes more time for large words.

  • Caleb

    Hi, dear programmer! I’m a fresh bird in practicing leetcode. What is the meaning of the following code? (Since the type in arr is char, then how is it possible to do “arr[ ] ++” in the for loop? Thank you!
    char[] arr = new char[26];
    for(int i=0; i<str.length(); i++){
    arr[str.charAt(i)-'a']++;
    }

  • Razvan Madalin MATEI

    A smarter solution is to use a hash function that applied to a word and any of its anagrams, will result in the same hash value. Such a hash can be constructed like this: assign a prime number to all the letters in the alphabet: a->2, b->3, c->5, d->7, etc. Construct the hash value of a string by multiplying the equivalent prime numbers.

  • Suriya

    It is more performance efficient to not use String utils. Try checking the time of execution and you will know the rest.

  • Jeff Guo

    Sorting is O(nlgn), here is the O(n) one.

    public static bool IsAnagram(string str1, string str2) {

    if(str1.Length != str2.Length)
    return false;

    int[] counter = new int[256];

    foreach(char c in str1)
    {
    counter[c]++;
    }

    foreach(char c in str2)
    {
    counter[c]–;
    }

    for(int i =0; i 0)
    return false;
    }

    return true;
    }

  • ThinkFree

    That’s cool.
    However, I had one doubt. Let say a word “RAT” is given. there are six possible combinations of it. RAT, RTA, TRA, TAR, ART, ATR. Now out of all these anagram combinations, what is the most efficient way to find out the valid english words? (given that we have access to dictionary, how the comparison will work?)

  • Chris

    Why cannot we use the version below?

    public static boolean anagram(String str1, String str2) {
    str1 = str1.replaceAll(“\s+”,””).toUpperCase();
    str2 = str2.replaceAll(“\s+”,””).toUpperCase();
    char[] cStr1 = str1.toCharArray();
    char[] cStr2 = str2.toCharArray();
    Arrays.sort(cStr1);
    Arrays.sort(cStr2);
    return String.valueOf(cStr1).equals(String.valueOf(cStr2));
    }

  • Satish

    public static boolean anagram(String str1, String str2) {

    if (str1.length() != str2.length()) {

    return false;

    }

    HashMap buff = new HashMap();

    for (int i = 0; i < str1.length(); i++) {

    char c1 = str1.charAt(i);

    char c2 = str2.charAt(i);

    if (buff.keySet().contains(c1)) {

    int count = buff.get(c1) + 1;

    if (count == 0) {

    buff.remove(c1);

    } else {

    buff.put(c1, count);

    }

    } else {

    buff.put(c1, 1);

    }

    if (buff.keySet().contains(c2)) {

    int count = buff.get(c2) – 1;

    if (count == 0) {

    buff.remove(c2);

    } else {

    buff.put(c2, count);

    }

    } else {

    buff.put(c2, -1);

    }

    }

    return buff.size() == 0;

    }