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

【JavaScript】配列内で最初に重複する要素のインデックスを返す方法

問題概要

配列の中で、少なくとも2回以上出現する要素のうち、最初に現れたもののインデックスを返す関数を作成します。すべての要素が1回しか出現しない場合は、-1 を返します。

この問題の条件は、定数空間(余分なメモリを追加で使用しないこと)で実装する必要があるという点です。つまり、Set や Map のような追加データ構造を使わずに解く必要があります。

解決アプローチ

この問題は、for ループで配列を先頭から順に走査し、Array.prototype.lastIndexOf() メソッドで重複をチェックすることで解決できます。

lastIndexOf() は指定した要素が配列内で最後に現れるインデックスを返します。その結果が現在のインデックスと一致しなければ、同じ値が後方にも存在する(=重複している)ことを意味します。したがって、条件が最初に成立した時点のインデックスが「最初の重複要素」の位置となります。

サンプルコード

const firstDuplicate = arr => {
    for(let i = 0; i < arr.length; i++){
        if(arr.lastIndexOf(arr[i]) !== i){
            return i;
        };
    };
    return -1;
}
console.log(firstDuplicate([3, 5, 6, 8, 5, 3])); // 0
console.log(firstDuplicate([0, 1, 2, 3, 4, 4, 5])); // 4
console.log(firstDuplicate([0, 1, 1, 2, 3, 4, 4, 5])); // 1
console.log(firstDuplicate([0, 1, 2, 3, 4, 9, 5])); // -1

実行結果

コンソールには次のように出力されます。

0
4
1
-1

コードの解説

1つ目の例では、配列 [3, 5, 6, 8, 5, 3] の先頭要素「3」がインデックス5にも存在するため、lastIndexOf() の結果(5)と現在のインデックス(0)が一致せず、即座に 0 が返されます。

2つ目の例では、値「4」が初めて重複するのはインデックス4なので 4 が返り、3つ目の例では値「1」の重複がインデックス1で発生するため 1 が返ります。最後の例のように重複が一切存在しない場合は -1 が返されます。

計算量について

この実装は空間計算量こそ O(1) で定数空間の条件を満たしますが、ループ内で毎回 lastIndexOf() を呼び出すため、時間計算量は O(n²) になります。配列サイズが非常に大きい場合やパフォーマンスが重要なケースでは、Set を使った O(n) の実装も検討するとよいでしょう。

  1. 【JavaScript】配列の数値を組み合わせて最大の数を作る方法

    今回は、数値の配列を第一引数(唯一の引数)として受け取るJavaScript関数を作成します。この関数の役割は、配列内の数値を最適な順序で連結し、それらの数値から作り得る最大の数値を文字列として返すことです。 具体例 例えば、入力配列が次のような場合を考えてみましょう。 const arr = [5, 45, 34, 9, 3]; このとき、期待される出力は以下の通りです。 const output = 9545343; 注目すべき点として、単純に数値の大小で降順ソートするだけでは不十分なケースがあることが挙げられます。例えば「45」と「5」を比較すると、数値としては45の方が大きいですが、連

  2. 【JavaScript入門】配列内で最初の非連続な数値を見つける方法

    はじめに本記事では、JavaScriptを使って「数値の配列の中から、直前の要素と連続していない最初の数値」を見つける方法を解説します。アルゴリズムの練習やコーディング面接の対策としても役立つ基本的な問題です。 問題の定義数値の配列を受け取るJavaScript関数を作成する必要があります。この関数は、直前の要素に対して +1 となっていない(連続していない)最初の要素を返さなければなりません。 言い換えると、隣り合う要素同士の差が1以外になる箇所が現れたとき、その箇所の後ろ側の要素を返すという処理です。なお、そのような要素が必ず配列内に1つ以上存在するものとします。 サンプルコード以下は、実