diff --git a/Python3/49. Group Anagrams.md b/Python3/49. Group Anagrams.md new file mode 100644 index 0000000..6efcf64 --- /dev/null +++ b/Python3/49. Group Anagrams.md @@ -0,0 +1,95 @@ +## Step 1. Initial Solution + +- 文字列をそれぞれソートして一致するものを同じグループに入れる + - 辞書型にしてソートされた文字列と結果のインデックスを紐づけておく +- 文字列に対してsortedを使うとどうなるのか + - sortされた文字列が返ってくる前提でやるとエラー + - リストが返ってきていそうなのでstr()で文字列化 + +```python +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + result: List[List[int]] = [] + sorted_str_idx: Dict[str, int] = {} + for str_i in strs: + sorted_str = str(sorted(str_i)) + if sorted_str not in sorted_str_idx: + sorted_str_idx[sorted_str] = len(result) + result.append([str_i]) + continue + idx = sorted_str_idx[sorted_str] + result[idx].append(str_i) + return result +``` + +### Complexity Analysis + +- 時間計算量:O(n * m log m) + - 文字列の数×文字列のソート + - 文字列化の実装の中身は詳しく分かっていない + - __str__メソッドの定義による + - print()で出力されるものと同じ +- 空間計算量:O(n) + - 文字列の数 + +## Step 2. Alternatives + +- Dictのvaluesに直接文字列を入れて、values()を出力する方法もある + - コードとしてもこちらの方が最小限で書けている + - ただ、この状態だとkeyが`"['a', 'e', 't']"` のようになってしまい少し違和感がある + +```python +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + sorted_to_group: Dict[str, List[str]] = defaultdict(list) + for anagram in strs: + sorted_to_group[str(sorted(anagram))].append(anagram) + return list(sorted_to_group.values()) +``` + +- str()を呼び出すよりも””.join()を使う方が良い + - strでは各要素のあとにカンマを入れる処理が必要なので遅い + - keyも`"aet"` のようになって分かりやすい + +```python +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + sorted_to_group: Dict[str, List[str]] = defaultdict(list) + for anagram in strs: + sorted_to_group["".join(sorted(anagram))].append(anagram) + return list(sorted_to_group.values()) +``` + +- あまり使う意味はないかもしれないが、tupleにするという手もあると思った + - keyは`["a","e","t"]` のようになる + +```python +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + sorted_to_group: Dict[Tuple[str], List[str]] = defaultdict(list) + for anagram in strs: + sorted_in_tuple: Tuple[str] = tuple(sorted(anagram)) + sorted_to_group[sorted_in_tuple].append(anagram) + return list(sorted_to_group.values()) + +``` + +- 異常な入力に関して、空リストが来たら空リストを返す + - 空文字列が来ていないのに空文字列を返すのもおかしいのでこれで良さそう +- tupleとfrozensetはimmutableだが、要素がhashableな場合だけhashableとのこと + - 脳死で辞書型のkeyに使えると思わないようにする + +## Step 3. Final Solution + +- 命名はこの辺りが分かりやすそうに感じた + +```python +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + grouped_anagrams: Dict[str, List[str]] = defaultdict(list) + for anagram in strs: + sorted_anagram = "".join(sorted(anagram)) + grouped_anagrams[sorted_anagram].append(anagram) + return list(grouped_anagrams.values()) + +```