動態規劃:連續子數組的最大和

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章