-
Notifications
You must be signed in to change notification settings - Fork 0
Wanwan87 20. valid parentheses #6
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,149 @@ | ||
| # step1 | ||
| - 紙面上で入力パターンを考えてみた | ||
| - 入力を取り出していって (,{,[ が来ていないのに ),},] が先に来るパターンはfalseになる | ||
| - ( が来たら丸かっこフラグをたてる、{ がきたら波かっこフラグを立てる。フラグが立っていないのに 閉じる側のかっこがきたらfalse | ||
| - ループでi番目とi+1番目の入力を比較して、開きかっこがきたら閉じるかっこが来るまでi+2,i+3と進めていく | ||
| - 例えば入力が([])だったら、i番目:( i+1番目:[ でfalseなので ( を保持しして 一致する閉じかっこが来るまでループを回す | ||
| - などを考えていたが、入力が(([]))のときなどの判断が難しかったので、一旦別の方法に切り替える | ||
| - (([]))のときに 最初の(を0番目としたら、入力の一番最後である5番目に)が来ればよい。1番目の ( に対応する ) はstrの長さ-1番目に、[ に対応する ] は strの長さ-2番目に来る。鏡のように対称の位置にあるかっこを探す形であれば実現できそう | ||
|
|
||
| ここまでで1時間ぐらいかかっている。 | ||
|
|
||
| 以下間違い | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def isValid(self, s: str) -> bool: | ||
| for i in range(len(s)): | ||
| if len(s) == 1: | ||
| return False | ||
| if s[i] =='(': | ||
| if s[len(s)-i-1] ==')' or s[i+1] ==')': | ||
| return True | ||
| elif s[i] =='{': | ||
| if s[len(s)-i-1] =='}' or s[i+1] =='}': | ||
| return True | ||
| elif s[i] =='[': | ||
| if s[len(s)-i-1] ==']' or s[i+1] ==']': | ||
| return True | ||
| else: | ||
| return False | ||
| return True | ||
| ``` | ||
|
|
||
| - sの長さ奇数のときは即falseにしてよさそう | ||
| - 今のコードだと "()(]" とかで破綻しそう。()の段階で s[i+1] ==')' で trueにしてしまっているから。 | ||
| - 即trueにしない場合、"()"のときの")"に対応するかっこを探しに行って破綻しそう | ||
| - 破綻しないようにsの長さ分forを回さず、len(s)/2も考えたが、結局"()(]"でダメそう | ||
| - 破綻しないようにパッチを当てていく方法だと、新しく追加した条件によって、もともと解決できていた個所も気付かないうちにカバーできなくなってしまっていたりする | ||
| - 対称の位置のかっこを探す方法を思いついた時に"(([]))"のような対称性のある入力のみを考えてしまったが、対称性のない入力も考えるべきだった。 | ||
|
|
||
| 時間をかけすぎてしまったので答えを見て整理。 | ||
|
|
||
| ```python3 | ||
| class Solution: | ||
| def isValid(self, s: str) -> bool: | ||
| i=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. 二項演算子の両側にスペースが入っているものと入っていないものが混ざっているのが気になりました。 参考までにスタイルガイドへのリンクを共有いたします。 https://peps.python.org/pep-0008/#other-recommendations
https://google.github.io/styleguide/pyguide.html#s3.6-whitespace
なお、このスタイルガイドは“唯一の正解”というわけではなく、数あるガイドラインの一つに過ぎません。チームによって重視される書き方や慣習も異なります。そのため、ご自身の中に基準を持ちつつも、最終的にはチームの一般的な書き方に合わせることをお勧めします。 |
||
| # stackに格納していく | ||
| a=[] | ||
|
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. a という変数名からは、中にどのような値が格納されるか想像しにくく感じます。 open_brackets 等、中に格納される値が想像しやすい変数名を付けるとよいと思います。
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. ありがとうございます、中身がわかる変数名を意識します |
||
| for i in range(len(s)): | ||
| # ({[の場合、スタックにプッシュする | ||
| if s[i]=='('or s[i]=='['or s[i]=='{': | ||
| a.append(s[i]) | ||
| # )}]の場合 | ||
| else: | ||
| # stackが空の場合はfalse | ||
| if not a: | ||
| return False | ||
| # stackに({[が入っている場合はtopと比較する | ||
| top=a.pop() | ||
| # 入力のかっことtopが一致しない場合はfalse。 | ||
| if s[i]==')'and top!='(': | ||
| return False | ||
| if s[i]==']'and top!='[': | ||
| return False | ||
| if s[i]=='}'and top!='{': | ||
| return False | ||
| # stackが空になったらtrueを返す | ||
| return len(a)==0 | ||
| ``` | ||
|
|
||
|
|
||
| # step2 | ||
|
|
||
| - 変数名aは変えたい。stackとか? | ||
| - https://github.com/hiro111208/leetcode/pull/6/changes | ||
| - ({[はdict型に格納すると簡潔に書けそう | ||
| - 命名は (キー)_to_(値) が良いらしい | ||
| - 今回の場合だと,open_to_closeという変数に{"(":")"}のように入れていく。 | ||
| - return not stackがスタイルガイド的にはいい。あくまでガイドなのでチームでのルールに則る。 | ||
| - https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0 | ||
| - 番兵を置いておくことで条件式を1つ減らせるらしい | ||
| - stackが空の場合の条件に入らなくなるので削減できる(if not aの条件) | ||
| - >“(aiu)[eo]” が入力としてきたときに、プログラムの挙動として好ましいのは何だと考えますか? | ||
| - 余計な入力は無視してtrueにする? | ||
| - これはちょっと怖いかも。関数の使用者かユーザーになにかしらのFBを返したい。 | ||
| - 入力がおかしいのでfalseにする? | ||
| - なんでfalseになっているか気づかれないかも。 | ||
| - エラーとして例外を投げる? | ||
| - 要件によるかもしれないが、かっこ以外の文字は入れないでくださいと返すとか。 | ||
| - 今回のコードの場合はforの中で確認すればよさそう。if char in open_to_closeのcontinueの時点で、開きかっこではないことが確定しているので、その下に閉じかっこでないことを確認(if char not in set(open_to_close.value())して、エラーを出す。 | ||
| - プッシュダウンオートマトン | ||
| - 聞いたことはなかったが、オートマトン+スタックを組み合わせた計算モデル | ||
| - https://www.krrk0.com/pushdown-automaton/ | ||
| - チョムスキー階層 | ||
| - 形式言語を生成する形式文法の包含階層(形式言語の階層)で、句構造文法(phrase structure grammar)の階層」などともいう | ||
| - 形式言語:プログラミング言語を含む一部の人工言語や、機械可読なドキュメント類など、用法の変化に関して自然言語に対して厳格である言語。自然言語は話者集団によってあいまいさが残されたり、用法がうつろいゆく。 | ||
| - チョムスキー階層のタイプ2がプッシュダウンオートマトンらしい。 | ||
| - https://ja.wikipedia.org/wiki/%E3%83%81%E3%83%A7%E3%83%A0%E3%82%B9%E3%82%AD%E3%83%BC%E9%9A%8E%E5%B1%A4 | ||
|
|
||
|
|
||
| if char != open_to_close[last_open_brackets]にする場合は、stackから#をpopしてきた時に辞書にないのでエラーとなってしまうので、辞書に登録するか、getでキーが存在しない場合に第二引数である空文字を返すようにする。 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def isValid(self, s: str) -> bool: | ||
| open_to_close = {"(" : ")", "{" : "}", "[" : "]"} | ||
| stack = ["#"] | ||
| for char in s: | ||
| if char in open_to_close: | ||
| stack.append(char) | ||
| continue | ||
| last_open_brackets = stack.pop() | ||
| if char != open_to_close.get(last_open_brackets,""): | ||
| return False | ||
| return stack == ["#"] | ||
| ``` | ||
|
|
||
|
|
||
| # step3 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def isValid(self, s: str) -> bool: | ||
| open_to_close = {"(":")","{":"}","[":"]"} | ||
| stack = ["#"] | ||
| for char in s: | ||
| if char in open_to_close: | ||
| stack.append(char) | ||
| continue | ||
| last_opne_bracket = stack.pop() | ||
| if char != open_to_close.get(last_opne_bracket,""): | ||
| return False | ||
| return stack == ["#"] | ||
| ``` | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def isValid(self, s: str) -> bool: | ||
| open_to_close = {"(":")","{":"}","[":"]"} | ||
| stack = ["#"] | ||
| for char in s: | ||
| if char in open_to_close: | ||
| stack.append(char) | ||
| continue | ||
| last_open_bracket = stack.pop() | ||
| if char != open_to_close.get(last_open_bracket,""): | ||
| return False | ||
| return stack == ["#"] | ||
| ``` | ||
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.
同じ失敗しました。
上手くいかなかったのは()(]を考えてないからなんですね。やっと理由がわかりました。
失敗の反省など書いてるの良いと思います。
Uh oh!
There was an error while loading. Please reload this page.
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.
ありがとうございます、良いアイデアだ!と思ってコードを書き始めちゃいましたが、(問題文で提示されている)テストケースは少なくとも試しておいたほうが良さそうですね