最大部分配列問題
数値で構成された配列内の部分配列の中で、総和が最大となるものを求めます。
In computer science, the maximum sum subarray problem is the task of finding a contiguous subarray with the largest sum, within a given one-dimensional array A[1…n] of numbers.
From Wikipedia, the free encyclopedia
配列の要素が全て負であれば、その中で一番大きい要素が回答になります。
配列の要素が全て正であれば、全ての要素の和が回答になります。
配列の中に正と負が混在していると、問題が難しくなります。
例えば、[2, 3, -1, -20, 5, 10] という配列を考えます。
最大となる部分配列は [5, 10] で、総和は 15 です。
単純に総当たりで考えると、以下のようなコードになります。
def maximum_subarray_BF(array):
best_sum = float('-inf')
best_start = best_end = -1
for i in range(len(array)):
for j in range(i+1, len(array)):
current_sum = sum(array[i:j+1])
if current_sum > best_sum:
best_sum = current_sum
best_start = i
best_end = j
return best_sum, (best_start, best_end)
if __name__ == '__main__':
array = [2, 3, -1, -20, 5, 10]
# (15, (4, 5))
print(maximum_subarray_BF(array))
総当たりの計算量は\( O (N^2) \) です。
Kadane’s algorithm は、 この問題を \( O (N) \) で解くアルゴリズムです。
Kadane’s algorithm
動的計画法です。
current_max を現在考えている部分配列の最大値、best_max を求める部分配列の最大値と考えると、current_max = max(array[i], current_max+array[i]、best_max = max(best_max, current_max)として更新することができます。
Dynamic Programming – Kadane’s Algorithm
def maximum_subarray_kadane(array):
best_sum = float('-inf')
best_start = best_end = -1
current_sum = 0
for current_end, num in enumerate(array):
if current_sum <= 0:
current_start = current_end
current_sum = num
else:
current_sum += num
if current_sum > best_sum:
best_sum = current_sum
best_start = current_start
best_end = current_end
return best_sum, (best_start, best_end)
if __name__ == '__main__':
array = [2, 3, -1, -20, 5, 10]
# (15, (4, 5))
print(maximum_subarray_kadane(array))