-
Notifications
You must be signed in to change notification settings - Fork 0
20. Valid Parentheses #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| #if __has_include("../../debug.hpp") | ||
| #include "../../debug.hpp" | ||
| #endif | ||
| // ここまでローカルでのデバッグ用なので気にしないでください -------------------- | ||
|
|
||
| #include <map> | ||
|
|
||
| using namespace std; | ||
|
|
||
| // <時間> | ||
| // 10分 | ||
| // <感想> | ||
| // これ正直10分じゃ無理だろ、と思っていたが意外と書けて嬉しい。 | ||
| // 最初の方でどうするのがいいか少し時間を取って考えた。 | ||
| // 最初に思い付いたのがpre変数を用意して、 | ||
| // ひとつ前の文字に対応する括弧のみ受けつけ続けるみたいな(結局うまく行かなそう)。 | ||
| // そっから何かの拍子にstackを使うことを思いつき、 | ||
| // 途中でclosing_to_openingが必要になり | ||
| // switchで書いていたロジックをclosing_to_openingを使った | ||
| // ifに書き換えるという流れ | ||
| // <疑問・不安点(・個人的な感想、違う意見があれば教えてほしいもの)> | ||
| // - L49を空けるか否か | ||
| // - closing_to_openingとopening_bracketsのどちらを先に宣言するか | ||
| // (細かいけど...) | ||
| // <他の人のを見てコメント> | ||
| // - なるほど。そういえばValid ParenthesesもCSZAPで触れていたかもしれない。 | ||
| // https://discord.com/channels/1084280443945353267/1201211204547383386/1202541275115425822 | ||
| // - そうか、closing_to_openingじゃなくてもopening_to_closingでもよかったのか… | ||
| // うーん、でもその場合2回map::findすることになるな | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 直感、あんまり速度が問題にならないと思うので、私はこれは気にしません。 ボトルネックでないところを最適化しない話がこのあたりに。 |
||
| // - stackに番兵を入れてstack::emptyを呼び出さなくていいようにしている | ||
| // ものがあった。頭いい。 | ||
| // - closing_to_opening定数だからスネークケースじゃなかったわ。 | ||
| // | ||
| // | ||
| // | ||
| // | ||
| // | ||
| // | ||
| // | ||
| // L40(行数調整用コメント) | ||
| class Solution { | ||
| public: | ||
| bool isValid(string s) { | ||
| static const map<char, char> closing_to_opening{ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 関数内で static 変数を定義した場合、最初に関数が呼ばれたときに初期化されます。その際、競合状態を防ぐためにロックが取られます。結果、関数の呼び出し毎にロックが取られ、パフォーマンスが低下する場合があります。原則、関数の外で定義することをお勧めします。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. static 変数のロックは C++11 からそうなっているんですね。 |
||
| {')', '('}, | ||
| {'}', '{'}, | ||
| {']', '['}, | ||
| }; | ||
|
|
||
| stack<char> opening_brackets; | ||
| for (auto c : s) { | ||
| if (auto it = closing_to_opening.find(c); | ||
| it != closing_to_opening.end()) { | ||
| auto opening = it->second; | ||
| if (!opening_brackets.empty() && opening_brackets.top() == opening) { | ||
| opening_brackets.pop(); | ||
| } else { | ||
| return false; | ||
| } | ||
| } else { | ||
| opening_brackets.push(c); | ||
| } | ||
|
Comment on lines
+52
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if else のネストが分かりにくいと私は思います。このあたりをざっと見ておくといいかもしれません。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. auto itを同じブロックで処理することに気を取られてましたが別に条件式外にすればネストを解消できましたね... |
||
| } | ||
| return opening_brackets.empty(); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| #if __has_include("../../debug.hpp") | ||
| #include "../../debug.hpp" | ||
| #endif | ||
| // ここまでローカルでのデバッグ用なので気にしないでください -------------------- | ||
|
|
||
| #include <map> | ||
|
|
||
| using namespace std; | ||
|
|
||
| // <時間> | ||
| // 5分 | ||
| // <感想> | ||
| class Solution { | ||
| public: | ||
| bool isValid(const string &brackets) { | ||
| static const map<char, char> kClosingToOpening{ | ||
| {')', '('}, | ||
| {'}', '{'}, | ||
| {']', '['}, | ||
| }; | ||
| stack<char> opening_brackets; | ||
| opening_brackets.push('*'); // sentinel | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. '*' 提案したのは自分な気がしますが、'\0' あたりのほうが自然かもしれません。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 確かに'\0'いいですね!ありがとうございます! |
||
| for (auto bracket : brackets) { | ||
| if (auto it = kClosingToOpening.find(bracket); | ||
| it != kClosingToOpening.end()) { | ||
| auto opening = it->second; | ||
| if (opening_brackets.top() != opening) return false; | ||
| opening_brackets.pop(); | ||
| } else { | ||
| opening_brackets.push(bracket); | ||
| } | ||
| } | ||
| return opening_brackets.size() == 1; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| #if __has_include("../../debug.hpp") | ||
| #include "../../debug.hpp" | ||
| #endif | ||
| // ここまでローカルでのデバッグ用なので気にしないでください -------------------- | ||
|
|
||
| #include <map> | ||
| #include <stack> | ||
| #include <string> | ||
|
|
||
| using namespace std; | ||
|
|
||
| // <時間> | ||
| // 15分 | ||
| // <コメント> | ||
| // - corresponding_bracketとopen_bracketは最初逆に名前を付けていた。 | ||
| // - corresponding_bracketは最初corresponding_open_bracketとしていたが、 | ||
| // openはなくても伝わると思い消した。 | ||
| // - だが、読む側に取ってどう見えるかは分からない。 | ||
| // - correspondingみたいな意味の名前は付けることが多いと思うが、 | ||
| // もっと短めの単語はないものか。 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 他の候補として、私は pair や match を連想しました。 |
||
| class Solution { | ||
| public: | ||
| bool isValid(const string &brackets) { | ||
| static const map<char, char> kCloseToOpen{ | ||
| {')', '('}, | ||
| {'}', '{'}, | ||
| {']', '['}, | ||
| }; | ||
| stack<char> open_brackets; | ||
| open_brackets.push('\0'); | ||
| for (auto bracket : brackets) { | ||
| // In the case `bracket` is an open bracket. | ||
| auto close_and_open = kCloseToOpen.find(bracket); | ||
| if (close_and_open == kCloseToOpen.end()) { | ||
| open_brackets.push(bracket); | ||
| continue; | ||
| } | ||
|
|
||
| // In the case `bracket` is a close bracket. | ||
| auto open_bracket = close_and_open->second; | ||
| auto corresponding_bracket = open_brackets.top(); | ||
| open_brackets.pop(); | ||
| if (corresponding_bracket != open_bracket) { | ||
| return false; | ||
| } | ||
| } | ||
| return open_brackets.size() == 1; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| #if __has_include("../../debug.hpp") | ||
| #include "../../debug.hpp" | ||
| #endif | ||
| // ここまでローカルでのデバッグ用なので気にしないでください -------------------- | ||
|
|
||
| #include <map> | ||
| #include <stack> | ||
| #include <string> | ||
|
|
||
| using namespace std; | ||
|
|
||
| // <時間> | ||
| // 10分 | ||
| // <感想> | ||
| // 多分3.cppよりこっちの方が読みやすい。 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 同感です。OpenToCloseに入っているかを調べる方が直感的だと思いました。 |
||
| // <コメント> | ||
| // - auto open_bracket = open_brackets.top(); | ||
| // で新しく変数を作ろうかとも思ったが、無駄に変数が多くても | ||
| // 読みづらいかなと思い作らないことにした。 | ||
| class Solution { | ||
| public: | ||
| bool isValid(const string &brackets) { | ||
| static const map<char, char> kOpenToClose{ | ||
| {'(', ')'}, | ||
| {'{', '}'}, | ||
| {'[', ']'}, | ||
| }; | ||
| stack<char> open_brackets; | ||
| for (auto bracket : brackets) { | ||
| // In the case `bracket` is an open bracket. | ||
| if (kOpenToClose.contains(bracket)) { | ||
| open_brackets.push(bracket); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これは好みかなと思いますが、わかりやすさ(正しさの保証)でいうと、 ただ、エラーケースの計算量がちょっと減るので、シビアな計算のことを考えるならば計算をなるべくあとに回す習慣でも良いかもしれません。 |
||
| continue; | ||
| } | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 私の好みとなり恐縮ですが、コメントを残されているので、この空白行はなくても読みやすく感じました。 |
||
| // In the case `bracket` is a close bracket. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. この問題の前提となる入力の場合はここのコメント通りなんですが、他の文字が入った場合の関数の挙動としては厳密には違うので、入力に対する前提知識がないと微妙に誤った理解を与えるかもしれません。 |
||
| if (open_brackets.empty()) { | ||
| return false; | ||
| } | ||
| auto close_bracket = kOpenToClose.at(open_brackets.top()); | ||
| open_brackets.pop(); | ||
| if (bracket != close_bracket) { | ||
| return false; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
if (bracket != kOpenToClose.at(open_brackets.top())) {としても十分わかりやすいと思います。 |
||
| } | ||
| return open_brackets.empty(); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # 20. Valid Parentheses | ||
|
|
||
| <https://leetcode.com/problems/valid-parentheses/description/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この辺はどちらでも。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ありがとうございます!
なんか今更なんですが、色々こうやってレビューもらっているうちに、プログラミングの可読性の面は言語ゲームなんじゃないかと思い始めてきました。
またなんかすごいブレークスルーした気がします。