Group Anagrams Together

Last Updated : 20 Jul, 2026

Given an array arr[] of strings, group all anagrams together. Two strings are anagrams if they contain the same characters with the same frequencies, possibly in a different order.

Return a 2D array, where each inner array contains a group of anagrams. The relative order of strings within each group should be the same as their order in arr.

Example:

Input: arr[] = ["act", "god", "cat", "dog", "tac"]
Output: [["act", "cat", "tac"], ["god", "dog"]]
Explanation: There are 2 groups of anagrams "god", "dog" make group 1. "act", "cat", "tac" make group 2.

Input: arr[] = ["listen", "silent", "enlist", "abc", "cab", "bac", "rat", "tar", "art"]
Output: [["abc", "cab", "bac"], ["listen", "silent", "enlist"],["rat", "tar", "art"]]
Explanation:
Group 1: "abc", "bac" and "cab" are anagrams.
Group 2: "listen", "silent" and "enlist" are anagrams.
Group 3: "rat", "tar" and "art" are anagrams.

Try It Yourself
redirect icon

[Naive Approach] Compare Every Pair of Strings - O(n^2 × m log m) Time and O(n+k) Space

Treat each unvisited string as the start of a new group and compare it with every remaining unvisited string. If two strings are anagrams (their sorted forms are the same), place them in the same group and mark the matching string as visited. Repeat this process until all strings are grouped.

C++
#include <bits/stdc++.h>
using namespace std;

// Function to check if two strings are anagrams
bool isAnagram(string &a, string &b) {
    if (a.size() != b.size())
        return false;

    string s1 = a;
    string s2 = b;

    sort(s1.begin(), s1.end());
    sort(s2.begin(), s2.end());

    return s1 == s2;
}

vector<vector<string>> anagrams(vector<string> &arr) {
    vector<vector<string>> res;
    int n = arr.size();

    vector<bool> visited(n, false);

    for (int i = 0; i < n; i++) {
        if (visited[i])
            continue;

        vector<string> group;
        group.push_back(arr[i]);
        visited[i] = true;

        for (int j = i + 1; j < n; j++) {
            if (!visited[j] && isAnagram(arr[i], arr[j])) {
                group.push_back(arr[j]);
                visited[j] = true;
            }
        }

        res.push_back(group);
    }

    return res;
}

int main() {
    vector<string> arr = {"act", "god", "cat", "dog", "tac"};

    vector<vector<string>> res = anagrams(arr);

    for (int i = 0; i < res.size(); i++) {
        for (int j = 0; j < res[i].size(); j++)
            cout << res[i][j] << " ";
        cout << "\n";
    }

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;

class GFG {

    // Function to check if two strings are anagrams
    static boolean isAnagram(String a, String b) {
        if (a.length() != b.length())
            return false;

        char[] s1 = a.toCharArray();
        char[] s2 = b.toCharArray();

        Arrays.sort(s1);
        Arrays.sort(s2);

        return Arrays.equals(s1, s2);
    }

    static ArrayList<ArrayList<String>> anagrams(String[] arr) {
        int n = arr.length;

        ArrayList<ArrayList<String>> res = new ArrayList<>();
        boolean[] visited = new boolean[n];

        for (int i = 0; i < n; i++) {
            if (visited[i])
                continue;

            ArrayList<String> group = new ArrayList<>();
            group.add(arr[i]);
            visited[i] = true;

            for (int j = i + 1; j < n; j++) {
                if (!visited[j] && isAnagram(arr[i], arr[j])) {
                    group.add(arr[j]);
                    visited[j] = true;
                }
            }

            res.add(group);
        }

        return res;
    }

    public static void main(String[] args) {
        String[] arr = {"act", "god", "cat", "dog", "tac"};

        ArrayList<ArrayList<String>> res = anagrams(arr);

        for (ArrayList<String> group : res) {
            for (String s : group)
                System.out.print(s + " ");
            System.out.println();
        }
    }
}
Python
def isAnagram(a, b):
    return sorted(a) == sorted(b)

def anagrams(arr):
    n = len(arr)
    visited = [False] * n
    res = []

    for i in range(n):
        if visited[i]:
            continue

        group = [arr[i]]
        visited[i] = True

        for j in range(i + 1, n):
            if not visited[j] and isAnagram(arr[i], arr[j]):
                group.append(arr[j])
                visited[j] = True

        res.append(group)

    return res

if __name__ == "__main__":
    arr = ["act", "god", "cat", "dog", "tac"]
    
    res = anagrams(arr)
    for group in res:
        print(*group)
C#
using System;
using System.Collections.Generic;

class GFG {
    
    // Function to check if two strings are anagrams
    static bool isAnagram(string a, string b)
    {
        if (a.Length != b.Length)
            return false;

        char[] s1 = a.ToCharArray();
        char[] s2 = b.ToCharArray();

        Array.Sort(s1);
        Array.Sort(s2);

        return new string(s1) == new string(s2);
    }

    static List<List<string>> anagrams(string[] arr)
    {
        int n = arr.Length;

        List<List<string>> res = new List<List<string>>();
        bool[] visited = new bool[n];

        for (int i = 0; i < n; i++)
        {
            if (visited[i])
                continue;

            List<string> group = new List<string>();
            group.Add(arr[i]);
            visited[i] = true;

            for (int j = i + 1; j < n; j++)
            {
                if (!visited[j] && isAnagram(arr[i], arr[j]))
                {
                    group.Add(arr[j]);
                    visited[j] = true;
                }
            }

            res.Add(group);
        }

        return res;
    }

    static void Main()
    {
        string[] arr = { "act", "god", "cat", "dog", "tac" };

        List<List<string>> res = anagrams(arr);

        foreach (var group in res)
        {
            foreach (var s in group)
                Console.Write(s + " ");
            Console.WriteLine();
        }
    }
}
JavaScript
// Function to check if two strings are anagrams
function isAnagram(a, b) {
    if (a.length !== b.length)
        return false;

    const s1 = a.split('').sort().join('');
    const s2 = b.split('').sort().join('');

    return s1 === s2;
}

function anagrams(arr) {
    const n = arr.length;
    const visited = new Array(n).fill(false);
    const res = [];

    for (let i = 0; i < n; i++) {
        if (visited[i])
            continue;

        const group = [arr[i]];
        visited[i] = true;

        for (let j = i + 1; j < n; j++) {
            if (!visited[j] && isAnagram(arr[i], arr[j])) {
                group.push(arr[j]);
                visited[j] = true;
            }
        }

        res.push(group);
    }

    return res;
}

// Driver code
const arr = ["act", "god", "cat", "dog", "tac"];

const res = anagrams(arr);

for (const group of res)
    console.log(group.join(" "));

Output
act cat tac 
god dog 


[Better Approach] Using sorted words as keys - O(n*k*log(k)) Time and O(n*k) Space

The idea is that if we sort two strings which are anagrams of each other, then the sorted strings will always be the same. So, we can maintain a hash map with the sorted strings as keys and the index of the anagram group in the result array as the value.

C++
#include <bits/stdc++.h>
using namespace std;

vector<vector<string>> anagrams(vector<string> &arr) {
    vector<vector<string>> res;
    unordered_map<string, int> mp;
    for (int i = 0; i < arr.size(); i++) {
        string s = arr[i];
      
        // Find the key by sorting the string
        sort(s.begin(), s.end());
      
        // If key is not present in the hash map, add
        // an empty group (vector) in the result and
        // store the index of the group in hash map
        if (mp.find(s) == mp.end()) {
            mp[s] = res.size();
            res.push_back({});
        }
      
        // Insert the string in its correct group
        res[mp[s]].push_back(arr[i]);
    }
    return res;
}

int main() {
    vector<string> arr = {"act", "god", "cat", "dog", "tac"};
    
    vector<vector<string>> res = anagrams(arr);
    for(int i = 0; i < res.size(); i++) {
    	for(int j = 0; j < res[i].size(); j++)
            cout << res[i][j] << " ";
        cout << "\n";
    }
    return 0;
}
Java
import java.util.*;

class GFG {
    static ArrayList<ArrayList<String>> anagrams(String[] arr) {
        ArrayList<ArrayList<String>> res = new ArrayList<>();
        HashMap<String, Integer> mp = new HashMap<>();
        
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            
            // Find the key by sorting the string
            char[] chars = s.toCharArray();
            Arrays.sort(chars);
            s = new String(chars);
            
            // If key is not present in the hash map, add
            // an empty group (ArrayList) in the result and
            // store the index of the group in hash map
            if (!mp.containsKey(s)) {
                mp.put(s, res.size());
                res.add(new ArrayList<>());
            }
            
            // Insert the string in its correct group
            res.get(mp.get(s)).add(arr[i]);
        }
        
        return res;
    }

    public static void main(String[] args) {
        String[] arr = {"act", "god", "cat", "dog", "tac"};
        
        ArrayList<ArrayList<String>> res = anagrams(arr);
        for (int i = 0; i < res.size(); i++) {
            for (int j = 0; j < res.get(i).size(); j++)
                System.out.print(res.get(i).get(j) + " ");
            System.out.println();
        }
    }
}
Python
from collections import defaultdict

def anagrams(arr):
    res = []
    mp = {}
    
    for i in range(len(arr)):
        s = arr[i]
        
        # Find the key by sorting the string
        s = ''.join(sorted(s))
        
        # If key is not present in the hash map, add
        # an empty group (list) in the result and
        # store the index of the group in hash map
        if s not in mp:
            mp[s] = len(res)
            res.append([])
        
        # Insert the string in its correct group
        res[mp[s]].append(arr[i])
    
    return res

if __name__ == "__main__":
    arr = ["act", "god", "cat", "dog", "tac"]
    
    res = anagrams(arr)
    for group in res:
        print(" ".join(group))
C#
using System;
using System.Collections.Generic;

class GFG {
    static List<List<string>> anagrams(string[] arr) {
        List<List<string>> res = new List<List<string>>();
        Dictionary<string, int> mp = new Dictionary<string, int>();

        for (int i = 0; i < arr.Length; i++) {
            string s = arr[i];

            // Find the key by sorting the string
            char[] charArray = s.ToCharArray();
            Array.Sort(charArray);
            s = new string(charArray);

            // If key is not present in the hash map, add
            // an empty group (list) in the result and
            // store the index of the group in hash map
            if (!mp.ContainsKey(s)) {
                mp[s] = res.Count;
                res.Add(new List<string>());
            }

            // Insert the string in its correct group
            res[mp[s]].Add(arr[i]);
        }

        return res;
    }

    static void Main(string[] args) {
        string[] arr = new string[] { "act", "god", "cat", "dog", "tac" };
        
        List<List<string>> res = anagrams(arr);
        for (int i = 0; i < res.Count; i++)
        {
            for (int j = 0; j < res[i].Count; j++)
                Console.Write(res[i][j] + " ");
            Console.WriteLine();
        }
    }
}
JavaScript
function anagrams(arr) {
    let res = [];
    let mp = new Map();

    for (let i = 0; i < arr.length; i++) {
        let s = arr[i];

        // Find the key by sorting the string
        s = s.split('').sort().join('');

        // If key is not present in the hash map, add
        // an empty group (array) in the result and
        // store the index of the group in hash map
        if (!mp.has(s)) {
            mp.set(s, res.length);
            res.push([]);
        }

        // Insert the string in its correct group
        res[mp.get(s)].push(arr[i]);
    }

    return res;
}

// Driver Code
let arr = ["act", "god", "cat", "dog", "tac"];

let res = anagrams(arr);
for (let i = 0; i < res.length; i++) {
    console.log(res[i].join(" "));
}

Output
act cat tac 
god dog 

[Expected Approach] Using Frequency as keys - O(n*k) Time and O(n*k) Space

Anagrams have the same frequency of every character. Use the character frequency of each string as a unique key to group all its anagrams together.

  • Generate a hash for each string using the frequency of all 26 lowercase characters.
  • Store the hash in a hash map, where each unique hash represents one anagram group.
  • If the hash is new, create a new group and store its index in the hash map.
  • Add the current string to its corresponding group.
  • Return all the groups.

Consider arr[] = ["act", "god", "cat", "dog", "tac"]

  • Process "act". Its hash corresponds to the character frequencies {a:1, c:1, t:1}. Create the first group containing ["act"].
  • Process "god". It has a different hash, so create the second group containing ["god"].
  • Process "cat". Its hash matches that of "act", so add it to the first group. The first group becomes ["act", "cat"].
  • Process "dog". Its hash matches that of "god", so add it to the second group. The second group becomes ["god", "dog"].
  • Process "tac". Its hash matches that of "act", so add it to the first group. The first group becomes ["act", "cat", "tac"].
C++
#include <bits/stdc++.h>
using namespace std;

// function to generate hash of word s
string getHash(string &s) {
    string hash;
	vector<int> freq(26, 0);
    
    // Count frequency of each character
    for(char ch: s)
        freq[ch - 'a'] += 1;
    
    // Append the frequency to construct the hash
    for(int i = 0; i < 26; i++) {
        hash.append(to_string(freq[i]));
    	hash.append("$");
    }
    
    return hash;
}

vector<vector<string>> anagrams(vector<string> &arr) {
    vector<vector<string>> res;
    unordered_map<string, int> mp;
    for (int i = 0; i < arr.size(); i++) {
        string key = getHash(arr[i]);
      
        // If key is not present in the hash map, add
        // an empty group (vector) in the result and
        // store the index of the group in hash map
        if (mp.find(key) == mp.end()) {
            mp[key] = res.size();
            res.push_back({});
        }
      
        // Insert the string in its correct group
        res[mp[key]].push_back(arr[i]);
    }
    return res;
}

int main() {
    vector<string> arr = {"act", "god", "cat", "dog", "tac"};
    
    vector<vector<string>> res = anagrams(arr);
    for(int i = 0; i < res.size(); i++) {
        for(int j = 0; j < res[i].size(); j++)
            cout << res[i][j] << " ";
        cout << "\n";
    }
    return 0;
}
Java
import java.util.*;

class GFG { 

    // Function to generate hash of word s
    static String getHash(String s) {
        StringBuilder hash = new StringBuilder();
        int[] freq = new int[26];
        
        // Count frequency of each character
        for (char ch : s.toCharArray()) {
            freq[ch - 'a']++;
        }

        // Append the frequency to construct the hash
        for (int i = 0; i < 26; i++) {
            hash.append(freq[i]);
            hash.append("$");
        }

        return hash.toString();
    }

    static ArrayList<ArrayList<String>> anagrams(String[] arr) {
        ArrayList<ArrayList<String>> res = new ArrayList<>();
        Map<String, Integer> mp = new HashMap<>();
        
        for (int i = 0; i < arr.length; i++) {
            String key = getHash(arr[i]);
            
            // If key is not present in the hash map, add
            // an empty group (List) in the result and
            // store the index of the group in hash map
            if (!mp.containsKey(key)) {
                mp.put(key, res.size());
                res.add(new ArrayList<>());
            }

            // Insert the string in its correct group
            res.get(mp.get(key)).add(arr[i]);
        }

        return res;
    }

    public static void main(String[] args) {
        String[] arr = {"act", "god", "cat", "dog", "tac"};
        
        ArrayList<ArrayList<String>> res = anagrams(arr);
        
        for (List<String> group : res) {
            for (String word : group) {
                System.out.print(word + " ");
            }
            System.out.println();
        }
    }
}
Python
def getHash(s):
    hashList = []
    freq = [0] * 26
    
    # Count frequency of each character
    for ch in s:
        freq[ord(ch) - ord('a')] += 1
    
    # Append the frequency to construct the hash
    for i in range(26):
        hashList.append(str(freq[i]))
        hashList.append("$")
    
    return ''.join(hashList)

def anagrams(arr):
    res = []
    mp = {}
    
    for i in range(len(arr)):
        key = getHash(arr[i])
        
        # If key is not present in the hash map, add
        # an empty group (list) in the result and
        # store the index of the group in hash map
        if key not in mp:
            mp[key] = len(res)
            res.append([])
        
        # Insert the string in its correct group
        res[mp[key]].append(arr[i])
    
    return res

if __name__ == "__main__":
    arr = ["act", "god", "cat", "dog", "tac"]
    
    res = anagrams(arr)
    for group in res:
        for word in group:
            print(word, end=" ")
        print()
C#
using System;
using System.Collections.Generic;
using System.Text;

class GFG {
    // Function to generate hash of word s
    static string GetHash(string s) {
        StringBuilder hash = new StringBuilder();
    	int[] freq = new int[26];

    	// Count frequency of each character
    	foreach (char ch in s) {
        	freq[ch - 'a'] += 1;
    	}

    	// Append the frequency to construct the hash
    	for (int i = 0; i < 26; i++) {
        	hash.Append(freq[i].ToString());
        	hash.Append("$");
    	}

    	return hash.ToString();
    }

    static List<List<string>> anagrams(string[] arr) {
        List<List<string>> res = new List<List<string>>();
        Dictionary<string, int> mp = new Dictionary<string, int>();

        for (int i = 0; i < arr.Length; i++) {
            string key = GetHash(arr[i]);

            // If key is not present in the hash map, add
            // an empty group (List) in the result and
            // store the index of the group in hash map
            if (!mp.ContainsKey(key)) {
                mp[key] = res.Count;
                res.Add(new List<string>());
            }

            // Insert the string in its correct group
            res[mp[key]].Add(arr[i]);
        }

        return res;
    }

    static void Main() {
        string[] arr = { "act", "god", "cat", "dog", "tac" };

        List<List<string>> res = anagrams(arr);
        foreach (var group in res) {
            foreach (var word in group) {
                Console.Write(word + " ");
            }
            Console.WriteLine();
        }
    }
}
JavaScript
function getHash(s) {
    let freq = Array(26).fill(0);
    
    // Count frequency of each character
    for (let i = 0; i < s.length; i++) {
        let ch = s[i];
        freq[ch.charCodeAt(0) - 'a'.charCodeAt(0)] += 1;
    }
    
    // Create hash string using join to avoid string concatenation in the loop
    let hashArray = [];
    for (let i = 0; i < 26; i++) {
        hashArray.push(freq[i].toString());
        hashArray.push('$');
    }
    
    return hashArray.join('');
}

function anagrams(arr) {
    let res = [];
    let mp = new Map();
    
    for (let i = 0; i < arr.length; i++) {
        let key = getHash(arr[i]);
        
        // If key is not present in the hash map, add
        // an empty group (array) in the result and
        // store the index of the group in hash map
        if (!mp.has(key)) {
            mp.set(key, res.length);
            res.push([]);
        }
        
        // Insert the string in its correct group
        res[mp.get(key)].push(arr[i]);
    }
    return res;
}

// Driver Code
let arr = ["act", "god", "cat", "dog", "tac"];
let res = anagrams(arr);

for (let i = 0; i < res.length; i++) {
    let temp = '';
    for (let j = 0; j < res[i].length; j++) {
        temp += res[i][j] + ' ';
    }
    console.log(temp);
}

Output
act cat tac 
god dog 

Time Complexity: O(n*k), where is the number of words and k is the maximum length of a word.
Auxiliary Space: O(n*k)

Comment