-
Notifications
You must be signed in to change notification settings - Fork 0
Word Search #105
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
Open
tom4649
wants to merge
3
commits into
main
Choose a base branch
from
79.Word-Search
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Word Search #105
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # 79. Word Search | ||
|
|
||
| ## step1 | ||
|
|
||
| 全ての位置から探索する解法が思いつく。最悪だと | ||
| (m * n * 3^L) / 10^7 <= (36*3^15)/ 10^7 = 50 | ||
| かかるが大丈夫だろうか。とりあえず実装してみる。 | ||
|
|
||
| 15mぐらいでかけてテストもクリアした。間違えた点:初期開始点のseenをTrueにし忘れた。 | ||
|
|
||
| > Follow up: Could you use search pruning to make your solution faster with a larger board? | ||
|
|
||
| これを考えたいが案は思いつかず答えを見る。 | ||
|
|
||
| ## step2 | ||
|
|
||
| ### 他の人のコード | ||
|
|
||
| https://github.com/huyfififi/coding-challenges/pull/61 | ||
|
|
||
| > というものが提示されていた。これを入れるだけでLeetCode上の実行時間ランキングでの順位が大きく上がった。 | ||
|
|
||
| > また、wordをひっくり返して word search を行っても同じ結果が得られるので、wordの先頭と末尾の文字のboard上での数を比べて、末尾の文字の個数の方が小さかったら word をひっくり返して search した方がDFSを始める回数が少なく済む。 | ||
|
|
||
| この通りにやったら確かにBeat 100msとなった | ||
|
|
||
| 片方しか行わないと遅くなるのでどちらも効果がある。 | ||
|
|
||
| > なるほど、確かに言われてみれば納得感はあるが、面接中にスラスラと思いつけるかは自信がない。word をひっくり返して探索しても同じ、というのは問題文を読んでいて気づけた方がいいだろうな。 | ||
|
|
||
| 自分はどちらも思いつかないのでまだまだなのだと思う。 | ||
|
|
||
|
|
||
| https://github.com/potrue/leetcode/pull/74 | ||
|
|
||
| 早期リターン | ||
|
|
||
|
|
||
| https://github.com/thonda28/leetcode/pull/14 | ||
|
|
||
| 再帰 -> ループを自分も書いておく | ||
|
|
||
| 次に試す方向の index を持たせておくのか。これは人のコードを見ないと書けなかったかもしれない。 | ||
|
|
||
| 再帰をスタックに置き換える場合、フレーウの状態を明示的に持つ必要がある。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import itertools | ||
|
|
||
|
|
||
| class Solution: | ||
| def exist(self, board: list[list[str]], word: str) -> bool: | ||
| if not board or not board[0]: | ||
| raise ValueError("invalid board") | ||
|
|
||
| num_row = len(board) | ||
| num_col = len(board[0]) | ||
|
|
||
| def traverse(row: int, col: int, i: int, seen: list[list][bool]) -> bool: | ||
| if not word[i] == board[row][col]: | ||
| return False | ||
| if i == len(word) - 1: | ||
| return True | ||
| for row_next, col_next in ( | ||
| (row + 1, col), | ||
| (row - 1, col), | ||
| (row, col + 1), | ||
| (row, col - 1), | ||
| ): | ||
| if ( | ||
| 0 <= row_next < num_row | ||
| and 0 <= col_next < num_col | ||
| and not seen[row_next][col_next] | ||
| ): | ||
| seen[row_next][col_next] = True | ||
| if traverse(row_next, col_next, i + 1, seen): | ||
| return True | ||
| seen[row_next][col_next] = False | ||
|
|
||
| return False | ||
|
|
||
| for row, col in itertools.product(range(num_row), range(num_col)): | ||
| seen = [[False] * num_col for _ in range(num_row)] | ||
| seen[row][col] = True | ||
| if traverse(row, col, 0, seen): | ||
| return True | ||
|
|
||
| return False | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import itertools | ||
|
|
||
|
|
||
| class Solution: | ||
| def exist(self, board: list[list[str]], word: str) -> bool: | ||
| if not board or not board[0]: | ||
| raise ValueError("invalid board") | ||
|
|
||
| num_row = len(board) | ||
| num_col = len(board[0]) | ||
|
|
||
| def traverse(row: int, col: int, i: int, seen: list[list][bool]) -> bool: | ||
| if not word[i] == board[row][col]: | ||
| return False | ||
| if i == len(word) - 1: | ||
| return True | ||
| for row_next, col_next in ( | ||
| (row + 1, col), | ||
| (row - 1, col), | ||
| (row, col + 1), | ||
| (row, col - 1), | ||
| ): | ||
| # fmt: off | ||
| if ( | ||
| 0 <= row_next < num_row and | ||
| 0 <= col_next < num_col and | ||
| not seen[row_next][col_next] | ||
| ): | ||
| # fmt: on | ||
| seen[row_next][col_next] = True | ||
| if traverse(row_next, col_next, i + 1, seen): | ||
| return True | ||
| seen[row_next][col_next] = False | ||
|
|
||
| return False | ||
|
|
||
| for row, col in itertools.product(range(num_row), range(num_col)): | ||
| seen = [[False] * num_col for _ in range(num_row)] | ||
| seen[row][col] = True | ||
| if traverse(row, col, 0, seen): | ||
| return True | ||
|
|
||
| return False |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import itertools | ||
| import collections | ||
|
|
||
|
|
||
| class Solution: | ||
| def exist(self, board: list[list[str]], word: str) -> bool: | ||
| if not board or not board[0]: | ||
| raise ValueError("invalid board") | ||
|
|
||
| num_row = len(board) | ||
| num_col = len(board[0]) | ||
|
|
||
| board_char_to_count = collections.Counter(itertools.chain.from_iterable(board)) | ||
| word_char_to_count = collections.Counter(word) | ||
|
|
||
| for ch in word_char_to_count: | ||
| if board_char_to_count[ch] < word_char_to_count[ch]: | ||
| return False | ||
|
|
||
| if board_char_to_count[word[-1]] < board_char_to_count[word[0]]: | ||
| word = word[::-1] | ||
|
|
||
| directions = ( | ||
| (1, 0), | ||
| (-1, 0), | ||
| (0, 1), | ||
| (0, -1), | ||
| ) | ||
|
|
||
| def start_from(row_start: int, col_start: int) -> bool: | ||
| if board[row_start][col_start] != word[0]: | ||
| return False | ||
|
|
||
| seen = [[False] * num_col for _ in range(num_row)] | ||
| seen[row_start][col_start] = True | ||
| stack = [(row_start, col_start, 0, 0)] | ||
|
|
||
| while stack: | ||
| row, col, letter_index, direction_index = stack[-1] | ||
| if letter_index == len(word) - 1: | ||
| return True | ||
|
|
||
| if direction_index == len(directions): | ||
| seen[row][col] = False | ||
| stack.pop() | ||
| continue | ||
|
|
||
| d_row, d_col = directions[direction_index] | ||
| stack[-1] = (row, col, letter_index, direction_index + 1) | ||
| row_next = row + d_row | ||
| col_next = col + d_col | ||
| next_letter_index = letter_index + 1 | ||
| if ( | ||
| 0 <= row_next < num_row | ||
| and 0 <= col_next < num_col | ||
| and not seen[row_next][col_next] | ||
| and board[row_next][col_next] == word[next_letter_index] | ||
| ): | ||
| seen[row_next][col_next] = True | ||
| stack.append((row_next, col_next, next_letter_index, 0)) | ||
|
|
||
| return False | ||
|
|
||
| for row, col in itertools.product(range(num_row), range(num_col)): | ||
| if start_from(row, col): | ||
| return True | ||
|
|
||
| return False |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import itertools | ||
| import collections | ||
|
|
||
|
|
||
| class Solution: | ||
| def exist(self, board: list[list[str]], word: str) -> bool: | ||
| if not board or not board[0]: | ||
| raise ValueError("invalid board") | ||
|
|
||
| num_row = len(board) | ||
| num_col = len(board[0]) | ||
|
|
||
| board_char_to_count = collections.Counter(itertools.chain.from_iterable(board)) | ||
| word_char_to_count = collections.Counter(word) | ||
|
|
||
| for ch in word_char_to_count: | ||
| if board_char_to_count[ch] < word_char_to_count[ch]: | ||
| return False | ||
|
|
||
| if board_char_to_count[word[-1]] < board_char_to_count[word[0]]: | ||
| word = word[::-1] | ||
|
|
||
| def traverse( | ||
| row: int, col: int, letter_index: int, seen: list[list][bool] | ||
| ) -> bool: | ||
| if not word[letter_index] == board[row][col]: | ||
| return False | ||
| if letter_index == len(word) - 1: | ||
| return True | ||
| for row_next, col_next in ( | ||
| (row + 1, col), | ||
| (row - 1, col), | ||
| (row, col + 1), | ||
| (row, col - 1), | ||
| ): | ||
| if ( | ||
| 0 <= row_next < num_row | ||
| and 0 <= col_next < num_col | ||
| and not seen[row_next][col_next] | ||
| ): | ||
| seen[row_next][col_next] = True | ||
| if traverse(row_next, col_next, letter_index + 1, seen): | ||
| return True | ||
| seen[row_next][col_next] = False | ||
|
|
||
| return False | ||
|
|
||
| for row, col in itertools.product(range(num_row), range(num_col)): | ||
| seen = [[False] * num_col for _ in range(num_row)] | ||
| seen[row][col] = True | ||
| if traverse(row, col, 0, seen): | ||
| return True | ||
|
|
||
| return False |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import itertools | ||
| import collections | ||
|
|
||
|
|
||
| class Solution: | ||
| def exist(self, board: list[list[str]], word: str) -> bool: | ||
| if not board or not board[0]: | ||
| raise ValueError("invalid board") | ||
|
|
||
| num_row = len(board) | ||
| num_col = len(board[0]) | ||
|
|
||
| board_char_to_count = collections.Counter(itertools.chain.from_iterable(board)) | ||
| word_char_to_count = collections.Counter(word) | ||
|
|
||
| for ch in word_char_to_count: | ||
| if board_char_to_count[ch] < word_char_to_count[ch]: | ||
| return False | ||
|
|
||
| if board_char_to_count[word[-1]] < board_char_to_count[word[0]]: | ||
| word = word[::-1] | ||
|
|
||
| directions = ( | ||
| (1, 0), | ||
| (-1, 0), | ||
| (0, 1), | ||
| (0, -1), | ||
| ) | ||
|
|
||
| def start_from(row_start: int, col_start: int) -> bool: | ||
| if board[row_start][col_start] != word[0]: | ||
| return False | ||
|
|
||
| seen = [[False] * num_col for _ in range(num_row)] | ||
| seen[row_start][col_start] = True | ||
| stack = [(row_start, col_start, 0, 0)] | ||
|
|
||
| while stack: | ||
| row, col, letter_index, direction_index = stack[-1] | ||
| if letter_index == len(word) - 1: | ||
| return True | ||
|
|
||
| if direction_index == len(directions): | ||
| seen[row][col] = False | ||
| stack.pop() | ||
| continue | ||
|
|
||
| stack[-1] = (row, col, letter_index, direction_index + 1) | ||
| dr, dc = directions[direction_index] | ||
| row_next = row + dr | ||
| col_next = col + dc | ||
| if ( | ||
| 0 <= row_next < num_row | ||
| and 0 <= col_next < num_col | ||
| and board[row_next][col_next] == word[letter_index + 1] | ||
| and not seen[row_next][col_next] | ||
| ): | ||
| seen[row_next][col_next] = True | ||
| stack.append((row_next, col_next, letter_index + 1, 0)) | ||
|
|
||
| for row, col in itertools.product(range(num_row), range(num_col)): | ||
| if start_from(row, col): | ||
| return True | ||
|
|
||
| return False |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
and は行末に書くこともあるようです。
参考までにスタイルガイドへのリンクを共有いたします。
https://google.github.io/styleguide/pyguide.html#32-line-length
なお、このスタイルガイドは“唯一の正解”というわけではなく、数あるガイドラインの一つに過ぎません。チームによって重視される書き方や慣習も異なります。そのため、ご自身の中に基準を持ちつつも、最終的にはチームの一般的な書き方に合わせることをお勧めします。
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.
リンク先の記事によると、PEP 8では演算子の前に改行を行うことが推奨されているようです。ただし、2016年以前は演算子の後が推奨されていたようです。
https://rcmdnk.com/blog/2019/11/04/computer-python/
自分はこれに倣って以降演算子の前に改行を行うように書こうと思います。
自分は改行をフォーマッタに任せて意識していなかったので勉強になりました。