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

JavaScriptで2つの配列の合計を等しくする!要素交換アルゴリズムの解説

問題の概要

数値を格納した2つの配列 arr1arr2 を、それぞれ第1引数・第2引数として受け取るJavaScript関数を実装することを考えます。

ここで、arr1 の要素の合計と arr2 の要素の合計は互いに異なっています。この関数には次のような役割を持たせます。
まず arr1 から1つの要素を取り出して arr2 へ移動させ、同時に arr2 から1つの要素を取り出して arr1 へ移動させます。この操作によって、両方の配列の要素の合計が等しくなるようにします。最後に、交換した2つの要素を配列として返します。

例として、関数への入力が以下の場合を確認してみましょう。

入力

const arr1 = [1, 2, 5];
const arr2 = [2, 4];

出力

const output = [5, 4];

出力の解説

arr1 から 5 を取り除いて arr2 に追加し、arr2 から 4 を取り除いて arr1 に追加すると、両方の配列の合計はそれぞれ 7 となり、見事に一致します。そのため、答えは [5, 4] となります。

解法のアプローチ

全ての要素の組み合わせを総当たりで調べる方法もありますが、数学的な性質を利用すれば、より効率的に解けます。考え方は以下の通りです。

  • まず、両方の配列の合計値 sumAsumB をそれぞれ計算します。
  • 交換後の目標となる合計値は、全体の合計の半分、つまり (sumA + sumB) / 2 です。
  • arr1 から要素 x を抜き、arr2 から要素 y を受け取ったとき、条件式は sumA − x + y = (sumA + sumB) / 2 と表せます。これを変形すると y = x + difference(ただし difference = (sumA + sumB) / 2 − sumA)というシンプルな関係になります。
  • そこで、arr2 の各要素をあらかじめハッシュマップ(オブジェクト)に登録しておけば、「x + differencearr2 に存在するか」をO(1)で判定でき、全体の計算量はO(n)に抑えられます。

実装コード

const arr1 = [1, 2, 5];
const arr2 = [2, 4];
const balanceArrays = (arr1 = [], arr2 = []) => {
    const sumA = arr1.reduce((acc, v) => acc + v, 0)
    const sumB = arr2.reduce((acc, v) => acc + v, 0)
    const difference = (sumA + sumB) / 2 - sumA
    const map = arr2.reduce((acc, v) => {
        acc[v] = true
        return acc
    }, {})
    for(let i = 0; i < arr1.length; i++) {
        if(map[arr1[i] + difference] === true) {
            return [arr1[i], arr1[i] + difference]
        }
    }
    return []
};
console.log(balanceArrays(arr1, arr2));

出力結果

[5, 4]

コードのポイント

  • reduce() を使うことで、配列の合計値やハッシュマップの生成を簡潔に記述できます。
  • 条件を満たす組み合わせが存在しない場合は、空の配列 [] を返す仕様になっています。
  • ハッシュマップによる検索により、二重ループを使う総当たり方式(O(n × m))と比べて大幅に高速化でき、大きな配列でも実用的なパフォーマンスを発揮します。

このように、差分の関係式を導き出しハッシュマップと組み合わせることで、一見複雑に思える配列のバランス調整問題も、線形時間でエレガントに解くことができます。

  1. JavaScriptで2つの配列を結合する方法【concat()とスプレッド構文】

    JavaScriptで2つの配列を1つにまとめたい場合、最も一般的なのが concat() メソッドです。このメソッドは、元の配列を変更することなく、複数の配列や値を連結した新しい配列を返します。 concat()メソッドの基本構文 let 新しい配列 = 配列A.concat(配列B); サンプルコード 以下は、ボタンをクリックすると2つの配列を結合し、その結果を画面に表示する完全なサンプルです。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8&

  2. JavaScriptで2つの配列を乗算する方法|forループとmap()の実装例

    JavaScriptで2つの配列の各要素同士を乗算し、その結果を新しい配列として取得する方法を解説します。基本的にはforループでインデックスを順番に処理しながら、対応する位置にある要素同士を掛け合わせていくシンプルなアプローチです。 2つの配列を乗算するサンプルコード 以下の例では、「CLICK HERE」ボタンをクリックすると、配列 arr と arr1 の対応する要素が乗算され、結果が新しい配列 multArray に格納された上で画面に表示されます。 <!DOCTYPE html> <html lang=en> <head> <meta ch