學習筆記——c語言實現最大連續子序列之和的演算法
今天到圖書館借了本資料結構的書,翻開一看,原來這裡有我之前參加的周立功機試的題目,哎,真是後悔莫及啊!現在把這個問題好好總結一下,以備不時之需。
最大連續子序列之和問題:給出N個整數(可以為負)A1,A2,A3,…,An,找出i到j項之和的最大值,如果所有整數為負,最大值為0。
下面是給出了三種不同的演算法。
//*********************************************************************************************
#include <stdio.h>
static int Start = 0;
static int End = 0;
/*
該演算法是窮舉法,時間複雜度為O(n^3).第一二層迴圈迭代了所有肯能的連續子序列,第三層迴圈裡tempSum += a[n]就是計算各子序列的和。然後tempSum再與max作比較,求出終結果。Start、End分別記錄了子序列的起始和終止位置(陣列下標從0開始算)。
*/
int fun(int a[], int n)//n是陣列元素的個數
{
int i,j,k,tempSum;
int max = 0;
for (i = 0; i < n; i++)
for (j = i; j < n; j++)
{
tempSum = 0;
for (k = i; k <= j; k++)
{
tempSum += a[k];
}
if (tempSum > max)
{
max = tempSum;
Start = i;
End = j;
}
}
return max;
}
/*
該演算法是基於上一個演算法的改進,演算法的時間複雜度為O(n^2).在這演算法中去掉了上面那個
演算法的第二層迴圈,原因在於,從a[i]加到a[j]的tempSum等於a[i]加到a[j-1]的tempSum
,所以就沒必要在來一層迴圈重新算tempSum了。
*/
int fun2(int a[], int n)
{
int i,j,tempSum;
int max = 0;
for (i = 0; i < n; i++)
{
tempSum = 0;
for (j = i; j <= n; j++)
{
tempSum += a[j];
if (tempSum > max)
{
max = tempSum;
//Start = i;
//End = j;
}
}
}
return max;
}
/*
該演算法是線性演算法。我們在計算最大連續子竄的時候會發現一個規律:a[i]至a[j]之和sum
若小於零,那麼a[j]後面的項再與sum相加的和一定小於沒有加上sum之前的和大。根據這個我們可以設計出如下演算法。
*/
int fun3(int a[], int n)
{
int i,j;
int max = 0;
int tempSum = 0;
for (i = 0,j = 0; j < n; j++)
{
tempSum += a[j];
if (tempSum > max)
{
max = tempSum;
//Start = i;
//End = j;
}
else if (tempSum < 0)//若tempSum小於0,下次直接從第j+1項開始加
{
i = j + 1;
tempSum = 0;
}
}
return max;
}
int main()
{
int a[10] = {1,-2,4,6,-2,4,-6,8,-2,-4};
printf("start:%d,end:%d,sum:%d/n", Start,End,fun(a,10));
printf("fun2: sum = %d/n", fun2(a,10));
printf("fun3: sum = %d/n", fun3(a,10));
return 0;
}
//*******************************************************************************************