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