Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions 20.Valid_Parentheses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
参考
https://github.com/rm3as/code_interview/pull/4/files
https://github.com/tarinaihitori/leetcode/pull/7/files など

1st.

stackを使って実装できると分かった
入力文字列を前から見ていって、
* 開き括弧の場合はstackに積む
* 閉じ括弧の場合はstackの一番上と
* 同じならばOK でstackからpop
* 同じでないならばout でFalse となる

これを文字列の最後まで見終わったときに
* stackが空ならすべて対応する括弧が正しい順番だったのでTrue
* 空でないなら開き括弧が残っているのでFalseとなる

方針はすぐ立ち、閉じ括弧が来た時に対応する開き括弧がすぐわかると良いので辞書を用意するところは良かったが、
Pythonのstackが分かっておらずバグらせてdocumentを見て実装した
特に要素がない場合にpop()するとエラーが出る仕様は知らなかった

```Python
class Solution:
def isValid(self, s: str) -> bool:
mapping = {')':'(', '}':'{', ']':'['}
stack = []

for character in s:
if character in mapping:
if stack and mapping[character] == stack.pop():
pass
else:
return False
else:
stack.append(character)

if not stack:
return True
else:
return False
```


2nd.
* 名前の変更
character -> bracket (今回の文字列は括弧のみなのでこちらのほうが適切)
辞書の名前はkey_to_valueとつけるのがよい
closeをkey, valueをvalueとしていたが、逆にした(入力の文字が \( かの判定を簡潔に書ける)
* 最後のreturnの簡単化
```Python
if not stack:
return True
else:
return False
```


```Python
return not stack
```

と簡潔に書ける

* ネストの深さ
if文がネストして読みづらくなっていた部分もあるのでcontinueで早めに抜けて浅くした
また不正な場合はすぐreturnするようにした

* 予期しない入力への対応
https://discord.com/channels/1084280443945353267/1225849404037009609/1231648833914802267

今回のコードだと括弧でない入力があったときに最初の条件でelseになりstackに入る
この文字がstackからpopされることはないので、途中のstackのpop時、または最後のstackの空判定でFalseになるので一応対応は出来ているはず(1st.ではここまで考えてなかったのでたまたま)
しかし、分かりづらい
不正な入力のときにすぐFalseを返す流れに変更(3rd.)

また、より丁寧にvalid_inputに適切な入力文字のリストを作り最初に確認 -> 今回は6文字だけなので良いがもっと多い場合は大変
また、validな入力かチェックする前に文字がbracketになっていると
```Python
if bracket in valid_input:
```
となり括弧が括弧に入っているかみたいになるのでcharに変更(characterは長いかも)


```Python
class Solution:
def isValid(self, s: str) -> bool:
valid_input = ['(', ')', '{', '}', '[', ']']
open_to_close = {'(':')', '{':'}', '[':']'}
stack = []

for char in s:
# 括弧以外の入力が来た場合の処理 無視する
if not char in valid_input:
continue
if char in open_to_close:
stack.append(char)
continue
if not stack:
return False
if char != open_to_close[stack.pop()]:
return False

return not stack
```

dequeを用いた解法
deque先頭、末尾へのアクセスがO(1).ただしそれ以外の真ん中の要素へのアクセスはO(n).
今回はstackとしてか用いないため末尾以外の要素にアクセスすることがないのでdequeを使うと良い(dequeの方がlistより若干速いよう)
from collections import deque が必要
上のコードの
stack = [] を stack = deque()にするだけ


3rd.
不正な入力はFalseになるようにした(無視したい場合はsndのようにする)
また括弧の対応判定は関数化できるので試してみた

```Python
class Solution:
def isValid(self, s: str) -> bool:
def is_pair(open, close):
if open == '(' and close == ')':
return True
if open == '{' and close == '}':
return True
if open == '[' and close == ']':
return True
return False

stack = deque()

for char in s:
if char == '(' or char == '{' or char == '[':
stack.append(char)
continue
if not stack:
return False
if not is_pair(stack.pop(), char):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

個人的には副作用のある式を条件のところにあまり書きたくないですね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントありがとうございます。

stack_top = stack.pop()
if not is_pair(stack_top, char):

のように一度変数に入れてから条件式に入れるのがよいですかね

これは、pop()がうまくいかなかったのにたまたま条件を満たしてしまい、エラーが起きたときにどこで最初に問題が起きていたか分かりづらくなる可能性があるから ということでしょうか?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同時に考えることが増えるので。
まあ趣味の範囲かと思います。

return False

return not stack
```

```Python
class Solution:
def isValid(self, s: str) -> bool:
open_to_close = {'(':')', '{':'}', '[':']'}
stack = deque()

for char in s:
if char in open_to_close:
stack.append(char)
continue
if not stack:
return False
if char != open_to_close[stack.pop()]:
return False

return not stack
```