數據結構-劍指offer-連續子數組的最大和

題目:HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全爲正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和爲8(從第0個開始,到第3個爲止)。你會不會被他忽悠住?(子向量的長度至少是1)

思路:首先是對題目的理解:連續子數組並不是必須以array[0],只要是數組的子序列就可以。討論區有人做出的答案是17,不等於正確答案18的原因,就是因爲在編程的時候,只考慮了子序列從array[0]開始的情況。

①以最簡單的數組array={1,2, 3}爲例,可以這樣的方式對所有子序列進行考慮計算:len = array.size() = 3,第一輪從第一個元素開始(i=0,j=0,1,2)  {1}{1,2,3}{1,2,3},第二輪從第二個元素開始(i=1,j=1,2)  {2}{2,3},第三輪從第三個元素開始(i=2,j=2)  {3},這樣就考慮到了所有的情況。但這種思路的時間複雜度很高O(n^2),並不是一個好方法,在牛客運行時會出現錯誤:運行錯誤:請檢查是否存在數組、列表等越界非法訪問,內存非法訪問等情況。

代碼①:

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int len = array.size();
        int max_num = array[0];
        vector<int> sum;
        for(int i=0;i<len;i++){
            for(int j=i;j<len;j++){
                sum[i] +=array[j];
                if(sum[i]>max_num)
                    max_num = sum[i];
            }
        }
        return max_num;
    }
};

②對於一個數A,若A的左邊累計數非負,那麼加上A能使得值不小於A,認爲累計值對整體和死有貢獻的。如果前幾項累積值負數,則認爲有害於總和。這個思路的複雜度之後O(n),這一方法其實是基於只考慮從數組第一位數組元素開始的子序列的代碼的基礎上進行改進的。看討論區才知道這就是動態規劃。。。動態規劃要看一下了。

       動態規劃:通過把原問題分解成相對簡單的子問題的方式求解複雜問題的方法。動態規劃常適用於有重疊子問題和最優子結構性質的問題。基本思想:如果要解一個給定問題,我們需要解其不同部分(即子問題),再合併子問題的解以得出原問題的解。通常許多子問題非常相似,爲此動態規劃法師徒僅僅解決每個子問題一次,從而減少計算量:一旦某個給定子問題的解已經算出,則將其記憶存儲,以便下次需要同一個子問題解時直接查表。(動態規劃的主要思想就是保存中間結果

       動態規劃個分治:共同點:二者都要求原問題具有最優子結構性質,都是將原問題分而治之,分解成若干規模較小的子問題,然後將子問題的解合併,形成原問題的解。不同點:分治法將分解後的子問題看成相互獨立的,通過遞歸來做,動態規劃將分解後的子問題理解爲相互間有聯繫,有重疊部分,需要記憶,通常用迭代來做。

       典型問題:0-1揹包問題、最長公共子序列(不連續)、最長公共子串(連續)、KMP(硬幣找零問題)、類似硬幣的問題找平方個數最小、最長迴文字串、最長遞增序列等。

代碼(只考慮從數組第一位數組元素開始的子序列):

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int len = array.size();
        int sum = array[0];
        int maxsum = array[0];
        for(int i=0;i<len;i++){
            sum +=array[i];
            if(sum>maxsum)
                maxsum = sum;
        }
        return maxsum;
    }
};

本題正確的代碼:

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int len = array.size();
        int sum = array[0];
        int maxsum = array[0];
        for(int i=1;i<len;i++){
            if(sum >= 0)
                sum +=array[i];
            else
                sum = array[i];
            if(sum>maxsum)
                maxsum = sum;
        }
        return maxsum;
    }
};

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