【JavaScript】スタックで最長の有効な括弧部分文字列の長さを求める方法
'(' と ')' の2種類の文字だけで構成された文字列が与えられたとき、その中に含まれる最長の有効な(正しく対応した)括弧部分文字列の長さを求める方法を、JavaScriptで解説します。
整形式の括弧列とは?
括弧の並びが「整形式(well-formed)」であるためには、すべての開き括弧に対して、それに対応する閉じ括弧が存在しなければなりません。具体例で確認してみましょう。
'(())()' は整形式の括弧列 '())' は整形式ではない '()()()' は整形式の括弧列
解き方:スタックを活用する
この問題はスタック(Stack)を使うことで効率的に解けます。手順は以下のとおりです。
- 文字列を1文字ずつ走査し、スタックには各文字のインデックスを保存します。
- 開き括弧 '(' を見つけたら、そのインデックスをスタックにプッシュします。
- 閉じ括弧 ')' を見つけた場合、スタックの先頭が対応する開き括弧のインデックスであればポップします。対応できない場合(スタックが空、または先頭が閉じ括弧のインデックス)は、そのインデックスを区切り位置としてプッシュします。
- 走査が終わったら、スタックの末尾に文字列長、先頭に -1 を番兵として追加し、隣接する要素の差分から最大値を計算します。これが答えとなります。
実装例
const str = '(())()(((';
const longestValidParentheses = (str = '') => {
var ts = str.split('');
var stack = [], max = 0;
ts.forEach((el, ind) => {
if (el == '(') {
stack.push(ind);
}
else {
if (stack.length === 0 || ts[stack[stack.length - 1]] == ')'){
stack.push(ind);
}
else {
stack.pop();
};
}
});
stack.push(ts.length);
stack.splice(0, 0, -1);
for (let ind = 0;
ind< stack.length - 1; ind++) {
let v = stack[ind+1] - stack[ind] - 1; max = Math.max(max, v);
};
return max;
}; console.log(longestValidParentheses(str));
出力結果
このコードをコンソールで実行すると、次のような出力が得られます。
6
入力文字列 '(())()(((' の場合、先頭の '(())()' が最も長い整形式の括弧部分文字列となり、その長さは 6 文字です。
-
JavaScriptで合計が0以上となる最長部分配列を見つけるアルゴリズム
問題の概要今回は、-1から1の範囲の整数のみを含む配列を受け取り、その中から合計が0以上になる最長の連続する部分配列(サブアレイ)の長さを返すJavaScript関数を作成します。一見単純な問題に見えますが、全ての組み合わせを総当たりで調べると計算量がO(n²)となり、配列が大きくなると非効率です。そこで本記事では、累積和(プレフィックスサム)の考え方を活用し、線形時間O(n)で解くスマートな手法を紹介します。解法のコードconst arr = [-1, -1, 0, 1, 1, -1, -1, -1]; const longestPositiveSum = (arr = []) =>
-
JavaScriptで文字列内の最長の母音部分文字列の長さを求める方法
問題 文字列を引数として受け取るJavaScriptの関数を作成する必要があります。この関数は、母音(a、e、i、o、u)のみで構成される連続した部分文字列の中から、最も長いものの長さを返さなければなりません。 アプローチ この問題は、文字列を先頭から順番に走査しながら、現在連続している母音の数をカウントすることで解決できます。具体的な手順は以下の通りです。 cur:現在連続している母音の数を記録するカウンター変数 max:これまでに見つかった最長の母音連鎖の長さを保持する変数 走査中の文字が母音であれば cur を1増やし、max より大きければ max を更新する 子音に遭遇した場合は