Skip to content
Merged
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
38 changes: 38 additions & 0 deletions 20. Valid Parentheses/FirstSolution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
public class FirstSolution {
public boolean isValid(String s) {
Stack<Character> openCharacters = new Stack<>();
char[] cs = s.toCharArray();
for (char current : cs) {
if (openCharacters.isEmpty() || isOpenCharacter(current)) {
openCharacters.push(current);
} else if (isPair(openCharacters.peek(), current)) {
openCharacters.pop();
} else {
return false;
}
}
return openCharacters.isEmpty();
}

private boolean isOpenCharacter(char c) {
return c == '(' || c == '{' || c == '[';
}

private boolean isPair(char left, char right) {
boolean result;
switch (left) {
case '(':
result = right == ')';
break;
case '{':
result = right == '}';
break;
case '[':
result = right == ']';
break;
default:
result = false;
}
return result;
}
}
19 changes: 19 additions & 0 deletions 20. Valid Parentheses/SecondSolution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
public class SecondSolution {
public boolean isValid(String s) {
Stack<Character> buckets = new Stack<>();
Map<Character, Character> bucketPairs = new HashMap<>();
bucketPairs.put('(', ')');
bucketPairs.put('{', '}');
bucketPairs.put('[', ']');

char[] cs = s.toCharArray();
for (char current : cs) {
if (bucketPairs.containsKey(current)) {
buckets.push(current);
} else if (buckets.isEmpty() || current != bucketPairs.get(buckets.pop())) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

私はこの文長いと思います。

いろいろな選択肢が見えて書いているかが気になるところです。

この問題に関する記述が Discord サーバー内にあるはずなので調べておいてください。

Copy link
Copy Markdown
Owner Author

@ryoooooory ryoooooory Jun 17, 2024

Choose a reason for hiding this comment

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

リンク
などを参考に連想される知識および、ループないでの処理の書き方のバリデーションについてnote.mdやThirdSolution.javaに記載しました!

return false;
}
}
return buckets.isEmpty();
}
}
39 changes: 39 additions & 0 deletions 20. Valid Parentheses/ThirdSolution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
public class ThirdSolution {
public boolean isValid(String s) {
Stack<Character> buckets = new Stack<>();
Map<Character, Character> bucketPairs = Map.of('(', ')', '{', '}', '[', ']');
char[] cs = s.toCharArray();
for (char current : cs) {
if (bucketPairs.containsKey(current)) {
buckets.push(current);
} else if (buckets.isEmpty()) {
return false;
} else if (current != bucketPairs.get(buckets.peek())) {
return false;
} else {
buckets.pop();
}
}
return buckets.isEmpty();
}

public boolean isValid(String s) {
Stack<Character> buckets = new Stack<>();
Map<Character, Character> bucketPairs = Map.of('(', ')', '{', '}', '[', ']');
char[] cs = s.toCharArray();
for (char current : cs) {
if (bucketPairs.containsKey(current)) {
buckets.push(current);
continue;
}
if (buckets.isEmpty()) {
return false;
}
char closeBucket = buckets.pop();
if (current != bucketPairs.get(closeBucket)) {
return false;
}
}
return buckets.isEmpty();
}
}
44 changes: 44 additions & 0 deletions 20. Valid Parentheses/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# FirstSolution

解法と計算量はすぐに浮かんだが、java の switch 文の使い方に慣れていなかったので、実装に時間がかかった。
普段使う言語と違って、break をいれないと次の case に進んでしまうので、気をつける必要がある。
基本的な解法は、左括弧だったら Stack にいれる。右括弧だったら、Stack から取り出して、対応する括弧かどうかを判定するという方針。
最後に Stack が空かどうかを判定することで、全ての括弧が対応しているかどうかを判定する。
少しの改善策としては、index を使って途中でも、残りの文字数が stack のサイズを超える場合は、すぐに false を返すようにすることで、計算量を減らすことができる。

# SecondSolution

https://github.com/kazukiii/leetcode/pull/7/files
を参考に、あらかじめ括弧のペアを持っておくき、それを使って判定をする解法にした。
かなりコード量もへり可読性も高くなったのでこちらの解法の方がよいと感じた。
解法作成後に以下の解法ももみつけて考え方が近かったが、主な違いとして括弧ペアの判定のところで変数をつくつかどうかがあった。好みももあるが自分はこれくらいの処理なら変数を作らなくてもいいと思った。
https://github.com/seal-azarashi/leetcode/pull/6/files
以下の解法は大体一緒だった
https://github.com/kagetora0924/leetcode-grind/pull/8/files

# ThirdSolution

指摘いただいて、Discord 内にある以下のリンクを参考に、知識を整理しました!
https://discord.com/channels/1084280443945353267/1201211204547383386/1202541275115425822

## 知識

連想されるものとしてはチョムスキー階層、タイプ-2、文脈自由文法だから、プッシュダウンオートマトンで書けるということらしく、各々について調べてみました!
・チョムスキー階層: 形式文法の包含階層。文脈自由文法、文脈依存文法、正規文法、正則文法の4つの階層に分けることができる
・タイプ-2: 文脈自由文法。文脈自由文法は、生成規則が「非終端記号から始まる任意の文字列を、非終端記号に置き換える」という形をとる文法
・オートマトン: 入力を受け取って、ある規則に従って状態を遷移させる機械。有限オートマトン、プッシュダウンオートマトン、チューリングマシンなどがある。
・プッシュダウンオートマトン: スタックを持つオートマトン。スタックを使って、文脈自由文法で表現される言語を認識することができる。
・有限オートマトン: 有限個の状態を持つオートマトン。正規言語を認識することができる。
・正規言語: 正規表現で表現される言語。正規表現は、文字列のパターンを表すための記法。

## 考え方

今回の問題では入力が括弧を含む文字列で非終端記号、終端記号をもつ文脈自由文法で表現される言語であると考えられる。なので、プッシュダウンオートマトン(Stack をつかって)で解くことができると考えられる。

## 蛇足

・オートマトン理論の起源は 20 世紀初頭に遡ることができ、アラン・チューリングが 1936 年に提案したチューリングマシンがその始まり。抽象機械なのでふつうは問題解決の枠組みで使われる。

## 解法
SecondSolution をベースに、Map での bucket 入力の簡略記法および、条件式の変更をしました。
少し違うものとして、早期 continue での処理のタイプの解法も追加しました。