1. 程式人生 > >動態規劃:連續子陣列的最大和

動態規劃:連續子陣列的最大和

這個題目寫了不下三遍了,次次寫還次次想不起來,想起來也還寫好幾遍才能寫對,求一串陣列的最大最大子序列和,用動態規劃的方法,簡直不要太高效。
比如下面這個陣列{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;
    }

希望我下次再碰到這種,不會再忘記了。。。。。。畢竟事不過三的。。