LeetCode – Group Anagrams (Java)

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

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.

Java Solution

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

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).

15 thoughts on “LeetCode – Group Anagrams (Java)”

  1. this is just checking for anagram… the question is grouping same anagram together with an array of strings…

  2. here is one more approach

    Take all letters, sort them, return a String. All anagrams of the same letters will have the same keys.

    With that key system, the basic code can be come simpler with:

    private static final String anagramKey(String word) {

    word = word.toLowerCase();

    char[] chars = word.toCharArray();

    Arrays.sort(chars);

    return new String(chars);

    }

    HashMap<String,List> matchMap = new HashMap();

    for (String word : args) {

    String key = anagramKey(word);

    if (!matchMap.containsKey(key)) {

    matchMap.put(key, new ArrayList());

    }

    matchMap.get(key).add(word);

    }

    System.out.println(matchMap);

  3. 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);

  4. 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.

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

  6. 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']++;
    }

  7. 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.

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

  9. 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;
    }

  10. 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?)

  11. 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));
    }

  12. 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;

    }

Leave a Comment