JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

【JavaScript】ソートせずに配列から上位2つの要素(最大値トップ2)を1パスで取得する方法

JavaScriptには、並び順がバラバラの数値が格納された配列があります。ここでの課題は、この数値配列を受け取って、配列内で最も大きい2つの要素(上位2要素)だけを抽出し、新しい配列として返す関数を書くことです。

さらに重要な条件として、処理は1パス(ワンパス)で完了させる必要があります。つまり、forループは1回だけ使う、あるいはES6の配列メソッドを利用する場合も1回の呼び出しにとどめ、ネストした処理(二重ループなど)は避け、時間計算量をO(n) の線形時間に保たなければなりません。

解決策:Array.prototype.reduce() を使う

この問題は、Array.prototype.reduce() メソッドを使うとエレガントに解決できます。reduceの初期値として「負の無限大」を2つ持つ配列 [-Infinity, -Infinity] を用意し、各要素を走査しながら最大値と2番目に大きい値を順次更新していきます。

コード例

const arr = [23, 65, 67, 23, 2, 6, 87, 23, 45, 65, 3, 234, 3];

const topTwo = arr => {
    // 要素が2つ未満の場合は false を返す
    if(arr.length < 2){
        return false;
    };
    return arr.reduce((acc, val) => {
        // 現在の最大値より大きければ、入れ替えを行う
        if(val > acc[0]){
            let t = acc[0];
            acc[0] = val;
            acc[1] = t;
        // 最大値以下でも2位より大きければ2位を更新
        }else if(val > acc[1]){
            acc[1] = val;
        };
        return acc;
    }, [-Infinity, -Infinity]);
};

console.log(topTwo(arr));

実行結果

コンソールへの出力は次のようになります。

[ 234, 87 ]

仕組みの解説

アキュムレータ accacc[0] には常に「現時点での最大値」が、acc[1] には「2番目に大きい値」が保持されます。

  • 走査中の値 valacc[0] より大きい場合:旧最大値を2位へ退避させ、val を新しい最大値とします。
  • val が最大値以下だが acc[1] より大きい場合:acc[1] だけを更新します。

初期値に -Infinity を使うことで、負の数を含むあらゆる数値配列にも正しく対応できます。また、配列を一度だけ走査するため、計算量はO(n)、追加のメモリも定数領域で済み、非常に効率的な実装となっています。

  1. 【初心者向け】JavaScriptのArray.from()メソッドの使い方を実例で解説

    JavaScript の Array.from() メソッドは、length プロパティを持つオブジェクト(配列風オブジェクト)や、文字列・Map・Set などの反復可能(イテラブル)なオブジェクトから、新しい Array オブジェクトを生成して返すためのメソッドです。元のオブジェクトは変更されず、常に新しい配列インスタンスが返されます。 基本構文 Array.from(obj, mapFunction, val) パラメータの説明 obj:配列へ変換したい対象のオブジェクト。配列風オブジェクト(length プロパティを持つもの)や反復可能なオブジェクトを指定します。 mapFunctio

  2. JavaScriptのArray.from()メソッドとは?使い方と実例をわかりやすく解説

    Array.from()メソッドは、配列風オブジェクト(array-like)や反復可能オブジェクト(iterable)から、新しい配列オブジェクトを作成するための便利なメソッドです。文字列、Map、Set、NodeListなど、さまざまなデータを手軽に配列へ変換できます。 Array.from()の基本的な動作 例えば、文字列「HelloWorld」に対してArray.from()を使用すると、1文字ずつ分割された新しい配列が生成されます。以下に実際のコード例を示します。 サンプルコード <!DOCTYPE html> <html lang="ja"&g