Problem Overview

  • We are given an array of strings strs
  • Our goal is to group the anagrams together and return an array of array of strings
  • All strings are in lowercase English letters

Leetcode - Group Anagrams

Example

Input:  strs = ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
  • nat and tan are anagrams
  • ate, eat and tea are anagrams
  • There is no anagram for bat in the array

If you dont know how to find anagrams then refer this Valid Anagrams

Brute Force

Intuition

  • We need to pick one string and using it, iterate over the other strings
  • We need to check whether the character frequencies of the other string match the selected string

Code

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {

        int n = strs.size();

        vector<vector<string>> result;
        vector<int> isGrouped(n, 0);

        for (int i = 0; i < n; i++) {

            if (isGrouped[i] == 1)
                continue;

            vector<int> freq(26, 0);
            string temp = strs[i];

            for (auto it : temp) {
                freq[it - 'a']++;
            }

            vector<string> group;

            for (int j = i; j < n; j++) {
                if (temp.size() != strs[j].size()) continue;

                bool flag = isAnagram(strs[j], freq);

                if (flag == true) {
                    group.push_back(strs[j]);
                    isGrouped[j] = 1;
                }
            }

            result.push_back(group);
        }

        return result;
    }

    bool isAnagram(string str, vector<int> freq) {
        for (char c : str) {
            if (--freq[c - 'a'] < 0) {
                return false;
            }
        }
        return true;
    }
};

Time and Space Complexity

  • Time — O(n² · m) — for each of the n strings, we compare against n others, and each comparison scans up to m characters
  • Space — O(n) — for the isGrouped array

Why It Fails

  • For every string, we’re comparing it against all other strings character by character
  • This takes O(n² · m) time — too slow for large inputs
  • We’re repeatedly scanning strings instead of using a smarter key to group them

Optimization

Intuition

  • If two strings are anagrams, sorting them gives the same string — we can use that sorted string as a key to group them

Code

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {

        unordered_map<string, vector<string>> mp;

        for (auto it : strs) {
            string key = it;
            sort(key.begin(), key.end());
            mp[key].push_back(it);
        }

        vector<vector<string>> result;
        for (auto& [key, group] : mp) {
            result.push_back(group);
        }

        return result;
    }
};

Time and Space Complexity

  • Time — O(n · m log m) — we iterate over all n strings, and sorting each string of length m takes m log m
  • Space — O(n · m) — for storing all strings in the hashmap

Key Takeaways

  • Sometimes a small observation can lead you straight to the solution — like the fact that sorted anagrams are always identical strings