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

【JavaScript】合計が0に最も近い配列の隣接要素ペアを見つける方法

本記事では、数値の配列を受け取り、隣接する2つの要素の合計が目標値に最も近くなるペアをサブ配列として返すJavaScript関数を作成します。目標値に0を指定すれば、「合計が0に最も近い隣接要素」を求めることができます。

問題の要件

この関数には、次の条件が課せられています。

  • 数値の配列を目標値(合計のターゲット)とともに受け取る
  • 隣接する2つの要素のうち、合計が目標値に最も近いペアを返す
  • 配列の長さが2以下の場合は、元の配列全体をそのまま返す

たとえば、次のような入力配列が与えられたとします。

const arr = [4, 4, 12, 3, 3, 1, 5, -4, 2, 2];

この配列の場合、隣接する2要素 [5, -4] の合計は 1 となり、ほかのどの隣接ペアよりも目標値に近いため、[5, -4] を返すのが正解です。

実装コード

以下が実際のコードです。配列の reduce() メソッドを活用し、各隣接ペアの合計と目標値との差分を順番に比較しながら、最も差分が小さい開始インデックスを記録していきます。

const arr = [4, 4, 12, 3, 3, 1, 5, -4, 2, 2];

const closestElements = (arr, sum) => {
    if(arr.length <= 2){
        return arr;
    }
    const creds = arr.reduce((acc, val, ind) => {
        let { closest, startIndex } = acc;
        const next = arr[ind+1];
        if(!next){
            return acc;
        }
        const diff = Math.abs(sum - (val + next));
        if(diff < closest){
            startIndex = ind;
            closest = diff;
        }
        return { startIndex, closest };
    }, {
        closest: Infinity,
        startIndex: -1
    });
    const { startIndex: s } = creds;
    return [arr[s], arr[s+1]];
};

console.log(closestElements(arr, 1));

コードのポイント

  • 初期値として Infinity(無限大)を設定しているため、最初のペアとの比較で必ず最小差分が更新されます。
  • 現在の要素と次の要素(arr[ind+1])の合計を計算し、Math.abs() によって目標値との絶対差を求めます。
  • 差分がそれまでの最小値より小さければ、開始インデックスと最小差分を更新します。
  • 最後に、記録しておいたインデックスをもとに、該当する2つの要素を配列として返します。

実行結果

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

[5, -4]

なお、第二引数に渡す目標値を変更すれば、任意の値に最も近い合計を持つ隣接ペアを汎用的に求められます。目標値を 0 にすれば、まさに「合計が0に最も近いペア」を取得できるのです。

  1. JavaScriptで配列を「2倍関係」を満たすように再配置できるか判定する方法

    問題数値の配列 arr を第一引数(唯一の引数)として受け取るJavaScript関数を作成する必要があります。配列 arr の長さは必ず偶数であると保証されています。この関数は、すべての 0 <= i < arr.length / 2 に対して arr[2 * i + 1] = 2 * arr[2 * i] という条件を満たすように並べ替えられる場合にのみ true を返し、そうでなければ false を返す必要があります。たとえば、関数への入力が次の場合を考えてみましょう。const arr = [4, -2, 2, -4];このとき、期待される出力は次のとおりです。const

  2. JavaScriptで2次元配列の要素を交互に加減算して合計を求める方法

    問題の概要行数と列数が同じ m × n の2次元配列(数値の行列)を受け取り、次の式で表される合計値を計算して返すJavaScript関数を作成します。$\sum_{i=1}^m \sum_{j=1}^n (-1)^{i+j}a_{ij}$この式が意味するのは、各要素に対して「インデックス i + j の偶奇」に応じて符号を切り替えるということです。具体的には、(i + j) が偶数である要素は正の符号で加算し、奇数である要素は負の符号で減算します。チェス盤のように市松模様状にプラスとマイナスが交互に並ぶイメージです。計算イメージ0始まりのインデックスで考えると、左上の要素 (0, 0) は