Skip to content

49 group anagrams#13

Open
MA-yo-TA wants to merge 5 commits into
mainfrom
49-Group-Anagrams
Open

49 group anagrams#13
MA-yo-TA wants to merge 5 commits into
mainfrom
49-Group-Anagrams

Conversation

@MA-yo-TA

Copy link
Copy Markdown
Owner

Comment thread 49-Group-Anagrams/note.md

## step1(まず通す)

「文字を入れ替えて同じになる」という同値関係に基づいて同値類に分割するという話。

@h-masder h-masder Jun 17, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

正確な説明ですが、同値関係や同値類あたりはソフトウェアエンジニアの世界では普段から使う言葉とは感じないので、避けてもいいかもしれません。

「並べ替えると同じになる文字列を同じグループにまとめる」でいいかと思います。

@MA-yo-TA MA-yo-TA Jun 18, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうですね、自分の思考過程をメモ書き程度に書いたつもりでしたが他の方も見るので言葉遣いは周りに合わせたほうが良さそうです。

↓のような説明だとだいぶマシでしょうか。
skypenguins/coding-practice#32 (comment)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

いいと思います。

効率の良さを議論するときは、それによって何が嬉しいのかも意識すると良いと思います。想像の域は出ませんが、例えば、前者の方法で実装されたプログラムが既に動いているとして、後者へ変更する価値があるのかを考えてみるとよいと思います。実行時間を見積もる意味も、そういった判断材料を得るところにあると私は思っています。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

例えば、前者の方法で実装されたプログラムが既に動いているとして、後者へ変更する価値があるのかを考えてみるとよいと思います。実行時間を見積もる意味も、そういった判断材料を得るところにあると私は思っています

まさにそうですね、困ってない(し、これからも困ることはなさそう)なら触らないというのは実務では多いですよね。

実践的なアドバイスありがとうございます!

class Solution:
def groupAnagrams(self, strs: list[str]) -> list[list[str]]:
sorted_to_originals: dict[str, list[str]] = {}
for string in strs:

@h-masder h-masder Jun 17, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stringは型名のように感じるので避けたいです。
(↑こちらstep2に言及されていました。失礼しました。)
wordなどはいかがでしょうか

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。word もありかなと思いつつ、"" みたいな自然言語の感覚で言うと word じゃない奴もいるよな、みたいな細かいところを気にしてました。

今考えてみると割り切って word は良い名前な気がしてます。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"" みたいな自然言語の感覚で言うと word じゃない奴もいるよな、みたいな細かいところを気にしてました。

おっしゃる通り、場合によってはword以外の変数名も考えたほうが良いかもしれないですね。

sorted_to_originals: dict[str, list[str]] = {}
for string in strs:
sorted_string = str(sorted(string))
if sorted_string in sorted_to_originals:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6~10行目はdefalutdictを使うこともできます。
利点は、行数が短くなる、「存在しないキーには空のリストを作り、そこへ要素を追加していく処理」が想像しやすい、あたりです。

from collections import defaultdict

class Solution:
    def groupAnagrams(self, strs: list[str]) -> list[list[str]]:
        sorted_to_originals = defaultdict(list)
        for string in strs:
            sorted_string = str(sorted(string))
            sorted_to_originals[sorted_string].append(string)

        return list(sorted_to_originals.values())

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。 defaultdict をあまり認識していなかったので調べておきます。

Comment thread 49-Group-Anagrams/note.md
- `frozenset` のように hashable な dict はないのかということが気になるが、調べたら 3.15 から `frozendict` が組み込み型に追加されるらしい。
- <https://docs.python.org/ja/3.15/library/stdtypes.html#frozendict>
- 現在の安定版の最新は 3.14 なのでまだ一般的に使える感じではなさそう

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

アルゴリズムの実行時間を見積もることをおすすめします。
Yuto729/leetcode#16 (comment)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。

今回の場合は配列長が最大 10 ^ 4 , 文字列一つ一つの長さが最大 100 なので、
(10 ^ 4 * 100 * log 100) / 10 ^ 7 ~ 0.6 s くらいという計算をして、実際と大分ずれているなという印象ですね、、(leetcode だと 20 ms くらいで終わっている)

(テストケースが最大の大きさのものがないとかかもしれないので最終的には実際に計らないとわからないのだろうと思いつつ、見積もりが雑とか計算間違ってるかもしれません。)

@h-masder h-masder Jun 18, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10^4 や 100 * log 100がどこからきているか書いておくと良いと思います
(前者がメモリアクセス、後者がsorted()ですね)
sorted()を使うのであれば、内部実装として、何が使われているか知っておくとよいと思います。以下のあたりを見る限りtimsortのようです。
https://github.com/python/cpython/blob/main/Objects/listsort.txt
https://github.com/python/cpython/blob/main/Objects/listobject.c#L3122

テストケースが最大の大きさのものがないとかかもしれないので最終的には実際に計らないとわからないのだろうと思いつつ

はい、テストケースでだいぶ変わると思います。ゆくゆくはleetcodeにたよらず、自分でテストケースを書く癖をつけていくとよいかと思います。(癖というより、自分でテストケースを書きたくなる気持ちを養うといったほうがいいかもしれないです)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10^4 や 100 * log 100がどこからきているか書いておくと良いと思います

省略しすぎました。サボらず伝わる書き方を心がけます。

自分でテストケースを書きたくなる気持ちを養う

ありがとうございます。まずは想定できるケースのバリエーションを増やす意識で取り組みます。

Comment thread 49-Group-Anagrams/note.md

## step2(整形&他の人のコードを読む)

`sorted_string` は `sorted_` とかでもいいかも。今回は基本 string の話しかしてなくて string であることは明らかなので。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数名と紛らわしくなるため、同じ(もしくはほとんど似た)名前を変数名に使うのは避けたほうが良いと思います。元の sorted_string の方が意図が分かりやすいと感じました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうですね、書いているうちにそう思うようになりました。
ありがとうございます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants