最大部分配列問題
数値で構成された配列内の部分配列の中で、総和が最大となるものを求めます。
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))