-
Notifications
You must be signed in to change notification settings - Fork 0
Create 20.md #6
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
Create 20.md #6
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,111 @@ | ||
| # 1st | ||
| - 前提: Arai60は一度一周しているが、期間をあけてなるべく忘れて取り組む(linkedList の方で思い出しながらと書きましたが、なるべく初見の状態で、どれだけやれるようになったかみていきたい) | ||
| - 問題: [20. Valid Parentheses](https://leetcode.com/problems/valid-parentheses/description/) | ||
| - コメント集: [20. Valid Parentheses](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.ns0bie22a6m) | ||
| - 引数に想定外がきた時はどうする?が気になったので実装に含めてみました | ||
| - 引数に対して、想定しない値がの場合は `IllegalArgumentException` を投げるようにしました | ||
| - が、コンパイルとか Linter のことを考えると、`(ai){ueo}` みたいなのが来たときは continue とかの方が良いのかもと思ったりしたので別解として載せました | ||
| - 所感 | ||
| - コンパイル、 Linter で高速に動いてくれないと困るよなと思いました | ||
|
|
||
| ### 実装 | ||
| - 時間計算量: O(N) --> 引数 s を全て走査するから | ||
| - 空間計算量: O(N) --> open の記号だけ Stack につめる、最悪全て open 記号だから | ||
| - 回答時間: 無制限(コメントをちゃんと読んでみたり、変数名の命名にこだわったりしてみました) | ||
|
|
||
| ```java | ||
| class Solution { | ||
| private static final Map<Character, Character> validParentheses = Map.of( | ||
| '(', ')', | ||
| '[', ']', | ||
| '{', '}' | ||
| ); | ||
|
|
||
| public boolean isValid(String s) { | ||
| Deque<Character> openSymbols = new ArrayDeque<>(); | ||
| for (int i = 0; i < s.length(); i++) { | ||
| char symbol = s.charAt(i); | ||
|
|
||
| if (isIllegalSymbol(symbol)) { | ||
| throw new IllegalArgumentException("Invalid Character is detected, symbol is " + symbol); | ||
|
Comment on lines
+29
to
+30
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. この設計の場合、入力文字列の長さが奇数なら即falseとかもできますよね。 |
||
| } | ||
|
|
||
| if (isOpenSymbol(symbol)) { | ||
| openSymbols.push(symbol); | ||
|
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. この分岐に入った場合、後続の処理がないのであれば
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. なるほどなと思いました。 |
||
| } else { | ||
| if (openSymbols.empty()) { | ||
| return false; | ||
| } | ||
| char peekedOpenSymbol = openSymbols.peek(); | ||
|
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. この時点でpop()してもいいかなと思います。 char peekedOpenSymbol = openSymbols.pop();
if (!isMatched(symbol, peekedOpenSymbol)) {
return false;
}
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. そうですね、手作業をコードに落とした結果 peek してから pop してますが、そちらでも良いと思います。 |
||
| if (isMatched(symbol, peekedOpenSymbol)) { | ||
| openSymbols.pop(); | ||
| } else { | ||
| // 合致しない時点で false | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return openSymbols.empty(); | ||
| } | ||
|
|
||
| private boolean isIllegalSymbol(char symbol) { | ||
| return !validParentheses.containsKey(symbol) && !validParentheses.containsValue(symbol); | ||
| } | ||
|
|
||
| private boolean isOpenSymbol(char symbol) { | ||
| return validParentheses.containsKey(symbol); | ||
| } | ||
|
|
||
| private boolean isMatched(char symbol, char peekedOpenSymbol) { | ||
| return validParentheses.get(peekedOpenSymbol) == symbol; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| - 別解 | ||
| - `isIllegalSymbol()` を削除し、引数として妥当でない場合は `continue` する方針にしました | ||
| - コンパイラとか Linter でこんな処理が動いているんだろうなで書きました | ||
| ```java | ||
| class Solution { | ||
| private static final Map<Character, Character> validParentheses = Map.of( | ||
| '(', ')', | ||
| '[', ']', | ||
| '{', '}' | ||
| ); | ||
|
|
||
| public boolean isValid(String s) { | ||
| Deque<Character> openSymbols = new ArrayDeque<>(); | ||
| for (int i = 0; i < s.length(); i++) { | ||
| char symbol = s.charAt(i); | ||
|
|
||
| if (isOpenSymbol(symbol)) { | ||
| openSymbols.push(symbol); | ||
| } else if (isCloseSymbol(symbol)) { | ||
| if (openSymbols.empty()) { | ||
| return false; | ||
| } | ||
| char peekedOpenSymbol = openSymbols.peek(); | ||
| if (isMatched(symbol, peekedOpenSymbol)) { | ||
| openSymbols.pop(); | ||
| } else { | ||
| // 合致しない時点で false | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return openSymbols.empty(); | ||
| } | ||
|
|
||
| private boolean isOpenSymbol(char symbol) { | ||
| return validParentheses.containsKey(symbol); | ||
| } | ||
|
|
||
| private boolean isCloseSymbol(char symbol) { | ||
| return validParentheses.containsValue(symbol); | ||
|
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. containtsKeyはkeyがhashtableを構築しているのでO(1)で存在確認できますが、containsValueはvalueがhashtableを持っておらず、存在確認のたびに配列を線形探査するのでカッコの種類をmとしてO(m)になります。 閉じカッコの存在確認が必要な場合には、Set closeSymbols = Set.of(')', ']', '}');を追加した方が良いと思います。 class Solution {
private static final Map<Character, Character> VALID_PARENTHESES = Map.of(
'(', ')',
'[', ']',
'{', '}'
);
private static final Set<Character> CLOSE_SYMBOLS = Set.copyOf(VALID_PARENTHESES.values());(インスタンス状態に依存しない定数なのでstatic finalでしょうか)
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. そうですね、とはいえ3種類しかないので今回はいいかなあと思ってます。 static final はその通りです。 |
||
| } | ||
|
|
||
| private boolean isMatched(char symbol, char peekedOpenSymbol) { | ||
| return validParentheses.get(peekedOpenSymbol) == symbol; | ||
| } | ||
| } | ||
| ``` | ||
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.
ユースケースをイメージされていて素晴らしいですね。同意です。