Conversation
| distance = 0 | ||
| for i in range(len(str1)): | ||
| if str1[i] != str2[i]: | ||
| distance += 1 |
There was a problem hiding this comment.
distance が 2 になったところで return False すると、処理量が少し減ると思います。
| ```python | ||
| class Solution: | ||
| def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: | ||
| def is_adjacent_pair(str1, str2): |
There was a problem hiding this comment.
ありがとうございます。
せっかくなので、面接だったらどういう選択肢を視野に入れて面接官とディスカッションするか考えてみました。
- 異常な値として対応するパターン
- 例外を投げて処理を停止する。
- wordListに異なる値が含まれている時点で例外を投げる。
- 異常な値だけ無視して処理を続行する。
- “正しい長さ”も受け取るように修正する方法。
- データの内容から”正しい長さ”も決める方法。(多数決など)
- 例外を投げて処理を停止する。
- 正常な値として対応するパターン
- adjacentの定義をハミング距離からレーベンシュタイン距離に変更して対応する
P.S. レーベンシュタイン距離は、正式な用語がわからずググりました。また、ハミング距離は”ハフマン距離”と間違えて覚えていました。。。
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
There was a problem hiding this comment.
自分なら、問題としては長さが違うものが来てもOK。単にその単語が到達不能なだけで無視すれば良い。
is_adjacent_pairの入力として長さが違う物が来たら、Falseを返すかなという感じです。
There was a problem hiding this comment.
正常な値として対応するパターン
adjacentの定義をハミング距離からレーベンシュタイン距離に変更して対応する
これは問題全体の要件が変わっているじゃんという気持ちです。まあそのレイヤーでの話をしているなら、良いですが、odaさんの意図とは違う気がします。
| distance = 0 | ||
| for i in range(len(str1)): | ||
| if str1[i] != str2[i]: | ||
| distance += 1 |
| - 2回くらいなら許容な気がした。3回以上足し算があるなら、f-stringの方が読みやすそう | ||
|
|
||
| - > で、そのおまけの話として、 | ||
| hamming_distance(a, b) と hamming_distance(b, a) が同じ結果なのに別のキャッシュになるのを避けたい気持ちがあるので、@cache つけるのを補助関数にするなどを考えていました。 |
There was a problem hiding this comment.
これ、たとえば、大小関係を入れようとすると、大小関係の確認に文字列を比べてしまい、hamming 距離の計算と遜色がない時間かかるので、id 化するなどちょっと工夫が必要でしょう。
| - 前者は`O(len(wordList)*len(word))` | ||
| - 後者は`O(26*len(word))` | ||
| - https://github.com/TORUS0818/leetcode/pull/22/files#r1666932153 | ||
|
|
There was a problem hiding this comment.
https://discord.com/channels/1084280443945353267/1295357747545505833/1309222881330335816
変えるところを "*" に置き換えてルックアップという方法もありました。
| - 実装時間: 4分 | ||
| - wordListの要素数を`n`, wordの長さ`l`をとして、 | ||
| - 時間計算量: O(ln) | ||
| - generate_adjacentsでO(26 * l) |
There was a problem hiding this comment.
文字数だけループするのと、その中で新しい文字列を作成しているのでl^2ですかね?
なんかlだと視認性が悪いので他のアルファベットを使ってもらう方が良いかもです。
There was a problem hiding this comment.
ありがとうございます!
文字列作成気づいてませんでした。ご指摘の通りです。
lが見にくいも確かにです。ありがとうございます。
| - wordListの要素数を`n`, wordの長さ`l`をとして、 | ||
| - 時間計算量: O(ln) | ||
| - generate_adjacentsでO(26 * l) | ||
| - メインのループでO(l) |
| word_and_lengths = deque([(beginWord, 1)]) | ||
| while word_and_lengths: | ||
| word, length = word_and_lengths.popleft() | ||
| if word == endWord: |
There was a problem hiding this comment.
この判定をnext_wordに対して行うことで、dequeに入れる前に判定できるので少しだけ高速化可能です。
| if next_word in unused_words: | ||
| yield next_word | ||
|
|
||
| word_and_lengths = deque([(beginWord, 1)]) |
There was a problem hiding this comment.
好みの問題かもですが、words_and_lengthsと、両方とも複数形にするほうが違和感が少ないと思いました。
|
最初にハミング距離が1である単語同士を結んだ無向グラフを作り、グラフに対してBFSをするという方法もあると思います |
| ```python | ||
| class Solution: | ||
| def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: | ||
| def generate_adjacents(word): |
There was a problem hiding this comment.
個人的にはここは外側で定義して、generate_unused_adjacentsとして、引数はunused_wordsも含めます。(その方がインターフェーとしてわかりすい気がしました)
| return length | ||
| for next_word in generate_adjacents(word): | ||
| word_and_lengths.append((next_word, length + 1)) | ||
| unused_words.remove(next_word) |
There was a problem hiding this comment.
個人的にはused_wordsに突っ込んでく方が好きですが、好みの問題かもしれません
| if next_word not in unused_words: | ||
| continue |
https://leetcode.com/problems/word-ladder/description/