-
Notifications
You must be signed in to change notification settings - Fork 0
Create 20. Valid Parentheses.md #8
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,144 @@ | ||
| 問題文: https://leetcode.com/problems/valid-parentheses/description/ | ||
|
|
||
| # step1: 何も見ないで書く(制限時間5分) | ||
| - CZAP4の計算モデルの回で聞いた問題なのでスタックを使うという方針はすぐに立てられた。 | ||
| - 手作業として考えるなら、こういう手順。 | ||
| - bracketの詰め合わせの中身がvalidかどうかをチェックしてください。 | ||
| - あなたの作業スペースにはbracketの種別ごとの対応表とopen置き場があります。 | ||
| - 詰め合わせの中身を前から順に取り出していき、open bracketが出てきたらopen置き場に積み重ねていってください。 | ||
| - close bracketが出たら、open置き場を確認してください。 | ||
| - open置き場が空だったら詰め合わせはvalidでないです。falseと報告してください。 | ||
| - open置き場が空じゃなければ一番上のbracketを取り出して対応表を確認し、対応が一致しているかを確認してください。一致していなければ詰め合わせはvalidではないので、falseと報告してください。 | ||
| - 一致していればそのbracketのペアは正しいです。正しいペアは脇に退けて、詰め合わせのチェックを続行してください。 | ||
| - 詰め合わせをすべてチェックし終えたとき、open置き場にbracketが残っていたら詰め合わせはvalidではありません。falseと報告してください。 | ||
| - 詰め合わせをチェックし終えて、open置き場に何もなければ詰め合わせはvalidです。trueを報告してください。 | ||
| - pythonでスタックを実装したいときはlist型が使える。\ https://docs.python.org/ja/3/tutorial/datastructures.html#more-on-lists | ||
| - リストが空のときにpop()メソッドを呼ぶとIndexErrorが送出される。事前にリストが空でないかのチェックが不可欠。 | ||
| - bracketの対応はdict型で保持する。\ https://docs.python.org/ja/3/library/stdtypes.html#typesmapping | ||
| - bracket以外の文字が入力に含まれているときは、何もせず`continue`する。 | ||
| - 実際の使用場面(コンパイラとか?)を想定するとブラケット以外の文字が含まれているほうが当たり前だと思われる。いちいち処理を止めるような実装にすると使い物にならない気がする。 | ||
| ```python | ||
| class Solution: | ||
| def isValid(self, s: str) -> bool: | ||
| close_to_open_dict = {')' : '(', '}' : '{', ']' : '['} | ||
| open_list = list(close_to_open_dict.values()) | ||
| open_stack = [] | ||
| i = 0 | ||
| while i < len(s): | ||
| symbol = s[i] | ||
| if symbol in open_list: | ||
| open_stack.append(symbol) | ||
| i += 1 | ||
| continue | ||
|
|
||
| if symbol in close_to_open_dict: | ||
| if len(open_stack) == 0: | ||
| return False | ||
| checking = open_stack.pop() | ||
| correct_open = close_to_open_dict[symbol] | ||
|
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. 自分なら expected という単語を使うと思います。 単体テストでは、 actual、expected という単語が使われる場合があります。 |
||
| if checking != correct_open: | ||
| return False | ||
| i += 1 | ||
| continue | ||
| i += 1 | ||
|
|
||
| if len(open_stack) != 0: | ||
|
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 not open_stackのほうがシンプルだと思います。 |
||
| return False | ||
| return True | ||
|
|
||
| ``` | ||
|
|
||
|
|
||
| # step2: 他の人を参考にコードを整える・コメントを予測する | ||
| ## 直近のコード | ||
| https://github.com/hiroki-horiguchi-dev/leetcode/pull/6 | ||
| - 使用例を考えながら実装している点が素晴らしかった。 | ||
|
|
||
| https://github.com/yas-2023/leetcode_arai60/pull/6 | ||
| - スタックだけでなく再帰も検討している。自分は再帰で解くという選択肢を思いつかなかった。 | ||
|
|
||
|
|
||
| https://github.com/nanae772/leetcode-arai60/pull/7 | ||
| - こちらもスタックと再帰。あとは、スタックからポップしたopen bracketをclose bracketに変換すればdictの初期化がわかりやすくなる(close_to_openからopen_to_closeにできる)との指摘あり。step2はこちらの方法を採用する。 | ||
|
|
||
|
|
||
|
|
||
| ## コメント集 | ||
| https://github.com/SanakoMeine/leetcode/pull/7#discussion_r1903350766 | ||
| - スタックの底に番兵を置くというテクニック。自分の選択肢に番兵が入っていないのは番兵を使ったことがないことが最大の原因なので、step2で使ってみる。 | ||
|
|
||
| https://discord.com/channels/1084280443945353267/1225849404037009609/1231648833914802267 | ||
|
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. これは一般によく考えられることだと思います。
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. 確かにユーザーの入力を処理するときは止まってほしい場面がありますね。開発経験に基づいたコメントは大変ありがたいです。 |
||
| - 想定外の入力への対応をどうするか。私は想定外の入力が来ても無視して`continue`することにしているが、状況によって対応は変わるらしい。自分以外の誰かが書き換えたときどうなるかという話は全然想定していなかった。 | ||
|
|
||
|
|
||
| https://github.com/HitoshiKoba/Arai60-public/pull/2#discussion_r1998179229 | ||
| - 進め方について。再帰下降構文解析の実装をするかどうか迷ってたが、先に進むことを優先しstep2,3ではやらない。step4とかでやります。 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def isValid(self, s: str) -> bool: | ||
| open_to_close = { | ||
| '(' : ')', | ||
| '{' : '}', | ||
| '[' : ']' | ||
| } | ||
| open_brackets = set(open_to_close.keys()) | ||
| close_brackets = set(open_to_close.values()) | ||
| valid_inputs = open_brackets.union(close_brackets) | ||
| stacked_opens = ['\0'] | ||
| open_to_close['\0'] = '\0' | ||
|
|
||
| for symbol in s: | ||
| if symbol not in valid_inputs: | ||
| continue | ||
| if symbol in open_brackets: | ||
| stacked_opens.append(symbol) | ||
| continue | ||
| correspond_open = stacked_opens.pop() | ||
| correct_close = open_to_close[correspond_open] | ||
| if symbol != correct_close: | ||
| return False | ||
|
|
||
| remaining = stacked_opens.pop() | ||
| if remaining != '\0': | ||
| return False | ||
| return True | ||
|
|
||
| ``` | ||
|
|
||
|
|
||
| # step3: 3回連続ミスなしで書く(制限時間15分) | ||
| - 制限時間を延長した。書き終わった後にタイポのチェックをすると時間が10分では足りなくなる。 | ||
| - 変数名を若干変更した。 | ||
| ```python | ||
| class Solution: | ||
| def isValid(self, s: str) -> bool: | ||
| open_to_close = { | ||
|
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. やっぱり |
||
| '(' : ')', | ||
| '{' : '}', | ||
| '[' : ']' | ||
| } | ||
| open_brackets = set(open_to_close.keys()) | ||
| close_brackets = set(open_to_close.values()) | ||
| valid_brackets = open_brackets.union(close_brackets) | ||
|
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. 二項演算子|のオーバーロードを用いて、 valid_brackets = open_brackets | close_bracketsと書くこともできますね。 |
||
| sentinel = '\0' | ||
| unclosed_opens = [sentinel] | ||
| open_to_close[sentinel] = sentinel | ||
|
|
||
| for symbol in s: | ||
| if symbol not in valid_brackets: | ||
| continue | ||
|
Comment on lines
+129
to
+130
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. この2行が先にあると読み手は以降カッコだけに集中できていいですね。 |
||
| if symbol in open_brackets: | ||
| unclosed_opens.append(symbol) | ||
| continue | ||
| latest_open = unclosed_opens.pop() | ||
| correct_close = open_to_close[latest_open] | ||
| if symbol != correct_close: | ||
| return False | ||
|
|
||
| remaining = unclosed_opens.pop() | ||
|
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. 私はこれ
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.
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 len(unclosed_opens) == 1;とするのが読みやすいように感じました。
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. 文字列の走査は終わってるのでスタックの中身を触りに行く必要なかったですね。条件の書き方については趣味に応じて何通りかあるのだと理解しました。 |
||
| if remaining != sentinel: | ||
| return False | ||
| return True | ||
|
|
||
| ``` | ||
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.
Implicit false を利用し、
と書くことをおすすめします。
参考までにスタイルガイドへのリンクを貼ります。
https://google.github.io/styleguide/pyguide.html#2144-decision
上記のスタイルガイドは唯一絶対のルールではなく、複数あるスタイルガイドの一つに過ぎないということを念頭に置くことをお勧めします。また、所属するチームにより何が良いとされているかは変わります。自分の中で良い書き方の基準を持ちつつ、チームの平均的な書き方で書くことをお勧めいたします。