diff --git a/problems/20.valid-parentheses/memo.md b/problems/20.valid-parentheses/memo.md new file mode 100644 index 0000000..c7a8937 --- /dev/null +++ b/problems/20.valid-parentheses/memo.md @@ -0,0 +1,53 @@ +## step1 +- この問題はやったことがある +- openの時はstackを確認して適切な順番であるかを確認して、問題なければstackにたす +- closeの時はstackの末尾が対応するものかを確認して、問題なければ末尾を削除 +- 最後に何も残らないことを確認 + +- "()[]{}"これOKなのか +- openの順番を気にする必要がなかった +- ちゃんと要件を確認しないのはよくない +- Example2でも分かったこと +- きちんとExampleを確認する + +## step2 +- 気になっているところ + - 要件的にありえない値が入ってきた時にraise Errorする必要があるか? + - closeの対応関係を表すのにもっといい方法はないか? + - 他の方法だとdictに対応関係入れて(openをkey,closeをvalue)にしたりしてもできそう +- 元々見返した時には気になっていなかったが自分で書き直した時に修正したところ + - 入力がカッコに限定されているためforの中の変数名をletter => parenthesesにした +- 時間計算量: O(n),空間計算量O(n)だと思う + +- 他の人のコードを読む +- https://github.com/Hiroto-Iizuka/coding_practice/pull/6/files + - `bracket_pairs = {'(': ')', '[': ']', '{': '}`はわかりやすい + - 他のコメントであった`open_to_close`もopenがkeyだとわかり良さそう(pairsでも感覚的にopenがkeyだと伝わるだろうが) + - コメントついているが定数を表すので大文字のBRACKET_PAIRSの方がより良い + - openしか入らないので`open_brackets_stack`にした方が良かった +- https://github.com/mamo3gr/arai60/pull/6/files + - 自分は_is_valid_close_parentheses_orderを関数内で定義したが外に出してもよかったかもしれない(自分は今回の対応関係を調査する関数を他で使用することがあるかという観点で判断して中に入れた) + - 私の場合は今入ってきた値が有効であるか?という観点で考え関数に切り出したので、空の場合でも関数に渡して判断させたかったので入力にstackを受け取ったが、対応関係だけ確認するようにされてる + - 私の関数名がorderという順番だけ気にしてる風の名前になっているので元々の私の観点の関数にするならば名前からorderは外した方が良いと思った +- https://github.com/komdoroid/arai60/pull/12 + - [入力に想定外の文字が含まれていた場合について考慮される方もいらっしゃいます。余裕があれば考えてみてください。](https://github.com/komdoroid/arai60/pull/12#discussion_r2630431901) + - やっぱり今回のケースだと想定外の入力に備えて条件を簡略化しすぎない方が拡張性や安全性が高いのでいい気がしてきた + - `参考までに、最後の要素の後にもコンマを追加する流派?も存在します。この方法の利点は、後から新しい要素を追加した時に変化する行数を減らすことができるところにあります。` 勉強になった + - もし、以下の内容について考慮していなかった場合は、問題上起きることはないのですが、一度考えてみると良いと思います! +"(aiu)[eo]" が入力としてきたときに、プログラムの挙動として好ましいのは何だと考えますか? + - [リンク](https://github.com/resumit30minutes/leetcode-arai60-practice/pull/7#discussion_r2588949104) + - こちらでは落ちてほしくないという見解だった。私は入力がおかしいエラーを吐く方がいいと思っていた。 + - 私の意図は、元の仕様と異なる使われ方をした場合に早く入力した人に知らせたいという意図だった + - `そこで、「約束にない間違った使い方をしているのだから、そいつが悪い。驚くような動作をして、デバッグで苦労していても、私の問題ではない。」というのは好まれる態度ではないでしょう。`(https://discord.com/channels/1084280443945353267/1226508154833993788/1227171332131786774) + - 今回のケースだと、元々の仕様にない状況でもカッコ以外の入力を想定して作りたいところ + - それ以外の入力を無視すればいいだけなので関数の複雑さが増さないので + - ただ今回のケースはValid Parenthesesを判定する問題なので不適切な入力が入ってきたら無視するのではなく、エラーを投げる方が優しいと感じる + - 無視して通すようなものはカッコが何も無くても通ってしまうコードになりがちだし、それを防ぐコードにするとカッコがあるかどうかの判定が増え複雑さが増す + - ほとんどのケースで`for char in s:`と書いているがそっちの方がみんなよく書いているのかなと思う + - 文字という意味でstep1でletterと書いたがcharとかcharacterの方がいいのか(DBの型とかにあるからみんな慣れているのか) + - `letterとcharacterの主な違いは、letterがアルファベット(A, B, C...)のような表音文字の1つを指すのに対し、characterはアルファベット、数字(1, 2, 3...)、記号(&, @...)、漢字、絵文字など文字全般(記号や図形的な要素も含む)を指す包括的な言葉です。つまり、すべてのletterはcharacterですが、すべてのcharacterがletterではありません。 ` + - そもそも今回letterに含まれる文字ではなかったし、今後は意図がない場合はcharを使う + + +## step3 + - open_parenthesesとopen_parentheses_stackという最初の文字列が同じものを定義したが、可能であれば異なる方が早く読めるし、suggestの面でも選び間違いがないのでいいと思った diff --git a/problems/20.valid-parentheses/step1.py b/problems/20.valid-parentheses/step1.py new file mode 100644 index 0000000..19e54e8 --- /dev/null +++ b/problems/20.valid-parentheses/step1.py @@ -0,0 +1,54 @@ +# +# @lc app=leetcode id=20 lang=python3 +# +# [20] Valid Parentheses +# + +# @lc code=start +class Solution: + def isValid(self, s: str) -> bool: + parentheses_stack = [] + open_parentheses = {"(", "{", "["} + close_parentheses = {")", "}", "]"} + + # @staticmethod + # def _is_valid_open_parentheses_order(parentheses_stack, input_open_parentheses): + # if not parentheses_stack: + # return input_open_parentheses == "(" + # elif parentheses_stack[-1] == "(": + # return input_open_parentheses == "{" + # elif parentheses_stack[-1] == "{": + # return input_open_parentheses == "[" + # else: + # return False + + @staticmethod + def _is_valid_close_parentheses_order( + parentheses_stack, input_close_parentheses + ): + if not parentheses_stack: + return False + elif parentheses_stack[-1] == "(": + return input_close_parentheses == ")" + elif parentheses_stack[-1] == "{": + return input_close_parentheses == "}" + else: + return input_close_parentheses == "]" + + for letter in s: + if letter in open_parentheses: + # if not _is_valid_open_parentheses_order(parentheses_stack, letter): + # return False + parentheses_stack.append(letter) + + elif letter in close_parentheses: + if not _is_valid_close_parentheses_order(parentheses_stack, letter): + return False + parentheses_stack.pop() + else: + raise ValueError + + return not parentheses_stack + + +# @lc code=end diff --git a/problems/20.valid-parentheses/step2.py b/problems/20.valid-parentheses/step2.py new file mode 100644 index 0000000..3f65bff --- /dev/null +++ b/problems/20.valid-parentheses/step2.py @@ -0,0 +1,35 @@ +# +# @lc app=leetcode id=20 lang=python3 +# +# [20] Valid Parentheses +# + +# @lc code=start +class Solution: + def isValid(self, s: str) -> bool: + open_parentheses = {"(", "{", "["} + close_parentheses = {")", "}", "]"} + open_parentheses_stack = [] + + open_to_close = { + "(": ")", + "{": "}", + "[": "]", + } + + for char in s: + if char in open_parentheses: + open_parentheses_stack.append(char) + elif char in close_parentheses: + if not open_parentheses_stack: + return False + if open_to_close[open_parentheses_stack[-1]] != char: + return False + open_parentheses_stack.pop() + else: + raise ValueError("Invalid input: only parentheses are allowed") + + return not open_parentheses_stack + + +# @lc code=end diff --git a/problems/20.valid-parentheses/step3.py b/problems/20.valid-parentheses/step3.py new file mode 100644 index 0000000..3f65bff --- /dev/null +++ b/problems/20.valid-parentheses/step3.py @@ -0,0 +1,35 @@ +# +# @lc app=leetcode id=20 lang=python3 +# +# [20] Valid Parentheses +# + +# @lc code=start +class Solution: + def isValid(self, s: str) -> bool: + open_parentheses = {"(", "{", "["} + close_parentheses = {")", "}", "]"} + open_parentheses_stack = [] + + open_to_close = { + "(": ")", + "{": "}", + "[": "]", + } + + for char in s: + if char in open_parentheses: + open_parentheses_stack.append(char) + elif char in close_parentheses: + if not open_parentheses_stack: + return False + if open_to_close[open_parentheses_stack[-1]] != char: + return False + open_parentheses_stack.pop() + else: + raise ValueError("Invalid input: only parentheses are allowed") + + return not open_parentheses_stack + + +# @lc code=end