前些天学车...真是至关累啊,比上课累,如今终于能够休息了...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