Algorithm/LeetCode
[LeetCode] 49. Group Anagrams
Jaime.Lee
2023. 7. 10. 03:37
Problem
Given an array of strings strs, group the anagrams together. You can return the answer in any order.
An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
Example 1:
Input: strs = ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
Example 2:
Input: strs = [""]
Output: [[""]]
Example 3:
Input: strs = ["a"]
Output: [["a"]]
Constraints:
- 1 <= strs.length <= 10^4
- 0 <= strs[i].length <= 100
- strs[i] consists of lowercase English letters.
Solution
아나그램은 문자의 순서를 바꿔서 다른 단어를 만들 수 있는 단어를 말합니다. 예를 들어, "eat", "tea", "ate"는 서로 아나그램입니다.
문자열 배열이 주어졌을 때 아나그램 그룹을 반환하는 문제입니다.
package io.lcalmsky.leetcode.group_anagrams;
import java.util.*;
public class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
char[] array = new char[26];
char[] charArray = str.toCharArray();
for (char c : charArray) {
array[c - 'a']++;
}
String newStr = new String(array);
if (!map.containsKey(newStr)) {
map.put(newStr, new ArrayList<>());
}
map.get(newStr).add(str);
}
return new ArrayList<>(map.values());
}
}
해당 코드는 다음과 같은 방식으로 아나그램 그룹을 찾습니다:
- Map<String, List>인 map을 생성합니다. 이 맵은 아나그램을 키로 가지고 해당 아나그램에 속하는 단어들의 리스트를 값으로 가지게 됩니다.
- strs 배열을 순회하면서 각 문자열을 처리합니다.
- 문자열을 구성하는 문자들을 세는 배열 array를 생성합니다. 이 배열의 인덱스는 알파벳 소문자의 아스키 코드 값에서 'a'의 아스키 코드 값을 뺀 결과입니다. 각 문자의 등장 횟수를 해당 인덱스의 값으로 기록합니다.
- array를 문자열로 변환하여 newStr에 저장합니다.
- map에서 newStr을 키로 가지는 리스트를 찾습니다. 만약 해당 키가 존재하지 않는다면, 새로운 ArrayList를 생성하여 해당 키로 맵에 추가합니다.
- map에서 newStr을 키로 가지는 리스트를 가져온 후, 해당 리스트에 현재 문자열을 추가합니다.
- map의 모든 값들을 담고 있는 리스트를 생성하여 반환합니다.
이렇게 함으로써 groupAnagrams() 메서드는 주어진 문자열 배열에서 아나그램 그룹을 찾아서 그룹별로 리스트를 반환합니다.
Test
package io.lcalmsky.leetcode.group_anagrams;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertTrue;
class SolutionTest {
@Test
void testAll() {
assertAll(
() -> test(new String[]{"eat", "tea", "tan", "ate", "nat", "bat"}, List.of(List.of("bat"), List.of("nat", "tan"), List.of("ate", "eat", "tea"))),
() -> test(new String[]{""}, List.of(List.of(""))),
() -> test(new String[]{"a"}, List.of(List.of("a")))
);
}
private void test(String[] strs, List<List<String>> expected) {
// when
Solution solution = new Solution();
List<List<String>> actual = solution.groupAnagrams(strs);
// then
assertTrue(actual.stream().flatMap(List::stream).collect(Collectors.toList())
.containsAll(expected.stream().flatMap(List::stream).collect(Collectors.toList())));
}
}