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

JavaScriptで配列の合計を指定の数で割り切れるようにする、削除すべき最小の部分配列の求め方

本記事では、第一引数に正の整数の配列、第二引数に正の整数を受け取るJavaScript関数を実装します。この関数の目的は、元の配列から削除すべき最小の部分配列(連続する要素)の長さを求めて返すことです。削除後の残りの要素の合計が、第二引数で指定された数で割り切れる状態になる必要があります。

問題の例

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

const arr = [3, 8, 2, 6];
const num = 9;

配列全体の合計は 3 + 8 + 2 + 6 = 19 であり、これを 9 で割ると余りは 1 になります。ここで部分配列 [8, 2] を削除すると、残りの合計は 3 + 6 = 9 となり、見事に 9 で割り切れます。1つの要素だけを削除してもこの条件は満たせないため、期待される出力は次のとおりです。

const output = 2;

解法のコード

以下が実際の実装コードです。

const arr = [3, 8, 2, 6];
const num = 9;

const minimumDeletion = (arr = [], num) => {
    // 配列全体の合計をnumで割った余り
    const diff = arr.reduce((a, b) => a + b) % num;
    // 余りが0なら削除不要、それ以外は仮の最大値を設定
    let res = diff == 0 ? 0 : arr.length;
    // 累積和の余りごとの最初の出現位置を記録するマップ
    for (let i = 0, sum = 0, map = {0: -1}; i < arr.length; i++) {
        sum += arr[i];
        // 削除候補となる部分配列の終点に対応する余りを計算
        const target = (sum % num - diff + num) % num;
        if (map[target] != undefined) {
            res = Math.min(res, i - map[target]);
        }
        map[sum % num] = i;
    }
    // 条件を満たす削除が不可能な場合は-1を返す
    return res == arr.length ? -1 : res;
};
console.log(minimumDeletion(arr, num));

アルゴリズムのポイント

  • 余りの計算:まず配列全体の合計を num で割った余り(diff)を求めます。diff が 0 であれば、そもそも削除は一切不要なので答えは 0 です。
  • 削除すべき部分配列の性質:「合計を num で割った余りが diff と一致する部分配列」を見つけて取り除けば、残りの合計は必ず num の倍数になります。
  • 累積和とハッシュマップによる高速化:各時点での累積和の余りと、その余りが最初に出現したインデックスをマップに記録します。これにより、二重ループを使わずに O(n) の時間計算量で最短の部分配列を効率的に探索できます。
  • 不可能なケースへの対応:どの部分配列を削除しても条件を満たせない場合は -1 を返す仕様になっています。

実行結果

上記のコードをコンソールで実行すると、次の出力が得られます。

2
  1. JavaScriptで配列内の正の数だけを合計する方法

    問題正と負の数値が混在した配列を受け取り、その中に含まれる正の数すべての合計を計算して返すJavaScript関数を作成する必要があります。たとえば、[5, -5, -3, -5, -7, -8, 1, 9] という配列が与えられた場合、正の数は 5、1、9 の3つなので、期待される出力は 15 となります。解決コード以下がその実装例です。const arr = [5, -5, -3, -5, -7, -8, 1, 9]; const sumPositives = (arr = []) => {    const isPositive = num => type

  2. JavaScriptで循環配列の最大部分配列和を求める方法

    問題JavaScriptで、整数の配列 arr を唯一の引数として受け取る関数を作成します。この配列 arr は循環配列として扱います。循環配列とは、配列の末尾の要素の後に先頭の要素が続く構造のことです。私たちのタスクは、arr の空でない部分配列の中から、要素の合計が最大となる値を見つけて返すことです。入出力の例入力:const arr = [2, -2, 3, -1];出力:const output = 4;出力の説明:この場合、最適な部分配列は [3, -1, 2] です。末尾の -1 の後に先頭の 2 が続くため、3 + (-1) + 2 = 4 となり、これが最大の合計値になります。