Skip to content

Create 20.md#6

Merged
hiroki-horiguchi-dev merged 3 commits intomainfrom
stack_20
Oct 20, 2025
Merged

Create 20.md#6
hiroki-horiguchi-dev merged 3 commits intomainfrom
stack_20

Conversation

@hiroki-horiguchi-dev
Copy link
Owner

レビューお願いします!

@hiroki-horiguchi-dev hiroki-horiguchi-dev self-assigned this Oct 12, 2025
@hiroki-horiguchi-dev
Copy link
Owner Author

すみません、leetcode から貼り付けるとインデントが2つになるみたいなので4つに調整します。

@hiroki-horiguchi-dev
Copy link
Owner Author

調整しましたのでレビューお願いします

}

private boolean isCloseSymbol(char symbol) {
return validParentheses.containsValue(symbol);

Choose a reason for hiding this comment

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

お疲れ様です。
指摘するところがなく重箱の隅をつつくような指摘となってしまいますが、
Map.containsValue()は値を順番に走査するO(n)なので、
パフォーマンスの観点ではO(1)のSet.contains()を使った方が良いかもしれません。
※今回の場合、括弧の種類が3つだけなので、そんなに大きな差にならないとは思いますが。

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます、おっしゃる通りかと思います。
修正します。

Copy link

@naoto-iwase naoto-iwase left a comment

Choose a reason for hiding this comment

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

お疲れさまです。
いくつかコメントさせていただきました。
自分がjavaあまり詳しくないので、話半分で見ていただけたらと思います。

);

public boolean isValid(String s) {
Stack<Character> openSymbols = new Stack<>();

Choose a reason for hiding this comment

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

https://docs.oracle.com/javase/jp/8/docs/api/java/util/Stack.html

より完全で一貫性のある一連のLIFOスタック・オペレーションが、Dequeインタフェースとその実装によって提供されています。このクラスよりもそれらを優先的に使用するようにしてください。 たとえば、
Deque<Integer> stack = new ArrayDeque<Integer>();

Choose a reason for hiding this comment

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

スタックデータ構造であれば、 Stack より ArrayDeque を優先的に使用することがおすすめです。
Stackはスレッドセーフな実装になっており、低速なためです。

https://docs.oracle.com/javase/jp/8/docs/api/java/util/ArrayDeque.html

このクラスは通常、スタックとして使われるときはStackよりも高速で、キューとして使われるときはLinkedListよりも高速です。

yamashita-ki/codingTest#7 (comment)

Copy link
Owner Author

Choose a reason for hiding this comment

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

お二人ともありがとうございます、 Deque を使おうと思います。
マルチスレッド等で共有スタックとして使うなら Stack は便利そうですね

}

private boolean isCloseSymbol(char symbol) {
return validParentheses.containsValue(symbol);
Copy link

@naoto-iwase naoto-iwase Oct 12, 2025

Choose a reason for hiding this comment

The 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でしょうか)

Copy link
Owner Author

Choose a reason for hiding this comment

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

そうですね、とはいえ3種類しかないので今回はいいかなあと思ってます。

static final はその通りです。

- コメント集: [20. Valid Parentheses](https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.ns0bie22a6m)
- 引数に想定外がきた時はどうする?が気になったので実装に含めてみました
- 引数に対して、想定しない値がの場合は `IllegalArgumentException` を投げるようにしました
- が、コンパイルとか Linter のことを考えると、`(ai){ueo}` みたいなのが来たときは continue とかの方が良いのかもと思ったりしたので別解として載せました

Choose a reason for hiding this comment

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

ユースケースをイメージされていて素晴らしいですね。同意です。

Comment on lines +29 to +30
if (isIllegalSymbol(symbol)) {
throw new IllegalArgumentException("Invalid Character is detected, symbol is " + symbol);

Choose a reason for hiding this comment

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

この設計の場合、入力文字列の長さが奇数なら即falseとかもできますよね。

@TrsmYsk
Copy link

TrsmYsk commented Oct 12, 2025

自分も今この問題やっているのでコード拝見しました。コンパイラやlinterなど実際のユースケースを想定して例外処理などを考えている点が素晴らしいと思いました。

}

if (isOpenSymbol(symbol)) {
openSymbols.push(symbol);

Choose a reason for hiding this comment

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

この分岐に入った場合、後続の処理がないのであればcontinue;してelse節のインデントも下げてあげたほうが読みやすくなると思います。

Copy link
Owner Author

Choose a reason for hiding this comment

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

なるほどなと思いました。
continue してあげた方が読みやすいか、確かに。。

if (openSymbols.empty()) {
return false;
}
char peekedOpenSymbol = openSymbols.peek();

Choose a reason for hiding this comment

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

この時点でpop()してもいいかなと思います。

char peekedOpenSymbol = openSymbols.pop();
if (!isMatched(symbol, peekedOpenSymbol)) {
    return false;
}

Copy link
Owner Author

Choose a reason for hiding this comment

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

そうですね、手作業をコードに落とした結果 peek してから pop してますが、そちらでも良いと思います。


```java
class Solution {
private final Map<Character, Character> validParentheses = Map.of(
Copy link

Choose a reason for hiding this comment

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

定数相当ですので、 private static final のほうが良いかなと思いました。

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます、おっしゃる通りです。

@hiroki-horiguchi-dev hiroki-horiguchi-dev merged commit f1c63ef into main Oct 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants