STEP: 1 区間の和 1
区間の和 1
- 数列の『ある区間和を求めなさい』という問題が出る
- 数列を使って累積和を作る
- 累積和を使って区間和を求める
ここは問題の解説ではなく、
というステップで問題を解きます。「累積和」は区間和を求める時などの前準備のもので、『これさえ作っちまえばあとはこっちのもんよ!』というくらい汎用性の高いツールです。そのツールの作り方と使い方をここで学習します。
例)A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ちなみにこの数列の数を全て足すと 55 になりますよね。この数列を使って累積和で 55 を導き出してみます。
まずは新しく cum_sum
というリストを作ります。その初期値を [0]
にします。
cum_sum = [0]
これと リストA を使って累積和を作ります。
要素番号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
cum_sum | 0 | 1 | 3 | 6 | 10 | 15 | 21 | 28 | 36 | 45 | 55 |
リストA | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
cum_sum[0] = 0
cum_sum[1] = cum_sum[0] + A[0]
cum_sum[2] = cum_sum[1] + A[1]
(中略)
cum_sum[10] = cum_sum[9] + A[9]
これをプログラムにすると、
A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
cum_sum = [0] * 11 # 先にゼロマップを作る方法
for i in range(10):
cum_sum[i+1] = cum_sum[i] + A[i]
print(cum_sum)
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
という感じになります。
この数列を「累積和」と言います。1つ1つの数値を指すこともあります。
このリストの最後の 55 が、1 から 10 の総和です。45 が、1 から 9 の総和です。
ここまでが「前準備」と言われるところです。
今度はこの累積和を使って区間和を求めてみます。びっくりするほど簡単です。😊
数列 1 2 3 4 5 6 7 8 9 10 の、5 番目から 8 番目の区間和を求める場合。
5 番目というのは 5 です。8 番目は 8 です。
5 + 6 + 7 + 8 = 26
この 26 を累積和を用いて求めます。
リストA | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
cum_sum | 0 | 1 | 3 | 6 | 10 | 15 | 21 | 28 | 36 | 45 | 55 |
1 ~ 8 までを足した数が 36 です。
5 ~ 8 までを足した数を求めたいので、1 ~ 4 までの数は不要です。
よって、1 ~ 8 まで足した 36 から 1 ~ 4 までを足した 10 を引くと、5 ~ 8 を足した数が求められます。
cum_sum[8] - cum_sum[4]
↓
36 - 10
↓
26
プログラムにすると、
A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
cum_sum = [0] * 11
for i in range(10):
cum_sum[i+1] = cum_sum[i] + A[i]
sum_range = cum_sum[8] - cum_sum[4]
print(sum_range)
26
この累積和が役立つのは、線形で繰り返し区間和を求める時です。例えば 1 ~ 100、2 ~ 101、……の区間和を何百回何百万回と繰り返して求める時、ループごとに毎度 1 ~ 100、2 ~ 101、と足し算をしていくことになります。時間がかかります。これを
これがランダムな数列だったとしても、区間がランダムだったとしても関係なく、一度累積和を作ってしまえば
これを人の手でやったとして、予め累積和さえ作っておけばどれだけ早く区間和が求められるかが容易に想像できるでしょう。
小学生でも超簡単に扱えるアルゴリズム。ネコにも優しい世界です。
それでは早速、問題の STEP 1 を累積和を使って区間和を求めるプログラムを組んでみましょう!もちろんこのプログラムを参考にしながらでも構いませんよ!