1. 程式人生 > >最大陣列問題--分治策略

最大陣列問題--分治策略

最大子陣列問題–分治策略

參考資料:演算法導論 P38. 所謂分治,一共分為三步:

分解:分解步驟將問題劃分為一系列子問題,子問題和原問 題形式一樣,只是規模更小

解決:遞迴地求解出子問題,如果子問題足夠小 ,就停止遞迴,直接求解

合併:將子問題的解組合城原問題的解

現在給一個整數型陣列。求出一一個它的子陣列世得子數組裡的元素和最大。

先分解這個問題。 假定我們要尋找子陣列A[low->high]的最大子陣列 我們可以將這個陣列從中間分開。得到兩個陣列。所求的最大子串的純在形式有三種: 1.完全位於A[low->mid]. 2.完全位於A[mid+1->high] 3.被mid所截。

我們可以分別求出以上三種情況的最大值left_sum,right_sum和cross_sum,然後三者中的最大值就是所求答案。

對於1和2情況,很明顯為問題的子問題。對於第三中情況,我們以mid為分界點,分別向左和向右進行遞加,求的每一邊的最大值,加起來即為第三種情況的最大值 。

c程式碼如下:

#include<stdio.h>
#include<stdlib.h>

//子陣列中有mid
int find_max_crossing_subarray(int *A, int low, int high, int mid)
{
	int left_sum = -0xffff
; //儲存到目前為止左邊最大和 int sum = 0; //儲存A[i->mdi]中所有值的和 for (int i = mid; i >= low; i--) { sum += A[i]; if (sum > left_sum) left_sum = sum; } int right_sum = -0xffff; //儲存到目前為止右邊最大和 sum = 0; for (int i = mid + 1; i <= high; i++) { sum += A[i]; if (sum > right_sum)
right_sum = sum; } return left_sum + right_sum; } int find_maximum_subarray(int *A, int low, int high) { if (high == low) //數組裡只有一個元素 return A[low]; int mid = (high + low) / 2; //得到中間元素的索引 int left_sum = find_maximum_subarray(A, low, mid); int right_sum = find_maximum_subarray(A, mid + 1, high); int cross_sum = find_max_crossing_subarray(A, low, high, mid); //取三個值中最大值 if (left_sum >= right_sum && left_sum >= cross_sum) return left_sum; else if (right_sum >= left_sum && right_sum >= cross_sum) return right_sum; else return cross_sum; } int main() { int A[] = { 13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7 }; int sum = find_maximum_subarray(A, 0, 15); printf("%d\n", sum); }