数の 幅を 持ち歩いて 星入りの 括弧を判定する
開きかっこ、
海外で定番の問題リスト 4 本には入っていません
問題
( と ) と * の 3 つのs を* は、(、)、* をtrue、false を
- 対応が
正しいとは、 どの )も、それより 前に あるまだ 閉じていない (を 1 つ閉じていて、 最後に 閉じていない (が残っていないことです *はそれぞれ別々に 置き換え方を選べます - 空の
文字列は、 対応が 正しい ものと見ます sの長さは 1 以上 100 以下です
入力と出力の例
例 1
2 文字目の * を ) に()() に
例 2
* を ( に
例 3
開きかっこが 2 つ* の 1 つだけです。
面接での聞かれ方
面接では、
- 「かっこの
文字列に、 どれに でもなれる 文字が 混ざっています。 正しい 並びに できますか」 - 最初に
スタックを 2 つ 使う 書き方や、 動的計画法で 書き、 「記憶を O(1) に できますか」と 聞かれる 流れもあります - 「
*は空にもなれますか」と 聞くと、 「なれます」と 返ってくるのが ふつうです
* が
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
素直に* ごとに 3 通りの* が k 個あると 3 の k 乗通り
段 2
* が( で 1 足し、) で 1 引けば* が( なら幅の) なら* なら
段 3
開いたままのlo とhi をhi が* を( にfalse です。lo はlo が 0 なら、true です。
解答
Python
Python
def star_brackets(s):
lo = 0
hi = 0
for ch in s:
if ch == "(":
lo += 1
hi += 1
elif ch == ")":
lo -= 1
hi -= 1
else:
lo -= 1
hi += 1
if hi < 0:
return False
lo = max(lo, 0)
return lo == 0JavaScript
JavaScript
function starBrackets(s) {
let lo = 0;
let hi = 0;
for (const ch of s) {
if (ch === "(") {
lo++;
hi++;
} else if (ch === ")") {
lo--;
hi--;
} else {
lo--;
hi++;
}
if (hi < 0) {
return false;
}
lo = Math.max(lo, 0);
}
return lo === 0;
}Go
Go
func starBrackets(s string) bool {
lo, hi := 0, 0
for _, ch := range s {
switch ch {
case '(':
lo++
hi++
case ')':
lo--
hi--
default:
lo--
hi++
}
if hi < 0 {
return false
}
lo = max(lo, 0)
}
return lo == 0
}hi がlo を 0 にhi は lo より
計算量
- 時間は O(n) です。
文字列を 前から 1 回なめ、 1 文字ごとの 手間は一定です - 使う
記憶は O(1) です。 持つのは loとhiの 2 つだけです (の位置と *の位置を 2 つの スタックに 積む 書き方も O(n) ですが、 記憶が O(n) 要ります
よく ある間違い
loを 0 に戻さない。 "(*)("では、3 文字目の )でloが -1 になり、 最後の (で 0 に上がって trueを返します。 最後の (は閉じられないので、 本当は falseです。負に なる 選び方は 捨てて 0 に戻します - 最後に
hiが 0 かを見る。 例 1 の最後は loが 0、hiが 2 です。hi == 0で決めると falseになります。 開いたままの 数を 0 に できるかは、 幅の 小さい 端で見ます *と)の数だけを比べる。 "*("は(1 つに*1 つで数は 足りますが、 *が(より前に あるので 閉じに 使えず、 falseです。順を 見ないと 取り こぼします - 途中で
hiが負に なったのを見逃す。 例 2 の *))は、最後まで 回して loだけを見ると 0 に なり、 trueを返してしまいます。 hiが負に なった 時点で falseです
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「
*が無ければ、 開いたままのかっこの 数を 1 つ 持てば済みます。 *があると その 数が 幅に なるので、 最小と 最大の 2 つを 持ちます。 (で両方を 1 足し、 )で両方を 1 引き、 *で最小を 1 引いて 最大を 1 足します。 最大が 負に なったら 閉じが 多すぎて false、 最小は 負に なったら 0 に 戻します。 最後に 最小が 0 なら true です。 時間は O(n)、 記憶は O(1) です。」
書き終えたら、
「例 1 の
(*()でたどります。 (で最小 1、 最大 1 です。 *で最小 0、 最大 2 です。 (で最小 1、 最大 3 です。 )で最小 0、 最大 2 です。 最大は 一度も 負にならず、 最後の 最小が 0 なので true です。」