這個題目寫了不下三遍了,次次寫還次次想不起來,想起來也還寫好幾遍才能寫對,求一串數組的最大最大子序列和,用動態規劃的方法,簡直不要太高效。
比如下面這個數組{1,-2,3,10,-4,7,2,-5},最大連續子數組是{3,10,-4,7,2}和爲18,不過這個求解過程我們不需要知道最大連續子數組的範圍,只要知道值是18就可以。
動態規劃的思想就是找到子結構的關係!我們可以這麼切入這個關係結構,如果我們有個序列{1,-2,3},顯然最大子序列是{3},如果我們在這個序列後面再加入一個數t,我們怎麼去求加入一個數之後新的序列的連續子序列{1,-2,3,t}的最大和?
當然得抓住連續這個性質!
設以t爲序列尾的最大子序列和爲sum,則我們可以很直觀地看出sum=max{3+t,t},這樣理解起來很簡單,因爲3就在t前面,而我們已經知道以3爲結尾的最大連續子序列和就是3,這個3就是t繞不過去的一個坑。
知道這個關係後我們就可以由題目推出這樣一個式子;
設F[n]爲下標爲n結尾的連續子序列最大和,數組名爲num
推出:F[n]=max{F[n-1]+num[n]}
看到這個式子
由這個關係我們就可以很自然地去求解這個問題
代碼如下:
int FindMax(char num[],int size)
{
int *f = new int[size];
f[0] = num[0];
for (int i = 1; i < size; i++)
{
if (f[i - 1] + num[i] > num[i])
f[i] = f[i - 1] + num[i];
else
f[i] = num[i];
}
int max = f[0];
for (int i = 1; i < size; i++)
if (max < f[i])
max = f[i];
delete[] f;
return max;
}
可是代碼雖然容易看懂,但是我們卻開了一塊輔助數組啊,這可要不得,僅僅就求個最大和我卻開了數組?完全沒必要啊,我只要在求f[i]時順帶和max比較下不就行了,而且公式告訴我們了,F[n]只和F[n-1]和num[n]有關係啊,那我存這麼多數幹嘛???所以我們就簡化下代碼如下
int FindMax(int num[],int size) {
if(size<=0)return 0;
int max=num[0];
int tmp=num[0];
for(int i=1;i<size;i++)
{
tmp=tmp+num[i];
if(num[i]>tmp)
tmp=num[i];
if(tmp>max)
max=tmp;
}
return max;
}
希望我下次再碰到這種,不會再忘記了。。。。。。畢竟事不過三的。。