-
Notifications
You must be signed in to change notification settings - Fork 0
Create 127WordLadder.md #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| # 進め方 | ||
|
|
||
| Step1 : 問題を解く。 | ||
|
|
||
| Step2 : 他の人のPRを参照し、コメントする。 | ||
|
|
||
| Step3 : 3回続けてエラーが出ないように書く。ドキュメントを参照する。 | ||
|
|
||
| # 実践 | ||
|
|
||
| ## Step1 | ||
|
|
||
| ### 思考ログ | ||
|
|
||
| 動きません。 | ||
|
|
||
| けっこう時間を費やしてしまったので、次回以降は解法がわからなければ解答をすぐ見る | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: | ||
| # まず入出力を合わせる | ||
| num_c = len(beginWord) | ||
|
|
||
| def is_one_diff(x, y): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. こちらでも問題なさそうですがis_adjacentとか他の候補もありそうです! |
||
| diff_count = 0 | ||
| for i in range(num_c): | ||
| if x[i] == y[i]: | ||
| continue | ||
| diff_count += 1 | ||
| if diff_count > 1: | ||
| return False | ||
| return diff_count == 1 | ||
|
|
||
| def calculate_min_length(target, used=set()): | ||
| if is_one_diff(target, endWord): | ||
| return 1 | ||
| word_to_min = {} | ||
| for i, word in enumerate(wordList): | ||
| if word in used: | ||
| continue | ||
| if not is_one_diff(target, word): | ||
| continue | ||
| used.add(word) | ||
| length = calculate_min_length(word, used) + 1 | ||
| if word not in word_to_min: | ||
| word_to_min[word] = length | ||
| else: | ||
| word_to_min[word] = min(word_to_min[word], length) | ||
|
|
||
| return min(word_to_min.values()) | ||
|
|
||
| return calculate_min_length(beginWord) | ||
|
|
||
| ``` | ||
|
|
||
| 最初スタックで書いてしまった。bfsが分かった気がする | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def ladderLength(self, begin_word: str, end_word: str, word_list: List[str]) -> int: | ||
| # 計算量は文字数×単語数の階乗 | ||
| # 多すぎるきがする | ||
| num_c = len(begin_word) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これすると word_list の中に長さが短い単語があると例外を投げそうですね。 |
||
|
|
||
| def is_one_diff(x, y): | ||
| diff_count = 0 | ||
| for i in range(num_c): | ||
| if x[i] == y[i]: | ||
| continue | ||
| diff_count += 1 | ||
| if diff_count > 1: | ||
| return False | ||
| return diff_count == 1 | ||
|
|
||
| used = set() | ||
| used.add(begin_word) | ||
| queue = deque([(1, begin_word)]) | ||
|
|
||
|
|
||
| while queue: | ||
| distance, base = queue.popleft() | ||
|
|
||
| for word in word_list: | ||
| if word in used: | ||
| continue | ||
| if not is_one_diff(base, word): | ||
| continue | ||
| if word == end_word: | ||
| return distance + 1 | ||
| used.add(word) | ||
| queue.append((distance + 1, word)) | ||
|
|
||
| return 0 | ||
|
|
||
| ``` | ||
|
|
||
| ## Step2 | ||
|
|
||
| ### 同じ問題を解いた人のプルリクを見る | ||
|
|
||
| https://github.com/SuperHotDogCat/coding-interview/pull/45/files | ||
|
|
||
| - 時間計算量を考える | ||
| - https://github.com/SuperHotDogCat/coding-interview/pull/45/files#r1980741221 | ||
|
|
||
| https://github.com/tshimosake/arai60/pull/11 | ||
|
|
||
| - string、文字コードについて | ||
| - https://docs.python.org/ja/3.13/library/string.html | ||
| - https://github.com/t0hsumi/leetcode/pull/12#discussion_r1886759238 | ||
|
|
||
| https://github.com/t0hsumi/leetcode/pull/20 | ||
|
|
||
| - 見積もり、このくらい精度で見積もりたい | ||
| - https://github.com/t0hsumi/leetcode/pull/20/files#r1944383585 | ||
| - 入出力に引っ張られないようにする | ||
| - https://github.com/t0hsumi/leetcode/pull/20/files#r1938166243 | ||
| - ジェネレーター式 | ||
| - 最大でword_listの分だけメモリを減らせる | ||
| - 今回はそこまで気にしなくてもよいと思っている。set(word_list)を使うので、メモリの消費量は半分程度くらいにしかならない。 | ||
| - https://docs.python.org/ja/3.11/reference/expressions.html#generator-expressions | ||
|
|
||
| https://github.com/olsen-blue/Arai60/pull/20 | ||
|
|
||
| - 分かりやすい | ||
| - wordListを消していけばよいのか | ||
|
|
||
| ### 書き直す | ||
|
|
||
| 関数に詰め込みすぎている感じがある | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: | ||
| num_word = len(beginWord) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. num_word ですと、単語の数という意味に感じます。 word_length のほうが直感的だと思います。 |
||
| word_queue = deque([(beginWord, 1)]) | ||
| word_set = set(wordList) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 自分は変数名には型を表す単語は含めないことが多いのです。ただ、今回は wordList が list 型で、それに対して word_set と定義しているため、悩ましいところです。 |
||
|
|
||
| def search_end_word(word: str, step: int) -> Optional[int]: | ||
| for i in range(num_word): | ||
| for c in string.ascii_lowercase: | ||
| target = f'{word[:i]}{c}{word[i+1:]}' | ||
| if target not in word_set: | ||
| continue | ||
| if target == endWord: | ||
| return step + 1 | ||
| word_queue.append((target, step + 1)) | ||
| word_set.remove(target) | ||
| return None | ||
|
|
||
| while word_queue: | ||
| word, step = word_queue.popleft() | ||
| result = search_end_word(word, step) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. search_end_word() の中で word_queue に要素が追加されるという流れが読み取りづらいように感じました。この程度の分量であれば、インラインで書いてしまってもよいと思います。 |
||
| if result is not None: | ||
| return result | ||
|
|
||
| return 0 | ||
| ``` | ||
|
|
||
| ## Step3 | ||
|
|
||
| ### 3回連続で再現できるようになる | ||
|
|
||
| 13分 | ||
|
|
||
| 18分 wordsとwordを書き間違えた。スコープが長いときは使わないほうが良いかも | ||
|
|
||
| 7分 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: | ||
| usable = set(wordList) | ||
|
|
||
| def get_next_words(word): | ||
| next_words = [] | ||
| for i in range(len(word)): | ||
| for c in string.ascii_lowercase: | ||
| candidate = f'{word[:i]}{c}{word[i+1:]}' | ||
| if candidate not in usable: | ||
| continue | ||
| next_words.append(candidate) | ||
| usable.remove(candidate) | ||
| return next_words | ||
|
|
||
| queue = deque([(beginWord, 1)]) | ||
| while queue: | ||
| word, step = queue.popleft() | ||
| next_words = get_next_words(word) | ||
| next_step = step + 1 | ||
| for target in next_words: | ||
| if target == endWord: | ||
| return next_step | ||
| queue.append((target, next_step)) | ||
|
Comment on lines
+187
to
+195
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 好みですが、get_next_words()は階層的(あるwordに対して、次の遷移可能な語を全て出している)な一方で、queueの方はiterativeに出し入れしていることが違和感に感じました。 words = [beginWord]
num_transformations = 1
while words:
next_words = []
for word in words:
if word == endWord:
return num_transformations
next_words.extend(get_next_words(word))
words = next_words
num_transformations += 1There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. その視点はありませんでした。ありがとうございます。 |
||
| return 0 | ||
|
|
||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
発想の仕方はありますが、とはいえ、さっさと答えを見ていいと思います。
5分考えて手が止まったら、調べるくらいがいいように思っています。
だいたいコメント集からたどれます。
https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0