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
32 changes: 32 additions & 0 deletions 20_Valid_Parentheses/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 20. Valid Parentheses

<https://leetcode.com/problems/valid-parentheses/>

## step1(まず通す)

文字列を先頭から見ていって

- 開きカッコ→スタックに積む
- とじカッコ→スタックが空じゃなくて、topが対応する開きカッコならそれをpopする。対応してなかったら即NG

最後にスタックが空になってたらOK

## step2(整形&他の人のコードを読む)

- opens は文字列で書いてもよかったかも(文字数が少なくてタイプが楽だし見やすそう)
- コメント集: 「"[aiu](eo)" が入力としてきたときに、プログラムの挙動として好ましいのは何だと考えますか?」
- →カッコに着目して妥当かを判断するプログラムであるのが良いか、あるいは要件によってはカッコ以外が入っていたらエラーを出して止まって欲しい、となるかもしれない。
- 他の文字を許容して括弧に着目した妥当性を判断する場合は、opens の他に closes も用意して、どちらでもない場合はスルーするようにする、というのが良さそう
- そうすると、for で回す変数は parenthesis じゃなくて character とかになりそう
- スタックが空になってたら True, そうじゃないなら False → not stack を返すことで見た目がスッキリする
- <https://github.com/X-XsleepZzz/leetcode/pull/7/changes>
- 取り組んでいる間にいただいたコメントで教えていただいたスタイルガイドでも、list が空かどうかは "implicit" な boolean で書けと指定されている
- <https://github.com/MA-yo-TA/leetcode/pull/6#discussion_r3369098265>

## step3(10分以内にさっとかける * 3回)

書いていて気づいたが、step2.py だと括弧の種類が増減した時に opens/closes/close_to_open の3つを書き換えないといけないので、opens/closes を close_to_open.values() close_to_open.keys() にした方がいいかも。ただしその場合でも、読み書きする時に .keys(), .values() だとどっちがどっちか混乱するので、変数に格納しといた方が読みやすそう。

## step4

いただいたコメントに沿って書き直してみる
20 changes: 20 additions & 0 deletions 20_Valid_Parentheses/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Solution:
def isValid(self, s: str) -> bool:
opens = ["(", "[", "{"]
close_to_open = {")": "(", "]": "[", "}": "{"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こちらのコメントをご参照ください。
silby72/LeetCode_arai60#5 (comment)

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 = []

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こちらのコメントをご参照ください。
silby72/LeetCode_arai60#5 (comment)

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.

ありがとうございます。
今回は opens (開きカッコの集まり)を変数で置いるのでそれをやめて スタックを open_brackets とするか、あるいは (found|discovered)_open_brackets などと書いて区別するか、でしょうかね。

for parenthesis in s:
if parenthesis in opens:
stack.append(parenthesis)
continue

if stack and stack[-1] == close_to_open[parenthesis]:
stack.pop()
continue

return False

if len(stack) != 0:
return False

return True
18 changes: 18 additions & 0 deletions 20_Valid_Parentheses/step2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Solution:
def isValid(self, s: str) -> bool:
opens = "([{"
closes = ")]}"
close_to_open = {")": "(", "]": "[", "}": "{"}
stack = []
for character in s:
if character in opens:
stack.append(character)
continue

if character in closes:
if stack and stack[-1] == close_to_open[character]:
stack.pop()
else:
return False

return not stack
18 changes: 18 additions & 0 deletions 20_Valid_Parentheses/step3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Solution:
def isValid(self, s: str) -> bool:
close_to_open = {")": "(", "]": "[", "}": "{"}
closes = close_to_open.keys()
opens = close_to_open.values()
stack = []
for character in s:
if character in opens:
stack.append(character)
continue

if character in closes:

@huyfififi huyfififi Jun 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

確かに [aiu](eo) のような入力を想定するのは納得感があり、そうするとここでも if 文が必要になるのですね、勉強になります 👀
なんとなくですが、カッコ以外の文字列をスキップすることを先に持ってきてもいいかなと思いました。メインで想定している入力以外のものを最初にはじけば、後の処理は限られた範囲内の入力でわかりやすいかな、と。

        for character in s:
            if character not in opens and character not in closes:
                continue

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.

ありがとうございます。そうですね、今のコードだとカッコじゃない文字の扱いが implicit なので冒頭で明示した方がわかりやすいかもですね。

if stack and stack[-1] == close_to_open[character]:
stack.pop()
else:
return False

return not stack
22 changes: 22 additions & 0 deletions 20_Valid_Parentheses/step4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Solution:
def isValid(self, s: str) -> bool:
open_to_close = {"(": ")", "[": "]", "{": "}"}
open_brackets = []
for character in s:
if (
character not in open_to_close.keys()
and character not in open_to_close.values()
):
continue

if character in open_to_close.keys():
open_brackets.append(character)
continue

if open_brackets and character == open_to_close[open_brackets[-1]]:
open_brackets.pop()
continue

return False

return not open_brackets