Skip to content

127. Word Ladder#22

Open
fhiyo wants to merge 2 commits intomainfrom
127_word-ladder
Open

127. Word Ladder#22
fhiyo wants to merge 2 commits intomainfrom
127_word-ladder

Conversation

@fhiyo
Copy link
Copy Markdown
Owner

@fhiyo fhiyo commented Jun 15, 2024

num_words += 1
return 0

def _getNextWords(self, word: str, words: set[str]) -> Generator[str, None, None]:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

自分で書く関数名は、 3rd のように lower snake で統一してよいと思います。

def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
words = set(wordList)
num_words = 1
word_queue = deque([beginWord])
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

変数名の queue は型と情報が重複しているため、不要だと思います。 3rd のように words next_words のほうが良いと思います。ただ、この命名も人によっては違和感を感じるかもしれません。自分は幅優先探索を書くときは、 frontier explorered という単語を使いますが、少数派かもしれません。

また、幅優先探索を書くとき、この解答のようにキューを 2 つ用意する実装方法も良いと思います。一方、キューは 1 つだけ用意し、先頭から取り出す、末尾に入れるという形で実装することもあります。その場合、キューまたは別の領域に、何回辿ったかを表す整数を保存しておく必要があります。個人的には最近はこちらの書き方で書くことが多いです。

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.

自分は幅優先探索を書くときは、 frontier explorered という単語を使いますが、少数派かもしれません。

ダイクストラのfrontierのイメージですかね。_queueとsuffixを付けたのは他の変数でwordsという名前を使ってたので付けました。今回みたいな仕方ないので_queue付ける、みたいなときの別の選択肢として良いかもと思いました。

Comment on lines +32 to +33
for next_word in self._getNextWords(word, words):
next_word_queue.append(next_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.

next_word_queue.extend(self._getNextWords(word, words)) でよいと思います。

return 0

def _getNextWords(self, word: str, words: set[str]) -> Generator[str, None, None]:
for i, original_ch in enumerate(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.

自分が書く場合は、 words でループを回し、 word と 1 文字違いかどうかを調べると思います。。ただし、 1 <= wordList.length <= 5000 のため Python だと TLE になると思います。自分の場合は C++ を使います。

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.

問題の制約が 1 <= beginWord.length <= 10 なので、最初は O(len(wordList)^2) でもいいがそこから制約が厳しくなったときに高速化する方法はあるか、という話に繋がりそうな気はしますね。言語を変えて定数倍高速化するという方法は一つではあるでしょうが、例えばここだけC++で他多言語みたいな状態にすると保守性は下がりそうな気はします

continue
new_word = f'{word[:i]}{ch}{word[i + 1:]}'
if new_word in words:
words.remove(new_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.

入力データを変更している点に違和感を感じます。自分だったら、使用済みの単語を表す set() を作ると思います。

class Solution:
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
wordList.append(beginWord)
adjacentList = self._makeAdjacentList(wordList)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

自分で定義する変数名は、 3rd のように lower snake でよいと思います。



```py
class Solution:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

自分はこちらの解法を先に思い付きました。ただ、 Python で O(len(wordList) ** 2) が通ると思えません。自分だったらこちらの解法を C++ で書くと思います。

endWordがwordListになかったら0を返すようにしている。高速化したくなったらやるかも、くらいの感覚。

i番目の文字が任意となることを表すパターンをkeyとして、そのパターンに合致するwordの集合をvalueとする辞書を作る。
ちょっとネストが深い。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

https://discord.com/channels/1084280443945353267/1200089668901937312/1216123084889788486

https://cs.stackexchange.com/questions/93467/data-structure-or-algorithm-for-quickly-finding-differences-between-strings
頭から半分または尻尾から半分が一致しているはずなので、それでバケットを作ってバケット内でのみ比較すればいいというやりかたもありますね。(編集距離が1であるかの確認に、頭から何文字一致していて、尻尾から何文字一致しているかを足してやればいいという方法をどっかで使ったことあります。)

nextWordIndexes = deque()
while wordIndexes:
wordIndex = wordIndexes.popleft()
used[wordIndex] = True
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

訪れたことを記録するタイミングは、nextWordIndexes.append(nextWordIndex) と同時にする方が好みです。

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.

4 participants