輸入一組整數,求出這組數字子序列和中最大值。也就是隻要求出最大子序列的和,不必求出最大的那個序列。例如:{4,-3,5,-2,6,-7,1}的最大子序列和是10。
算法1,
//窮舉法,時間複雜度O(N^3) int MaxSub(int Data[]) { int len = sizeof(Data)/sizeof(int); int MaxSum = 0; for (int i = 0;i <len;i++) { for (int j = i;j<len;j++) { int sum = 0; for (int k = i;k<j;k++) { sum += Data[k]; } if (MaxSum < sum) { MaxSum = sum; } } } return MaxSum; }
算法2
//窮舉法,時間複雜度O(N^2) int MaxSub(int Data[]) { int len = sizeof(Data)/sizeof(int) int MaxSum = 0; for (int i = 0;i<len;i++) { int sum = 0; for (int j = i;j<len;j++) { sum += Data[j]; } if (sum > MaxSum) { MaxSum = sum; } } return MaxSum; }
算法3
採用分治算法思想,時間複雜度O(NlogN);
最大序列只可能出現在序列的左邊,右邊或者跨越左右兩邊,用遞歸的方法可以解決問題。
int Max(int a,int b,int c) { int max = a; if (max < b){ max = b; } if (max <c){ max = c; } return max; } int MaxSub(int first,int last,int Data[]) { int lSum = 0; int rSum = 0; int lMaxSum = 0; int rMaxSum = 0; int middle = (first + last)/2; if (last < first ) return 0; if (last == first) return Data[first]; int lData = MaxSub(first,middle,Data); int rData = MaxSub(middle+1,last,Data); lMaxSum = Data[middle]; for (int i = middle;i>=first;i--) { lSum += Data[i]; if (lSum > lMaxSum){ lMaxSum = lSum; } } rMaxSum = Data[middle+1]; for (int j = middle+1;j<=last;j++) { rSum += Data[j]; if (rSum >rMaxSum) { rMaxSum = rSum; } } int num = Max(rData,lData,rMaxSum + lMaxSum); return num; }
算法4
下面介紹一個線性的算法,這個算法是許多聰明算法的典型,時間複雜度爲O(N)。
主要思想:如果a[i]是負數那麼它不可能代表最大序列的起點,因爲任何包含a[i]的作爲起點的子序列都可以通過用a[i+1]作爲起點來改進。類似的有,任何的負的子序列不可能是最優子序列的前綴。
long maxSubSum4(int a[],int len) { int maxsum, maxhere; maxsum = maxhere = a[0]; //初始化最大和爲a【0】 for (int i=1; i<len; i++) { if (maxhere <= 0) maxhere = a[i]; //如果前面位置最大連續子序列和小於等於0,則以當前位置i結尾的最大連續子序列和爲a[i] else maxhere += a[i]; //如果前面位置最大連續子序列和大於0,則以當前位置i結尾的最大連續子序列和爲它們兩者之和 if (maxhere > maxsum) { maxsum = maxhere; //更新最大連續子序列和 } } return maxsum; }
遍歷到a[i]時,如果a[i]前面的子序列和小於零,則將maxhere置爲a[i],因爲負的子序列和不會優化得到最大子序列。