Pythonで配列内のすべての奇数長部分配列の合計を求める方法を解説
正の整数からなる配列 nums が与えられたとき、考えられるすべての奇数長の部分配列(サブ配列)の要素の合計を求めます。なお、部分配列とは元の配列から連続して取り出された部分列のことを指します。
具体例で確認する
例として、nums = [3, 8, 2, 5, 7] が入力された場合を考えてみましょう。このときの出力は 92 になります。対象となる奇数長の部分配列は以下の通りです。
nums[0] = 3 nums[1] = 8 nums[2] = 2 nums[3] = 5 nums[4] = 7 nums[0..2] → 合計 = 13 nums[1..3] → 合計 = 15 nums[2..4] → 合計 = 14 nums[0..4] → 合計 = 25
これらをすべて足し合わせると、3 + 8 + 2 + 5 + 7 + 13 + 15 + 14 + 25 = 92 となります。
解法のアプローチ
この問題は、次の手順で解くことができます。
- 合計値
totalを 0 で初期化する - インデックス
idxを 0 で初期化する - 奇数の長さ(1, 3, 5, …)を格納したリスト
lを作成する idxがlのサイズ未満である間、以下を繰り返すk := l[idx]として、現在注目している部分配列の長さを取得するiを 0 からnumsのサイズまでループさせるi + k < len(nums) + 1を満たす場合、nums[i : i+k]の要素の合計をtotalに加算する
idx := idx + 1として、次の奇数長へ進む
- 最後に
totalを返す
Pythonでの実装例
理解を深めるために、実際のコードを見てみましょう。
def solve(nums):
total = 0
idx = 0
l = [i for i in range(len(nums)+1) if i % 2 != 0]
while(idx < len(l)):
k = l[idx]
for i in range(len(nums)):
if i+k < len(nums)+1:
total += sum(nums[i:i+k])
idx += 1
return total
nums = [3,8,2,5,7]
print(solve(nums))
入力
[3,8,2,5,7]
出力
92
計算量と効率化のヒント
上記の実装では、奇数の長さごとに開始位置を走査し、さらにスライスの合計を計算するため、時間計算量は O(n³) になります。配列のサイズが大きくなると処理が遅くなる点に注意が必要です。
より効率化したい場合は、「各要素が奇数長の部分配列に何回登場するか」を数学的に求める方法が有効です。インデックス i(0始まり)の要素が含まれる奇数長の部分配列の個数は ((i+1) * (n-i) + 1) // 2 で表せるため、これを利用すると O(n) で答えを求められます。
def solve_fast(nums):
n = len(nums)
return sum(((i+1)*(n-i)+1)//2 * v for i, v in enumerate(nums))
nums = [3,8,2,5,7]
print(solve_fast(nums)) # 92
この最適化版でも同じ結果 92 が得られます。大きなデータを扱う場合や競技プログラミングでは、こちらのアプローチがおすすめです。
-
Pythonで二分木の全ノードの値の合計を求めるプログラム
二分木(バイナリツリー)にいくつかの値が格納されている場合、木に含まれるすべての値の合計を求めたいことがあります。例えば、次のような二分木が入力として与えられたとします。この場合、出力は 14 になります(2 + 4 + 3 + 5 = 14)。解決のアプローチこの問題を解くには、再帰を使って各ノードを順番に訪問し、値を足し合わせていきます。具体的な手順は以下の通りです。関数 recurse() を定義します。引数としてノードを受け取ります。変数 val に現在のノードの値を代入します。ノードの左の子が存在する場合は、val に左部分木の再帰結果を加算します。ノードの右の子が存在する場合は、v
-
Pythonで数の奇数の約数(奇因子)の合計を求めるプログラム
この記事では、「整数 n が与えられたとき、その数の奇数の約数(奇因子)の合計を求める」という問題の解き方を解説します。 問題文 整数 n が入力として与えられます。求めるのは、n の奇数の約数をすべて足し合わせた値です。 例えば n = 27 の場合、約数は 1, 3, 9, 27 のすべてが奇数であるため、合計は 1 + 3 + 9 + 27 = 40 となります。 アプローチのポイント この問題で最初に行うべきは、偶数の約数をすべて除外することです。 偶数の約数を取り除くには、n が 2 で割り切れなくなるまで繰り返し 2 で割ります。この操作によって n から 2 の因数が完全に