Skip to content
Open
Show file tree
Hide file tree
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
33 changes: 33 additions & 0 deletions arai60/valid-parentheses/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## 考察
- 過去に解いたことあり
- 方針
- stackを使って対応を見ていく
- 前から文字を見ていって、open bracketが来たらstackに積む
- close bracketが来たら、stackから要素をpopして対応をチェックする(stackが空じゃないかだけ注意)
- 最後にstackが空になっていたらOK
- time: O(n), space: O(n)
- あとは実装

## Step1
- 上のアルゴリズムを実装
- time: O(n), space: O(n)

## Step2
- 手続き的にbracketの対応関係を判定していた箇所を、辞書を使って宣言的な記述に変更
- 結果、余計なif文がかなり減った

## Step3
- 1回目: 1m51s
- 2回目: 1m53s
- 3回目: 1m28s

## Step4
- レビューを元にコードを修正
- 変数名の見直し
- stack -> bracket_stack
- 何を入れるstackなのかを明確に
- bracket_pairs -> open_to_close
- 例えば、open_to_close[open_bracket] という記述を見たときにclose_bracketが返ってくることが一目でわかる
- より具体的になって、わかりやすくなった感覚
- `if not open_to_close[open_bracket] == c:` と書いていたところを `if open_to_close[open_bracket] != c:`に
- early continueしてネストを浅く
22 changes: 22 additions & 0 deletions arai60/valid-parentheses/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Solution:
def isValid(self, s: str) -> bool:
stack = []
for c in s:
if c in ['(', '{', '[']:
stack.append(c)
else:
if not stack:
return False

open_bracket = stack.pop()
if c == ')':
if not open_bracket == '(':
return False
elif c == '}':
if not open_bracket == '{':
return False
else:
if not open_bracket == '[':
return False

return not stack
20 changes: 20 additions & 0 deletions arai60/valid-parentheses/step2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Solution:
def isValid(self, s: str) -> bool:
stack = []

Choose a reason for hiding this comment

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

何を入れるstackなのかわかる命名だと良いかもしれません。
brackets_stack とかですかね。

bracket_pairs = {
'(': ')',
'{': '}',
'[': ']',
}
Comment on lines +4 to +8

Choose a reason for hiding this comment

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

open_to_close
とか皆さんよく使われてます。

Copy link
Owner Author

Choose a reason for hiding this comment

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

いい名前ですね。open_to_close 真似させていただきます。

for c in s:
if c in bracket_pairs:
stack.append(c)
else:
if not stack:
Comment on lines +10 to +13

Choose a reason for hiding this comment

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

ここはネストを深くするよりcontinueで切った方が読みやすいなと感じます。

if c in bracket_pairs:
    stack.append(c)
    continue

if not stack:

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます。early continueしてみます。

return False

open_bracket = stack.pop()
if not bracket_pairs[open_bracket] == c:

Choose a reason for hiding this comment

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

ここは素直に

if bracket_pairs[open_bracket] != c:

で良いのではないでしょうか。

Copy link
Owner Author

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
20 changes: 20 additions & 0 deletions arai60/valid-parentheses/step3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Solution:
def isValid(self, s: str) -> bool:
stack = []
bracket_pairs = {
'(': ')',
'{': '}',
'[': ']',
}
for c in s:
if c in bracket_pairs:
stack.append(c)
else:
if not stack:
return False

open_bracket = stack.pop()
if not bracket_pairs[open_bracket] == c:
return False
Comment on lines +10 to +18

Choose a reason for hiding this comment

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

cだけ見るより、「stackのtopと合わせてペアができるか」に注目したほうが条件分岐が少なくなっていいのではと思いました。

(Pythonに詳しくなく、動くコードかは怪しいです...)

Suggested change
if c in bracket_pairs:
stack.append(c)
else:
if not stack:
return False
open_bracket = stack.pop()
if not bracket_pairs[open_bracket] == c:
return False
top = stack[-1]
is_match = False
match (top, c):
case ('(', ')'):
is_match = True
case ('{', '}'):
is_match = True
case ('[', ']'):
is_match = True
if is_match:
stack.pop()
else:
stack.append(c)

Copy link
Owner Author

Choose a reason for hiding this comment

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

コメントありがとうございます。
これは好みの問題ですが、stackに閉じカッコを入れる場合(上のコードで c in [')', '}', ']'] かつ is_match がfalse)は、その時点で全体としてのカッコ列の整合性が崩れるので return false すると頭の中のスタックが解放される感じがします。
例えば (}((((())))) とあったときに、3文字目以降は見なくていいよね、という感じです。

Choose a reason for hiding this comment

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

@kazukiii
なるほどです。場合によっては早めにinvalid判定できるんですね

ありがとうございます〜


return not stack
21 changes: 21 additions & 0 deletions arai60/valid-parentheses/step4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Solution:
def isValid(self, s: str) -> bool:
bracket_stack = []
open_to_close = {
'(': ')',
'{': '}',
'[': ']',
}
for c in s:
if c in open_to_close:
bracket_stack.append(c)
continue

if not bracket_stack:
return False

open_bracket = bracket_stack.pop()
if open_to_close[open_bracket] != c:
return False

return not bracket_stack