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
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.
/*
* 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)
- What key is the same for every anagram of a word?