diff --git a/49-Group-Anagrams/note.md b/49-Group-Anagrams/note.md new file mode 100644 index 0000000..2ce11f4 --- /dev/null +++ b/49-Group-Anagrams/note.md @@ -0,0 +1,40 @@ +# 49. Group Anagrams + + + +## step1(まず通す) + +「文字を入れ替えて同じになる」という同値関係に基づいて同値類に分割するという話。 +ただし、毎回二つの文字列が同値関係を満たすか?とチェックするのは大変なので、一つの文字列を見た時に「それがどの同値類に属するか?」を判定できると嬉しい。 + +そのためには、それぞれの同値類に「名前」をつけたい + +- 文字列じゃなくても、Counter.count() (に相当する操作)をした結果とかでもいいが、実用上は hashable であってほしい +- 代表元の取り方にルールを設けてそれをその同値類の「名前」にすると文字列で名前がついて良い + - 例えばソートする + +制約上、各文字列の長さは 100 以下と短いのでソートすれば良さそう + +カウントする方が線形時間で時間計算量のオーダーとしては小さくなるが、 + +- アルファベット小文字は 26 個しかないので長さ26のタプルを使うこともできるが、コードのわかりやすさが犠牲になりそう +- `frozenset` のように hashable な dict はないのかということが気になるが、調べたら 3.15 から `frozendict` が組み込み型に追加されるらしい。 + - + - 現在の安定版の最新は 3.14 なのでまだ一般的に使える感じではなさそう + +## step2(整形&他の人のコードを読む) + +`sorted_string` は `sorted_` とかでもいいかも。今回は基本 string の話しかしてなくて string であることは明らかなので。 + +あとは他の人の書き方を見る。 + +- + - ちゃんと把握してなかったが、str だけじゃなくて string も予約語(に近い、モジュールがある)らしい + - そもそも他言語でも string は予約語なことが多いと思うので避けた方がいい + - スコープも短いし `s` くらいでもいいかも、というコメントもあった + - counter タプルに詰める時、文字コードを使う発想はなかった +- + - 文字ごとの出現数を数える場合は、英小文字じゃなかったらスキップしとかないとおかしくなる + - ord とか all とか、知らない組み込み関数がいろいろある + +## step3(10分以内にさっとかける * 3回) diff --git a/49-Group-Anagrams/step1.py b/49-Group-Anagrams/step1.py new file mode 100644 index 0000000..b3cc10a --- /dev/null +++ b/49-Group-Anagrams/step1.py @@ -0,0 +1,11 @@ +class Solution: + def groupAnagrams(self, strs: list[str]) -> list[list[str]]: + sorted_to_originals: dict[str, list[str]] = {} + for string in strs: + sorted_string = str(sorted(string)) + if sorted_string in sorted_to_originals: + sorted_to_originals[sorted_string].append(string) + else: + sorted_to_originals[sorted_string] = [string] + + return list(sorted_to_originals.values()) diff --git a/49-Group-Anagrams/step2.py b/49-Group-Anagrams/step2.py new file mode 100644 index 0000000..f0b430d --- /dev/null +++ b/49-Group-Anagrams/step2.py @@ -0,0 +1,11 @@ +class Solution: + def groupAnagrams(self, strs: list[str]) -> list[list[str]]: + grouped_anagrams: dict[str, list[str]] = {} + for s in strs: + sorted_s = str(sorted(s)) + if sorted_s in grouped_anagrams: + grouped_anagrams[sorted_s].append(s) + else: + grouped_anagrams[sorted_s] = [s] + + return list(grouped_anagrams.values()) diff --git a/49-Group-Anagrams/step3.py b/49-Group-Anagrams/step3.py new file mode 100644 index 0000000..d55adfa --- /dev/null +++ b/49-Group-Anagrams/step3.py @@ -0,0 +1,10 @@ +class Solution: + def groupAnagrams(self, strs: list[str]) -> list[list[str]]: + grouped_anagrams: dict[str, list[str]] = {} + for s in strs: + sorted_s = str(sorted(s)) + if sorted_s in grouped_anagrams: + grouped_anagrams[sorted_s].append(s) + else: + grouped_anagrams[sorted_s] = [s] + return list(grouped_anagrams.values())