問題
( ) [ ] { } の 6 つのs をtrue、false を
- 対応が
正しいとは、 どの 閉じかっこも、 同じ 種類で、 まだ 閉じていない 一番新しい 開きかっこを 閉じていることです - 最後には、
開いたままのかっこが 残っていてはいけません - 空の
文字列は、 対応が 正しい ものとして trueを返します sの長さは 0 以上 10000 以下です
入力と出力の例
例 1
入れ子に
入力
s = "{[()]}()"出力
true例 2
数は
入力
s = "([)]"出力
false例 3
開いたままのかっこが
入力
s = "[{}"出力
false面接での聞かれ方
面接では、
- 「かっこだけの
文字列が あります。 正しく 閉じているか 判定してください」 - 最初は
()の 1 種類だけで出され、 解けたら 「では 3 種類なら?」と 広げられる ことがあります - 「空の
文字列は どう 扱いますか?」と、 端の 場合を 聞かれる こともあります
かっこ以外の
まず 考える手順
段 1
まずは 1 種類だけの
段 2
3 種類に([)] は、
段 3
閉じて
段 4
正しくないfalse です。
ここから解答です。先に自分で書いてから読むと、考え方が残ります。
解答
Python
Python
def valid_brackets(s):
pairs = {
")": "(",
"]": "[",
"}": "{",
}
stack = []
for ch in s:
if ch in pairs:
if not stack:
return False
top = stack.pop()
if top != pairs[ch]:
return False
else:
stack.append(ch)
return not stackJavaScript
JavaScript
function validBrackets(s) {
const pairs = {
")": "(",
"]": "[",
"}": "{",
};
const stack = [];
for (const ch of s) {
if (ch in pairs) {
if (stack.length === 0) {
return false;
}
const top = stack.pop();
if (top !== pairs[ch]) {
return false;
}
} else {
stack.push(ch);
}
}
return stack.length === 0;
}辞書は
計算量
- 時間は O(n) です。
文字列を 前から 1 回なめ、 積むのも 取り出すのも 一定の手間です - 使う
記憶は O(n) です。 開きかっこだけが 続くと、 全部を スタックに積みます - 段 1 の
数を 数える 書き方は 記憶が O(1) ですが、 3 種類のかっこには 使えません
よく ある間違い
- 種類ごとに
数を 数えるだけで 済ませる。 例 2 の ([)]を正しいと 答えてしまいます。 順を 見るには スタックが要ります - 空の
スタックから 取り出す。 ")"のように閉じかっこから 始まる 文字列で、 Python は 例外で 止まります。 JavaScript は undefinedが返り、 気づきにくい間違いに なります。 取り出す 前に 空か どうかを調べます - 最後の
残りを 調べ忘れる。 例 3 の [{}は、途中では 一度も 食い 違いません。 最後に スタックが 空か どうかで 決まります
面接での 話し方の例
書き始める
「1 種類なら数を
数えれば 済みますが、 3 種類あると 閉じる 順も 見る 必要が あります。 閉じて よいのは 一番新しく 開いたかっこなので、 スタックに 積んで おき、 閉じかっこが 来たら 一番上と 照らします。 時間も 記憶も O(n) です。」
書き終えたら、
「例 2 の
([)]でたどります。 (と[を積みます。 次の )で一番上を 取り出すと [なので、種類が 合わず、 ここで false を 返します。 数を 数えるだけでは 見落とす場合です。」
