From 1b3e49a7f5e9ba12caf831de9d2fd958c8e83e66 Mon Sep 17 00:00:00 2001 From: yus-yus Date: Thu, 6 Feb 2025 15:42:57 +0900 Subject: [PATCH] 20 Valid Parentheses --- 20.Valid_Parentheses.md | 162 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 20.Valid_Parentheses.md diff --git a/20.Valid_Parentheses.md b/20.Valid_Parentheses.md new file mode 100644 index 0000000..a910966 --- /dev/null +++ b/20.Valid_Parentheses.md @@ -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): + 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 +``` +