前些天學車...真是至關累啊,比上課累,如今終於能夠休息了...ios
從新看《算法導論》,不過這下可得認真看了,9個月不到就得去找工做了,與我一樣的大三黨們同樣加油咯...算法
《算法導論》中引入這個問題是經過股票的購買與出售,將前一天的當天的股票差價從新表示出來,即轉爲了一個最大子數組的問題,具體內容我很少說,轉的內容是:數組
13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7spa
找到這連續的16個數裏面的連續和最大的子數組;設計
書中練習部分說用設計非遞歸的,線性時間的算法,我就YY爲動態規劃處理了;code
從數組的左邊界開始,從左至右處理,記錄到目前爲止已經處理過的最大子數組。若已知A[1..j]的最大子數組,基於以下性質將解擴展爲A[1...j+1]的最大子數組:A[1...j+1]的最大子數組要麼是A[1...j]的最大子數組,要麼是某個子數組A[i...j+1](1<=i<=j+1)。在已知A[1...j]的最大子數組的狀況下,能夠在線性時間內找出形如A[i...j+1]的最大子數組;遞歸
思想上述都將出來了,只要將關鍵點寫出便可:io
若是前面若干和<0,則其對後面子數組相加無幫助,此時重置dp爲array[i],而且記錄的起始位置從新標記;class
if(dp[i - 1] <= 0) //前面的<0,直接丟棄 { dp[i] = array[i]; temp = i; //記錄起始爲止 }
不然,繼續日後延伸;stream
dp[i] = array[i] + dp[i - 1]; //日後求和
最後判斷最大子數組值就行,同時標記起始與結束位置:
if(dp[i] > MaxSumSub) //找到到i爲止的最大子數組 { MaxSumSub = dp[i]; //最大... start = temp; //標記起始 end = i; //標記此時的結束位置 }
代碼:
#include <iostream> using namespace std; int FindMaxSubarray(int array[], int length) { int start = 0, end = 0; //記錄最大子數組的起始位置(在數組中的下標) int MaxSumSub; //最大子數組的值 int* dp = new int[length]; //動態規劃記錄 dp[0] = array[0]; //初始爲第一個數 MaxSumSub = dp[0]; //最大值初始爲第一個數 int temp = 0; // for(int i = 1; i < length; i++) { if(dp[i - 1] <= 0) //前面的<0,直接丟棄 { dp[i] = array[i]; temp = i; //記錄起始爲止 } else dp[i] = array[i] + dp[i - 1]; //日後求和 if(dp[i] > MaxSumSub) //找到到i爲止的最大子數組 { MaxSumSub = dp[i]; //最大... start = temp; //標記起始 end = i; //標記此時的結束位置 } } cout<<"最大子序列的下標:"<<start<<"->"<<end<<endl; return MaxSumSub; } int main() { int a[] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7}; //int a[] = {23, 4}; int length = sizeof(a) / sizeof(int); cout<<FindMaxSubarray(a, length); return 0; }
最大子序列即爲{18, 20, -7, 12};
上述dp即爲動態記錄尋找最大子數組的過程,你們也能夠進行輸出看一下;
歡迎你們指點,o(∩_∩)o