顧名思義,最大子陣列問題是求乙個陣列array中「和最大的非空連續子陣列「,這樣的連續子陣列我們叫做最大子陣列,它的應用也有
很多,比如說找出時間序列中兩個時間節點使得這兩個時間節點對應的值的落差最大,如下圖:
對於這類問題,通過求原始時間序列的一階差分得到序列array,此時求得array的最大子陣列便是原問題的解。
這是最容易想到的辦法,對於規模為n的問題,需要嘗試c(2,n)次(代表組合數,這裡不方便打公式),因為每次的處理時間也至少是常量,因此,這種方法的執行的時間下界是n的平方,當n很大的時候,這種方法不可取。下面先介紹一種時間複雜度上界為n平方的分治的遞迴演算法,最後再分析一種非遞迴的線性演算法。
這裡我們是求「乙個最大子陣列」,而不是求「最大子陣列」,因為最大子陣列可能有多個,另外,很顯然只有陣列中有負數的時候問題才有意義。
分治演算法的關鍵是問題如何劃分為兩個(或多個)子問題,之後又是如何進行合併,劃分問題成為兩個規模更小的子問題的分析如下:
找到陣列array的**位置mid,然後考慮求解array[low,...,mid]和array[mid+1,...,high],而array[low,...,high]的任何連續子陣列array[i,...,j]所處的位置必然是以下三種情況之一:
(1)完全位於子陣列array[low,...,mid]中,因此low=
現在我們先求跨越中點的最大子陣列問題,這個問題並不是規模更小的問題,因為它要求子陣列必須跨越中點,我們只需要求出形如
array[i,...,mid]的最大子陣列和形如array[mid+1,...,j]的最大子陣列,合併即可,對於這個子程式,我們返回兩端的索引和最大子陣列
的和(後乙個子程式也返回這種形式的結果),我們定義返回結果為結構體型別:
//定義型別為結構體型別的返回結果
struct value
;
接下來是求跨越中點的最大子陣列子程式:
//最大子陣列跨越中點的情況
struct value find_max_crossing_subarray(int arr,int low,int mid,int high)
} //找到右邊陣列的最大子陣列
sum = 0;
for(i = mid+1;i < high+1;i++) }
result.index_left = max_left;
result.index_right = max_right;
result.sum = left_sum + right_sum;
return result;
}
很顯然,這個子程式的時間複雜度為線性,接下來是求陣列
array最大子陣列的遞迴程式:
//求解最大子陣列問題的遞迴子程式
struct value find_maximum_subarray(int arr,int low,int high)
else
}
這段程式很簡單,處理特殊情況和一般情況,遞迴呼叫自身,之後再合併解,我們可以想象得到這是乙個樹形的結構,從最底層向上
合併結果,最上面即是最後的結果。
完整的程式:
#include#include#include#define max 8888
#define min -8888
//最大子陣列的分治求解演算法
//定義型別為結構體型別的返回結果
struct value
;//最大子陣列跨越中點的情況
struct value find_max_crossing_subarray(int arr,int low,int mid,int high)
} //找到右邊陣列的最大子陣列
sum = 0;
for(i = mid+1;i < high+1;i++) }
result.index_left = max_left;
result.index_right = max_right;
result.sum = left_sum + right_sum;
return result;
}//求解最大子陣列問題的遞迴子程式
struct value find_maximum_subarray(int arr,int low,int high)
else }
//主程式
void main(void)
;void main(void)
printf("\n");
//當前最優結果
struct value current_best;
for(i = 0;i < n-1;i++)
int temp = 0,sum = 0,current_left;
//計算arr[0,...,i+1]的形如arr[j,...,i+1]的最大子陣列,然後和之前的arr[0,...,i]的最大子陣列(current_best)比較,更新當前最大子陣列
for(j = i+1;j > -1;j--)
}//此時,找到了arr[0,...,i+1]的形如arr[j,...,i+1]的最大子陣列,現在進行比較
if(sum > current_best.sum)
}//列印結果
printf("陣列的最大子陣列已經找到,兩端的下標值分別為%4d,%4d,最大子陣列的值為%4d\n",current_best.index_left,current_best.index_right,current_best.sum);
}
結果如下:
最大子陣列問題
include include include typedef struct num num extern void displayarray const int a,const int n 顯示陣列元素值 extern void buildarray int a,const int n 陣列元素賦...
最大子陣列問題
每週堅持搞三種演算法問題,介紹一下最大子陣列問題 演算法思路 分治策略求解,將問題不斷分為更小的問題,進而求解 問題描述 求陣列中相連著的數 相加值最大,例如 輸出最大為2 3 4 21 22 define crt secure no warnigns include include include...
最大子陣列問題
include 使用時,請使用maxarray函式 using namespace std int max int a,int b,int c 返回三個數中最大者。void f int low,int len,int max0 引數分別為 陣列首位址,陣列長度,目前求得的最大值 for j 0 j ...