-
Notifications
You must be signed in to change notification settings - Fork 0
Valid Parentheses #7
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,213 @@ | ||
# Valid Parentheses | ||
|
||
## step1 | ||
|
||
- 最初の十分で下のコードを書いた | ||
- ([)]のような事例に対応できていない。 | ||
|
||
```python | ||
class Solution: | ||
def isValid(self, s: str) -> bool: | ||
brackets = {"round":0,"curly":0,"square":0} | ||
for character in s: | ||
if character == "(": | ||
brackets["round"] += 1 | ||
elif character == ")": | ||
brackets["round"] += -1 | ||
if brackets["round"] < 0: | ||
return False | ||
elif character == "{": | ||
brackets["curly"] += 1 | ||
elif character == "}": | ||
brackets["curly"] += -1 | ||
if brackets["curly"] < 0: | ||
return False | ||
elif character == "[": | ||
brackets["square"] += 1 | ||
elif character == "]": | ||
brackets["square"] += -1 | ||
if brackets["square"] < 0: | ||
return False | ||
|
||
if all(val == 0 for val in brackets.values()): | ||
return True | ||
else: | ||
return False | ||
``` | ||
|
||
- わからなかったため[回答](https://leetcode.com/problems/valid-parentheses/solutions/3399077/easy-solutions-in-java-python-and-c-look-at-once-with-exaplanation/)を見た | ||
|
||
```python | ||
class Solution: | ||
def isValid(self, s: str) -> bool: | ||
stack = [] | ||
for c in s: | ||
if c in '({[': | ||
stack.append(c) | ||
else: | ||
if not stack or (c == ')' and stack[-1] != '(') or (c == '}' and stack[-1] != '{') or (c == ']' and stack[-1] != '['): | ||
return False | ||
stack.pop() | ||
return not stack | ||
|
||
``` | ||
|
||
- stackに入れて後ろから確かめていくのは思いつかなかった | ||
- `return not stack`で返すとbool値になるのは知らなかった | ||
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. |
||
- [[引用符]]は"と'で違いがあるのだろうか? | ||
- [pep8](https://peps.python.org/pep-0008/#string-quotes)によるとどちらでもいいらしい | ||
- 文字列内にどちらかが含まれる場合はバックスラッシュを使うためもう一つを使うべき | ||
- ペアのdictを定義して下のようにやった方が簡単になるのではないかと思った | ||
|
||
```python | ||
class Solution: | ||
def isValid(self, s: str) -> bool: | ||
stack = [] | ||
pair = {')':'(','}':'{',']':'['} | ||
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. 承知しました。今度からは気をつけたいと思います。 |
||
for c in s: | ||
if c in '({[': | ||
stack.append(c) | ||
else: | ||
if not stack or stack[-1] != pair[c]: | ||
return False | ||
stack.pop() | ||
return not stack | ||
``` | ||
|
||
- `if len(stack) == 0 or stack.pop() != brackets[s[i]]:`としてもできるらしい | ||
- list.pop(i)について<https://docs.python.org/ja/3/tutorial/datastructures.html> | ||
- リストのi番目の要素を削除しそれを返す。何も指定されない場合は最後の要素を返す。 | ||
|
||
## step2 他の人のコードを見る・コードの改善 | ||
|
||
[valid parentheses は、チョムスキー階層、タイプ-2、文脈自由文法だから、プッシュダウンオートマトンで書ける](https://discord.com/channels/1084280443945353267/1201211204547383386/1202541275115425822) | ||
- [[チョムスキー階層]] | ||
- チョムスキーによって提唱された形式文法の分類のための理論的枠組み | ||
- タイプ0~3がある | ||
- タイプ2:文脈自由文法 | ||
- 非終端記号が単独で生成規則に従う | ||
- プッシュダウンオートマトンで書ける | ||
- プッシュダウンオートマトン | ||
- 要素 | ||
- 状態集合 | ||
- 有限の内部状態を保つ | ||
- 入力 | ||
- スタック | ||
- 初期状態 | ||
- スタック初期記号 | ||
- スタックが空であることを示すもの | ||
- 状態遷移関数 | ||
- 現在の状態・入力・スタックのトップ記号に基づいて次の状態とスタック操作を決定する | ||
- 自分が書いているコードのやり方に名前がついてるということ | ||
- 今後調べてみる | ||
## [再帰下降構文解析](https://www.youtube.com/watch?v=b83HIvQ8bqY)でも解ける | ||
- 難しそうだったので今後の課題とする | ||
## [moriさん](https://github.com/hroc135/leetcode/pull/6/files/a54d34fc4e5ed6ed09a40bf695d55924b8a9b42f#diff-bfc7c633525ec3f5b431366ade3df4c7bbc2592dca465c6b4fc39882d99dec66) | ||
- やり方はほぼ同じ | ||
- Lifo Queueを用いている | ||
- [[スタックとキュー]]のうちスタックを実装するもの | ||
- 主にスレッド通信に用いられる | ||
- スタック操作に効率化されている | ||
- 今回はListの順番の要素が必要ないためLifoQueueを用いるのも有用と考えられる。 | ||
- dictをopen_to_closeで実装した方が直感的なので良いと考える | ||
```python | ||
from queue import LifoQueue | ||
|
||
|
||
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 = LifoQueue() | ||
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. queue.LifoQueue() は内部でスレッド同期が取られるため、取られないデータ構造に比べて動作が遅いと思います。プロデューサー・コンシューマーパターンを実装するときなど特別な場合を除き、避けたほうがよいと思います。 |
||
|
||
for c in s: | ||
if c in open_to_close: | ||
open_brackets.put(c) | ||
continue | ||
if open_brackets.empty(): | ||
return False | ||
top = open_brackets.get() | ||
if c != open_to_close[top]: | ||
return False | ||
|
||
return open_brackets.empty() | ||
``` | ||
|
||
### 自分の改善 | ||
|
||
```python | ||
class Solution: | ||
def isValid(self, s: str) -> bool: | ||
open_to_close = { | ||
"(":")", | ||
"{":"}", | ||
"[":"]" | ||
} | ||
stack = [] | ||
|
||
for c in s: | ||
if c in open_to_close: | ||
stack.append(c) | ||
continue | ||
if not stack or c != open_to_close[stack.pop()]: | ||
return False | ||
|
||
return not stack | ||
``` | ||
|
||
collections.dequeを用いてみる | ||
|
||
- [Listとdequeの計算量の違い](https://wiki.python.org/moin/TimeComplexity) | ||
- append,popどちらもO(1)なので今回は差がない | ||
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. 定数倍の処理を無視していて、少し乱暴に思えます。dequeの方は双方向LinkedListを使っているため、単にStackとして使用するならListに比べてオーバーヘッドがあると思います。 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. 計算量に興味がありすぎるかもしれません。計算量は計算時間を見積もるための手段です。だから、定数倍にも興味を持ちましょう。また、内部実装とできることの差異により注目しましょう。 |
||
|
||
```python | ||
from collections import deque | ||
|
||
|
||
class Solution: | ||
def isValid(self, s: str) -> bool: | ||
open_to_close = { | ||
"(":")", | ||
"{":"}", | ||
"[":"]" | ||
} | ||
stack = deque() | ||
|
||
for c in s: | ||
if c in open_to_close: | ||
stack.append(c) | ||
continue | ||
if not stack or c != open_to_close[stack.pop()]: | ||
return False | ||
|
||
return not stack | ||
``` | ||
|
||
いろいろ調べていたら4時間くらいかけてしまった。これで良いのだろうか? | ||
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. LeetCode解くことがゴールではないのでいいのではないでしょうか。慣れれば調べるのに掛かる時間も減ると思います。 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. 問題にもよりますが、この問題からは相当たくさんのことを連想することが分かったと思います。はじめはそれでいいのです。 |
||
|
||
## step3 | ||
|
||
step2と同じ | ||
|
||
```python | ||
class Solution: | ||
def isValid(self, s: str) -> bool: | ||
open_to_close = { | ||
"(":")", | ||
"{":"}", | ||
"[":"]" | ||
} | ||
stack = [] | ||
|
||
for c in s: | ||
if c in open_to_close: | ||
stack.append(c) | ||
continue | ||
if not stack or c != open_to_close[stack.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. 自分はifの条件を分けて書いてしまいますね。あとstackの操作もif分とは別にやると思います。まあ好みかもしれないです。 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 False | ||
|
||
return not stack | ||
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. 自分もこっち派です 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. 個人的には好みの範囲かなと思ってます。どの記法に慣れているかだったりPython以外の馴染みのある言語でも読みやすさも変わってきそうですし。個人的には 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. PEP-8 と Google Style Guide は strings, lists, tuples は implicit でということでしたね。 |
||
``` |
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.
カッコが登場する順番も考慮する必要があるので、カウントするだけではだめですね。コードを書く前に手作業でやるならどうすれば良いのかということを考えると良いと思います。
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.
ありがとうございます。手作業でやるならどうするかを考えたことはなかったので次から試してみたいと思います。