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
57 changes: 57 additions & 0 deletions 20_ValidParentheses/20_ValidParentheses.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// data_structures

// Step1
#include <stack>
#include <iostream>

class Solution {
public:
bool isValid(std::string s) {
std::stack<char> st;

for (char c : s) {
if (c == '(' || c == '{' || c == '[') {
st.push(c);
continue;
} else if ((c == ')' || c == '}' || c == ']') && !st.empty()) {
const char top = st.top();
if ((top == '(' && c == ')') || (top == '{' && c == '}') || (top == '[' && c == ']')) {
st.pop();
continue;
}
}
return false;
}
return st.empty();
}
};

// Step2
#include <stack>
#include <iostream>
#include <unordered_map>

class Solution {
public:
bool isValid(std::string s) {
std::stack<char> st;

std::unordered_map<char, char> match = {
{'(', ')'},
{'{', '}'},
{'[', ']'}
};

for (char c : s) {
if (match.count(c)) {
st.push(c);
continue;
} else if (!st.empty() && match[st.top()] == c ) {
st.pop();
continue;
}
Comment on lines +46 to +52
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

resumit30minutes/leetcode-arai60-practice#7 (comment)
問題上起こりえないですが、こちらのディスカッションでは意図しない文字が入ってきた場合はどうするか?ということが議論されておりました。
今回のコードではFalseを返すと思っており、私もFalseを返すorエラーを吐くのが良いのでは?と思っているのですが、そうではないと考える方もおり、多角的な意見が学べたので紹介します。

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.

ありがとうございます。
第一義的にはerrを返して終了すべきだと考えます(今回の場合はfalse返すしかないですが)。
PythonもC++も、普通にアクセスしてしまうと新しくkeyが作成されてしまうと認識しているので、事前にその要素があるか、cppなら.count()、pythonなら"key" in D等でチェックするのが安全な設計をするなら望ましいとも思います。

return false;
}
return st.empty();
}
};
96 changes: 96 additions & 0 deletions 20_ValidParentheses/20_ValidParentheses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# 20. Valid Parentheses
- 問題文: [20. Valid Parentheses](https://leetcode.com/problems/valid-parentheses/description/)
- 使用言語: C++
- 次に解く問題: [206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/description/)

## 知識セット
### 知っていたこと
- stackというデータ構造

### 今回調べたこと
- std::stackの使い方
- メソッド:
- push: スタックに追加
- top: 一番上の値を返す
- pop: 一番上の値を削除(返り値は無し)
- empty: 空ならtrue, 入っていたらfalse
- size: sizeを返す
- 範囲for文の使い方
- std::unordered_mapの使い方

## Step1
- 所要時間: 10min.
- 方針:
- 愚直にstackに積んでいって、対応しているかチェック
- コード
```cpp
#include <stack>
#include <iostream>

class Solution {
public:
bool isValid(std::string s) {
std::stack<char> st;

for (char c : s) {
if (c == '(' || c == '{' || c == '[') {
st.push(c);
continue;
} else if ((c == ')' || c == '}' || c == ']') && !st.empty()) {
const char top = st.top();
if ((top == '(' && c == ')') || (top == '{' && c == '}') || (top == '[' && c == ']')) {
st.pop();
continue;
}
}
return false;
}
return st.empty();
}
};
```
- 計算量
- 時間計算量: O(N)
- 空間計算量: O(N)

## Step2
- 所要時間: 20min.
- 方針:
- 辞書を使って条件文を簡単に
- ネストを減らす
- コード
```cpp
#include <stack>
#include <iostream>
#include <unordered_map>

class Solution {
public:
bool isValid(std::string s) {
std::stack<char> st;

std::unordered_map<char, char> match = {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

現状のままでもそんなにわかりづらくはないですが、自分であれば matched_parentheses ないし open_to_close とするかなと思います。

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.

確かに、結局何が入っているのか変数名から理解できないですね。ご指摘ありがとうございます。

{'(', ')'},
{'{', '}'},
{'[', ']'}
};

for (char c : s) {
if (match.count(c)) {
st.push(c);
continue;
} else if (!st.empty() && match[st.top()] == c ) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

私はここ else 消します。上が continue なので。
また、条件はひっくり返して、return false; を中にいれます。
いずれも趣味の範囲です。

まあ、あとは、この問題はプッシュダウンオートマトンを連想するので、一応それは確認してみてください。たぶん、完走した人とかを調べると誰かよくまとめているでしょう。「in: レビュー依頼 55」あたりで検索すると完走した人たちが出てきます。

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.

continueの後のelseを残すかは悩みどころでした。可読性の面からつけたほうがいいかなと思っていましたが、むしろコード量が増えてしまうので避けても良さそうです。個人的にもシンプルなほうが好きなので次回からはそうしようと思います。
正常系・異常系のどちらかをifブロックに入れるなら異常系とも思います。こちらも意識します。

プッシュダウンオートマトン(というよりオートマトンという概念自体)については存じ上げなかったのですが、幸いBNFに基づいた再帰下降構文解析は書いたことがあるので、この問題でも実装してみます。

st.pop();
continue;
}
return false;
}
return st.empty();
}
};
```
- 計算量
- 時間計算量: O(N)
- dictの分は高々定数倍
- 空間計算量: O(N)
- dictの文が追加されたとて