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

【C++】配列の指定範囲の平均値を求める方法:累積和で効率化する解法

この問題では、n個の整数からなる配列とm個のクエリが与えられます。各クエリで指定された範囲の平均値の整数部分(小数点以下は切り捨て)を計算するプログラムを作成するのがタスクです。

具体例を使って問題を確認しましょう。

入力

array = {5, 7, 8, 9, 10}
m = 2; [0, 3], [2, 4]

出力

7
9

この問題を解く方法は大きく分けて2つあります。ひとつは素直に直接計算する方法、もうひとつは累積和(prefix sum)を活用する方法です。

直接計算のアプローチ:各クエリに対して、範囲の開始インデックスから終了インデックスまでループ処理を行い、該当する要素をすべて加算してから要素数で割ります。この方法でも正しい結果は得られますが、クエリごとに範囲内の要素を毎回足し直すため、計算量はO(n)となり、クエリが多くなると非効率です。

累積和(Prefix Sum)を使う方法

このアプローチでは、あらかじめ「配列の先頭からi番目のインデックスまでの要素の合計」を格納する累積和配列を計算しておきます。つまり、prefixSum(4)はインデックス4までの全要素の合計を表します。

この累積和配列を利用すれば、各クエリの平均値は次の式でO(1)で求められます。

Mean = (prefixSum[upper] - prefixSum[lower-1]) / (upper - lower + 1)

upperとlowerはクエリで指定された範囲のインデックスです。lowerが0の場合は、prefixSum(lower-1)を0として扱います。

前処理にO(n)かかりますが、以降の各クエリへの応答が定数時間で済むため、クエリ数が多い場合に大幅な高速化が期待できます。

サンプルプログラム

この解法の動作を示すC++プログラムは以下の通りです。

#include <iostream>
#define MAX 100
using namespace std;
int prefixSum[MAX];
void initialisePrefixSum(int arr[], int n) {
   prefixSum[0] = arr[0];
   for (int i = 1; i < n; i++)
   prefixSum[i] = prefixSum[i - 1] + arr[i];
}
int queryMean(int l, int r) {
   int mean;
   if (l == 0)
      mean =(prefixSum[r]/(r+1));
   else
      mean =((prefixSum[r] - prefixSum[l - 1]) / (r - l + 1));
      return mean;
}
int main() {
   int arr[] = {5, 7, 8, 9, 10 };
   int n = sizeof(arr) / sizeof(arr[0]);
   initialisePrefixSum(arr, n);
   cout<<"1番目のクエリの平均: "<<queryMean(1, 4)<<endl;
   cout<<"2番目のクエリの平均: "<<queryMean(2, 4)<<endl;
   return 0;
}

実行結果

1番目のクエリの平均: 8
2番目のクエリの平均: 9

このように、累積和を事前に構築しておくことで、範囲の合計を差分だけで即座に求められ、多数のクエリが発生する場面でも効率的に平均値を計算できます。

  1. C++で文字列の配列を定義・操作する方法を解説

    この記事では、C++において文字列の配列をどのように定義し、扱うのかを詳しく解説します。C言語との違い:文字列配列の基礎知識C言語には文字列型が存在しないため、文字列はchar型の配列(文字配列)として表現する必要がありました。そのため、複数の文字列をまとめて管理する「文字列の配列」を作るには、2次元のchar型配列を用意し、各行に異なる文字列を格納するという手法が取られていました。これは直感的ではなく、コードも冗長になりがちでした。一方、C++ではstd::stringクラスが標準ライブラリとして提供されています。このクラスのオブジェクトを使えば、文字列データを効率的かつ安全に格納・操作でき

  2. C++で配列を並べ替える方法|選択ソートの仕組みと実装例を解説

    C++では、さまざまなソート(並べ替え)アルゴリズムを使って配列を整列できます。ソート済みの配列とは、数値の大小順やアルファベット順など、何らかの基準に従って要素が並び替えられた配列のことです。代表的なソートアルゴリズムには、バブルソート、挿入ソート、選択ソート、マージソート、クイックソート、ヒープソートなどがあります。本記事では、その中でも構造がシンプルで理解しやすい「選択ソート」を取り上げ、実際のコード例とともに詳しく解説していきます。 選択ソートとは? 選択ソートは、未ソート部分の中から最小値を繰り返し探し出し、それを未ソート部分の先頭にある要素と交換することで、配列全体を昇順に整列さ