49 group anagrams#13
Conversation
|
|
||
| ## step1(まず通す) | ||
|
|
||
| 「文字を入れ替えて同じになる」という同値関係に基づいて同値類に分割するという話。 |
There was a problem hiding this comment.
正確な説明ですが、同値関係や同値類あたりはソフトウェアエンジニアの世界では普段から使う言葉とは感じないので、避けてもいいかもしれません。
「並べ替えると同じになる文字列を同じグループにまとめる」でいいかと思います。
There was a problem hiding this comment.
そうですね、自分の思考過程をメモ書き程度に書いたつもりでしたが他の方も見るので言葉遣いは周りに合わせたほうが良さそうです。
↓のような説明だとだいぶマシでしょうか。
skypenguins/coding-practice#32 (comment)
There was a problem hiding this comment.
いいと思います。
効率の良さを議論するときは、それによって何が嬉しいのかも意識すると良いと思います。想像の域は出ませんが、例えば、前者の方法で実装されたプログラムが既に動いているとして、後者へ変更する価値があるのかを考えてみるとよいと思います。実行時間を見積もる意味も、そういった判断材料を得るところにあると私は思っています。
There was a problem hiding this comment.
例えば、前者の方法で実装されたプログラムが既に動いているとして、後者へ変更する価値があるのかを考えてみるとよいと思います。実行時間を見積もる意味も、そういった判断材料を得るところにあると私は思っています
まさにそうですね、困ってない(し、これからも困ることはなさそう)なら触らないというのは実務では多いですよね。
実践的なアドバイスありがとうございます!
| class Solution: | ||
| def groupAnagrams(self, strs: list[str]) -> list[list[str]]: | ||
| sorted_to_originals: dict[str, list[str]] = {} | ||
| for string in strs: |
There was a problem hiding this comment.
stringは型名のように感じるので避けたいです。
(↑こちらstep2に言及されていました。失礼しました。)
wordなどはいかがでしょうか
There was a problem hiding this comment.
ありがとうございます。word もありかなと思いつつ、"" みたいな自然言語の感覚で言うと word じゃない奴もいるよな、みたいな細かいところを気にしてました。
今考えてみると割り切って word は良い名前な気がしてます。
There was a problem hiding this comment.
"" みたいな自然言語の感覚で言うと 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: |
There was a problem hiding this comment.
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())There was a problem hiding this comment.
ありがとうございます。 defaultdict をあまり認識していなかったので調べておきます。
| - `frozenset` のように hashable な dict はないのかということが気になるが、調べたら 3.15 から `frozendict` が組み込み型に追加されるらしい。 | ||
| - <https://docs.python.org/ja/3.15/library/stdtypes.html#frozendict> | ||
| - 現在の安定版の最新は 3.14 なのでまだ一般的に使える感じではなさそう | ||
|
|
There was a problem hiding this comment.
アルゴリズムの実行時間を見積もることをおすすめします。
Yuto729/leetcode#16 (comment)
There was a problem hiding this comment.
ありがとうございます。
今回の場合は配列長が最大 10 ^ 4 , 文字列一つ一つの長さが最大 100 なので、
(10 ^ 4 * 100 * log 100) / 10 ^ 7 ~ 0.6 s くらいという計算をして、実際と大分ずれているなという印象ですね、、(leetcode だと 20 ms くらいで終わっている)
(テストケースが最大の大きさのものがないとかかもしれないので最終的には実際に計らないとわからないのだろうと思いつつ、見積もりが雑とか計算間違ってるかもしれません。)
There was a problem hiding this comment.
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にたよらず、自分でテストケースを書く癖をつけていくとよいかと思います。(癖というより、自分でテストケースを書きたくなる気持ちを養うといったほうがいいかもしれないです)
There was a problem hiding this comment.
10^4 や 100 * log 100がどこからきているか書いておくと良いと思います
省略しすぎました。サボらず伝わる書き方を心がけます。
自分でテストケースを書きたくなる気持ちを養う
ありがとうございます。まずは想定できるケースのバリエーションを増やす意識で取り組みます。
|
|
||
| ## step2(整形&他の人のコードを読む) | ||
|
|
||
| `sorted_string` は `sorted_` とかでもいいかも。今回は基本 string の話しかしてなくて string であることは明らかなので。 |
There was a problem hiding this comment.
関数名と紛らわしくなるため、同じ(もしくはほとんど似た)名前を変数名に使うのは避けたほうが良いと思います。元の sorted_string の方が意図が分かりやすいと感じました。
There was a problem hiding this comment.
そうですね、書いているうちにそう思うようになりました。
ありがとうございます。
この問題:https://leetcode.com/problems/group-anagrams/
次の問題:https://leetcode.com/problems/intersection-of-two-arrays/