Group Anagrams

Problem

Each input line is one word. Group the words that are anagrams of each other. Inside a group sort the words alphabetically and join them with a space. Print one group per line, and sort the groups by their first word.

Constraints

  • 1 <= words <= 10^4
  • lowercase letters only

Examples

Input

eat
tea
tan
ate
nat
bat

Output

ate eat tea
bat
nat tan

Solutions

Best approachTime O(n * k log k)Space O(n * k)

The sorted letters are the same for all anagrams, so they work as a map key. Maps do not guarantee an order in every language, so the output order is fixed by sorting.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Group anagrams.
 * Input   : One word per line.
 * Output  : One group per line.
 * Approach: Sorted letters as key.
 * Time    : O(n * k log k)
 * Space   : O(n * k)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        // Step 1: Two words are anagrams if their sorted letters are equal. We use the sorted letters as the key of a map.
        java.util.Map<String, java.util.List<String>> groups = new java.util.HashMap<>();
        for (String word : lines) {
            char[] letters = word.toCharArray();
            java.util.Arrays.sort(letters);
            groups.computeIfAbsent(new String(letters), key -> new java.util.ArrayList<>()).add(word);
        }

        // Step 2: Sort the words inside each group and join them.
        java.util.List<String> output = new java.util.ArrayList<>();
        for (java.util.List<String> group : groups.values()) {
            java.util.Collections.sort(group);
            output.add(String.join(" ", group));
        }

        // Step 3: Sort the groups. The first word decides the order, so we compare up to the first space.
        output.sort((x, y) -> x.split(" ")[0].compareTo(y.split(" ")[0]));
        return output.toArray(new String[0]);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(String.join("\n", solve(lines)));
    }
}
Hints (1)
  1. What key is the same for every anagram of a word?