Conversation
| return length + 1 | ||
| if next_word in generated_words: | ||
| continue | ||
| generated_words.add(next_word) |
|
|
||
| 先に1文字違いを調べておく方針。 | ||
| 1文字違いを調べるのに、time complexityがO(n^2 * m)かかり、 | ||
| これはMemory limit exceededとなった。 |
There was a problem hiding this comment.
この問題、結構制限が適当に決められているという印象があります。
通らなかったらよくない解答である、通ったらよい解答である、というようには見ないほうがいいです。
いくつか選択があり、偶然にもこの場合はこういう制限がかかっていたので、そのうちのいくつかが偶然にも動かないものがあった。
とはいえ、どういうものが動かないかが分かったあとに、回避策がいくつかでてくるようにしておく事自体は大切です。
| word, length = words_and_lengths.popleft() | ||
| for pattern in generate_pattern(word): | ||
| for next_word in pattern_to_words[pattern]: | ||
| if next_word == endWord: |
There was a problem hiding this comment.
後のステップで直っていますが、ここのネストが深すぎてちょっと読みづらさを感じました。
There was a problem hiding this comment.
for pattern in generate_pattern(word):
for next_word in pattern_to_words[pattern]:この二行圧縮すべきでしたね、ありがとうございます
| for i in range(len_word): | ||
| if word1[i] == word2[i]: | ||
| continue | ||
| num_of_diffs += 1 |
There was a problem hiding this comment.
ここで、num_of_diffが2以上だったらループを抜けると無駄な処理を減らせそうです
| generated_word = f"{word[:index]}{char}{word[index + 1:]}" | ||
| if generated_word not in word_set: | ||
| continue | ||
| yield generated_word |
There was a problem hiding this comment.
373-375 行目は、
if generated_word in word_set:
yield generated_wordのほうが簡潔ではありませんか?
There was a problem hiding this comment.
個人的には、そこまで簡潔さが変わっている印象はないです。
こうしている理由としては、https://discord.com/channels/1084280443945353267/1192728121644945439/1194203372115464272
これに書いてある気持ちに近いかもしれません。
ただリンク先の問題と異なり、この部分は、条件も、それが成立した時・しなかった時にする処理も1行で表せるので、いただいた提案でも簡潔だと思います。
| wordに対して、1文字違いをwordListから毎回探すやり方でTLE | ||
|
|
||
| find_words_diff_by_one()に時間がかかる。m = len(word), n = len(wordList)として、 | ||
| find_words_diff_by_one()のtime complexityがO(mn). |
There was a problem hiding this comment.
ladderLength() 全体の時間計算量も求めてみてください。そして、時間計算量を求めたあと、制約にあるデータサイズの上限を代入し、どれくらいの数字になるかを確かめてみてください。その数字が言語ごとの処理速度の違いを考慮したうえで、一定の数値以下に入っていれば、現実的な時間で処理が終わると思います。
今回の場合ですと O(m*n^2) とります。制約に 1 <= m <= 10、1 <= n <= 5000 とありますので、 m = 10、n = 5000 を代入します。すると 2.5 * 10^8 となります。 Python は比較的遅い言語で、 1 秒間に 100 万ステップくらいしか計算できません。2.5 * 10^8 / 10^6 = 250 となり、 250 秒くらいかかりそうということが分かります。これは制限時間を大きく超えそうです。
言語ごと速度の差は以下をご覧ください。
https://github.com/niklas-heer/speed-comparison
https://benchmarksgame-team.pages.debian.net/benchmarksgame/box-plot-summary-charts.html
上記の実行時間の概算方法は、 IPC やメモリのアクセスパターンや整数・浮動小数の計算速度の違い等、様々な要因で大きくぶれます。目安程度に考えることをお勧めいたします。
|
|
||
| 一番最後の、「visitedに追加される前に同じwordをnext_candidatesに加えている」によって | ||
| かなり遅くなっているみたいだった。BFSをするなら、最短経路以外の同じ地点に至るルートはできるだけ | ||
| 早く探索対象から外した方が実行時間が短くなるようだった。 |
There was a problem hiding this comment.
LeetCode の実行環境は実行時間の計測の精度が良くないようです。 LeetCode に表示される実行時間はあまり信用しないほうがよいと思います。
| generated_words = set([beginWord]) | ||
| word_set = set(wordList) | ||
| while words_and_lengths: | ||
| word, length = words_and_lengths.popleft() |
There was a problem hiding this comment.
lengthは文字の長さという印象を受けました。
stepとか
レーベンシュタイン距離というものがあるらしいのでdistanceなどはどうでしょうか。
https://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%BC%E3%83%99%E3%83%B3%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%A4%E3%83%B3%E8%B7%9D%E9%9B%A2
https://leetcode.com/problems/word-ladder/description/