JavaScriptでソートを使わずに配列から2番目に小さい値を取得する方法
数値の配列が与えられたとき、その配列から2番目に小さい値を返す関数を作成する必要があります。ポイントは、sort()メソッドなどで配列を並べ替えることなく実装することです。
例として、次のような配列を考えてみましょう。
const arr = [67, 87, 56, 8, 56, 78, 54, 67, 98, 56, 54];
この場合、期待される出力は次のとおりです。
54
これは、配列内の最小値が 8 であり、それより大きい値の中で最も小さいのが 54 だからです。重複する値(56 や 54)が存在することにも注目してください。
実装例:Math.min() と indexOf() を活用する方法
この問題は、以下のアプローチで解決できます。
Math.min()とスプレッド構文(...)を使って配列の最小値を求める。indexOf()でその最小値が最初に出現するインデックスを特定する。- 元の配列を壊さないよう
slice()でコピーを作り、splice()で最小値を1つ取り除く。 - 取り除いた後の配列に対して再び最小値を求めると、それが「2番目に小さい値」になる。
const arr = [67, 87, 56, 8, 56, 78, 54, 67, 98, 56, 54];
// 配列の最小値が最初に出現するインデックスを取得
const minimumIndex = arr => {
return arr.indexOf(Math.min(...arr));
};
// 最小値を1つ削除した後の配列の最小値=2番目に小さい値
const secondMinimum = arr => {
const copy = arr.slice(); // 元の配列を変更しないためコピーを作成
copy.splice(minimumIndex(copy), 1); // 最小値を1つだけ除去
return copy[minimumIndex(copy)]; // 残った要素の最小値を返す
};
console.log(secondMinimum(arr));実行結果
コンソールには次のように出力されます。
54
コードのポイント
- 元の配列を保護:
slice()によるシャローコピーを作成しているため、関数呼び出し後も元のarrは変更されません。これは副作用を避けるための重要なプラクティスです。 - 重複への対応:
indexOf()は最初に一致したインデックスのみを返すため、splice()では最小値が1つだけ除去されます。仮に最小値が複数存在しても、このコードは正しく動作します。
注意点とパフォーマンスについて
この実装はシンプルで読みやすい反面、Math.min(...arr) を複数回呼び出すため、配列サイズが非常に大きい場合には計算コストが増加します。また、スプレッド構文は要素数が数十万を超えるような巨大な配列ではスタックオーバーフローを引き起こす可能性がある点にも注意が必要です。
そのようなケースでは、ループを1回だけ回して最小値と2番目の最小値を同時に追跡する O(n) のアルゴリズムを採用すると、より効率的かつ安全に処理できます。
-
JavaScriptで配列を波状(ジグザグ)パターンに並べ替える方法
問題数値の配列 arr を唯一の引数として受け取るJavaScript関数を作成します。この関数は、並べ替え後の配列の要素が次のパターンに従うように並べ替える必要があります。arr[0] < arr[1] > arr[2] < arr[3]....このような並べ順は「波状ソート」や「ジグザグソート」と呼ばれることもあります。偶数番目のインデックスの要素は隣接する要素より小さく、奇数番目のインデックスの要素は隣接する要素より大きくなるように配置するのがポイントです。例として、関数への入力が次の場合を考えてみましょう。const arr = [1, 5, 1, 1, 6, 4];
-
JavaScriptで文字列の配列からコメントを削除する方法
この記事では、JavaScriptを使って文字列の配列からコメント部分を削除する方法について解説します。 問題 文字列の配列 arr を第一引数として、特殊文字の配列 starters を第二引数として受け取るJavaScript関数を作成する必要があります。 starters 配列には、コメントの開始となり得る文字が格納されています。作成する関数は、配列 arr を走査し、各文字列に含まれるコメントをすべて削除した結果を返すものとします。 例えば、関数への入力が次のような場合を考えてみましょう。 const arr = [ red, green !blue