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

【C++】連続する部分配列の合計がkの倍数になるかを判定するアルゴリズム

問題概要

負でない数値のリストと目標となる整数 k が与えられたとき、長さが2以上の連続する部分配列(サブアレイ)の中に、合計が k の倍数(つまり n × k、n は任意の整数)となるものが存在するかどうかを判定する関数を作成します。

例えば、入力が [23, 2, 4, 6, 7] で k = 6 の場合を考えてみましょう。[2, 4] は長さ2の連続部分配列であり、その合計は 6 で k の倍数に一致するため、結果は True(真) となります。

解法のアプローチ:累積和の剰余とハッシュマップ

この問題は、累積和(プレフィックスサム)の剰余とハッシュマップを組み合わせることで、O(n) の時間計算量で効率的に解くことができます。

解法の手順

  • ハッシュマップ m を用意し、初期値として m[0] = -1 を設定します。また、sum = 0、n = nums のサイズ とします。
  • i を 0 から n − 1 まで順に処理します。
    • sum += nums[i] として累積和を更新します。
    • k が 0 以外の場合、sum %= k で剰余を取ります。
    • m に sum が既に存在し、かつ i − m[sum] >= 2 を満たす場合は true を返します。
    • m に sum が存在しない場合は、m[sum] = i として現在のインデックスを登録します。
  • ループ完了後も条件を満たす部分配列が見つからなければ、false を返します。

なぜこの方法が有効なのか

重要なポイントは、「2つの異なるインデックスで累積和の剰余が等しい場合、その間の部分配列の合計は必ず k の倍数になる」という性質です。また、m[0] = -1 を事前に登録しておくことで、配列の先頭から始まる部分配列も正しく判定できるようになります。さらに、「インデックスの差が2以上」という条件を設けることで、長さ1の部分配列が誤ってマッチするのを防いでいます。

C++ 実装例

#include <bits/stdc++.h>
using namespace std;
class Solution {
    public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> m;
        m[0] = -1;
        int sum = 0;
        int n = nums.size();
        for(int i = 0; i < n; i++){
            sum += nums[i];
            if(k)
            sum %= k;
            if(m.count(sum) && i - m[sum] >= 2){
                return true;
            }
            if(!m.count(sum)) m[sum] = i;
        }
        return false;
    }
};
main(){
    vector<int> v = {23,2,4,6,7};
    Solution ob;
    cout << (ob.checkSubarraySum(v, 6));
}

入力

[23,2,4,6,7]
6

出力

1

出力が 1 となっているのは、関数が true を返したこと、つまり条件を満たす連続部分配列 [2, 4] が存在することを示しています。

  1. C++のプレフィックス和(累積和)を活用してO(n)で最大部分配列和を求める方法

    問題概要 正の整数と負の整数が混在する配列が与えられたとき、その配列の中で合計値が最大となる部分配列(連続した要素の並び)の合計を求める問題です。 例 入力配列が {-12, -5, 4, -1, -7, 1, 8, -3} の場合、合計が最大になる部分配列は {1, 8} となるため、出力は 9 になります。 アルゴリズム この問題は、プレフィックス和(累積和)を利用することで O(n) の時間計算量で効率的に解くことができます。考え方の核心は、「ある位置 i で終わる部分配列の合計の最大値」は「prefix_sum[i] から、それ以前に現れた最小の累積和を引いた値」で表せるという点です

  2. C++でアリコート和(Aliquot Sum)を計算する方法

    本記事では、アリコート和(Aliquot Sum)とは何かを解説します。アリコート和とは、ある数 n の約数のうち、n 自身を除いたすべての約数の総和のことです。例えば、数値が 20 の場合、その約数は (1, 2, 4, 5, 10) となるため、アリコート和は 22 になります。興味深い点として、アリコート和がその数自身と等しくなる場合、その数は「完全数」と呼ばれます。例えば 6 の場合、約数は (1, 2, 3) であり、アリコート和は 1 + 2 + 3 = 6 となるため、6 は完全数です。それでは、以下のアルゴリズムを使ってアリコート和を求める方法を見ていきましょう。アルゴリズムg