子陣列問題分為三類:
1:連續子陣列
2:非連續子陣列
3:可連續也可以不連續
這三類問題的解決辦法一般都是迴圈或者動態規劃,嘗試了dfs演算法,結果把自己給繞進去了!
一:最大公升序問題(屬於第三類)
參考:1:動態規劃解法:
利用動態規劃來做,假設陣列為1, -1, 2, -3, 4, -5, 6, -7。我們定義lis[n]陣列,其中lis[i]用來表示以array[i]為最後乙個元素的最長遞增子串行。使用i來表示當前遍歷的位置:
當i = 0 時,顯然,最長的遞增序列為(1),則序列長度為1。則lis[0] = 1
當i = 1 時,由於-1 < 1,因此,必須丟棄第乙個值,然後重新建立序列。當前的遞增子串行為(-1),長度為1。則lis[1] = 1
當i = 2 時,由於2 > 1,2 > -1。因此,最長的遞增子串行為(1, 2),(-1, 2),長度為2。則lis[2] = 2。
當i = 3 時,由於-3 < 1, -1, 2。因此,必須丟掉前面的元素,重建建立序列。當前的遞增子串行為(-3),長度為1。則lis[3] = 1。
依次類推之後,可以得出如下結論。
lis[i] = max, array[i] >array[k], for any k < i
最後,我們取max。
這個通用解法可以實現求最大子陣列的長度和求和問題。網上還有一種迴圈的解法但是沒有回溯,得到的結果並不是我我們想要的額!
二:陣列非連續子串行的最大和
動態規劃:找遞推關係式!
從《程式設計之美》一題中得到啟發,我們是不是也可以用動態規劃的方法來解這道題呢?假設從原陣列a第i位開始的最大不連續子陣列和為m[ i ],那麼它的值有兩種可能,一種是當前元素a[ i ]與隔一位上子問題解m[ i+2 ]之和(由不連續性質決定),另一種是不包含當前元素而直接等於前一位上子問題解m[ i+1 ],那麼我們可以寫出遞推公式為:m[ i ] = max(a[ i ] + m[ i+2 ], m[ i+1 ])。
等等,也許你要說,好像這個遞推式有漏洞啊,因為前一位上的解m[ i+1 ]本身就有可能是包含或不包含a[ i+1 ],假如m[ i+1 ]不包含a[ i+1 ],那麼豈不是還要考慮a[ i ]+m[ i+1 ]這種可能性呢?
這個遞推式真的經不起推敲嗎?我們不妨重新整理一下思路:由於原陣列上每一元素都有取與不取兩種可能,那麼也就對應有包含和不包含該元素的兩個子陣列的最大和。對於原陣列a中第i位上的元素,假設包含a[ i ]元素的子陣列最大和為s[ i ],而不包含元素a[ i ]的子陣列最大和為ns[ i ],因此所要求的不連續子陣列最大和m[ i ] = max(s[ i ], ns[ i ])。那麼根據題意我們可以整理出遞推關係如下:
s[ i ] = max(a[ i ] + ns[ i+1 ], a[ i ] + m[ i+2 ])
ns[ i ] = m[ i+1 ]
m[ i ] = max(a[ i ] + ns[ i+1 ], a[ i ] + m[ i+2 ], m[ i+1 ])
有趣的地方在於ns[ i ] = m[ i+1 ]這一項上,根據它我們可以得到ns[ i+1 ] = m(i+2),也就是說假如m[ i+1 ]不包含a[ i+1 ]的話,那麼它一定等於m[ i+2 ],所以a[ i ]+ns[ i+1 ]等價於a[ i ] + m[ i+2 ],遞推式m[ i ] = max(a[ i ] + m[ i+2 ], m[ i+1 ])是正確的!
從《程式設計之美》給出的解法中得到啟發,我們也只需要使用兩個變數來記錄m[ i+2 ]和m[ i+1 ]的值就行了,而且同樣只需要o(n)的複雜度就可以解這道題,**如下:
#include
#include
using namespace std;
static int max(int a,int b)
int maxsubsum(int a , const int len)
return a[len-1];
}//程式設計之美的解法
int maxsum(int* a, int n)
return m1;
}int main( )
;int b= ;
int result_a = maxsubsum(a,4);
int result_b = maxsum(b,7);
cout << result_a << endl;
cout << result_b << endl;
return 0;
}
求子集問題
從訂閱部落格中看到這道題,於是花了上午的時間寫了一下,此題類似於 0 1揹包問題,故複習了一下,分別有遞迴和非遞迴的解法。題目 給定乙個數 t,以及 n個整數,在這 n個整數中找到相加之和為 t的所有組合,例如 t 4 n 6,這6 個數為 4,3,2,2,1,1 這樣輸出就有 4個不同的組合,它們...
求子陣列最大和
題目 輸入乙個整形陣列,陣列裡有正數也有負數。陣列中連續的乙個或多個整數組成乙個子陣列,每個子陣列都有乙個和。求所有子陣列的和的最大值。要求時間複雜度為o n 例如輸入的陣列為1,2,3,10,4,7,2,5,和最大的子陣列為3,10,4,7,2,因此輸出為該子陣列的和18。因為是o n 的複雜度,...
求子陣列的最大和
題目 輸入乙個整形陣列,陣列裡有正數也有負數。陣列中連續的乙個或多個整數組成乙個子陣列,每個子陣列都有乙個和。求所有子陣列的和的最大值。要求時間複雜度為o n 本題最初為2005年浙江大學計算機系的考研題的最後一道程式設計題,在2006年裡包括google在內的很多知名公司都把本題當作面試題。由於本...