题目
有整数数组int a[]={-1,2,-3,10,-4,7,2,5},找出此数组的一个连续子序列,使得该子序列的和最大。可以得到子序列{10,-4,7,2,5}的和20最大,输出该子序列
分析
设sum[i]为0到i元素数组的最大子序列和,那么sum[i-1]是它的子问题解,可以利用动态规划求解。有关系式
sum[0]=a[0];
sum[i]=a[j],当sum[i-1]<0;
sum[i]=sum[i-1]+a[j],当sum[i-1]>=0;
算法复杂度为O(n),空间复杂度O(1)
代码
int MaxSubSumOfArray(int arr[],int len,int& sub_s,int& sub_e) { if (arr==NULL||len<=0) { throw std::exception("Invalid input."); } int sum=arr[0]; int max=sum; int sidx=0,eidx=0; for(int i=1;i<len;i++) { if(sum<0) { sum=arr[i]; sidx=i; eidx=i; }else { sum=sum+arr[i]; eidx++; } //max=(max>sum)?max:sum; if (max<=sum) { max=sum; sub_s=sidx; sub_e=eidx; } } return max; }
题目
现有矩阵:
0, -2, -7, 0, 3
9, 2, -6, 2, 5
-4, 1, -4, 1, 6
-1, 8, 0, -2, 2
求该矩阵的一个子矩阵,使子矩阵所有元素的和最大
分析
对于最大子矩阵和sum来说,是子矩阵所有元素相加的和,即可以先同一列上的元素相加,多行降维成一行,进而可以转化为求最大子序列和的问题。循环对矩阵不同行的组合进行降维求最大子序列和,进而求出和最大的那个行组合,即可得到最大子矩阵和。
算法时间复杂度O(n*n*m)
代码
int MaxSumOfMatrix(int **matrix,int row_len,int column_len) { if (matrix==NULL||row_len<=0||column_len<=0) { throw std::exception("Invalid input."); return -1; } int max=0; //申请二维数组空间 int **sumMatrix=new int*[row_len]; for (int i=0;i<row_len;i++) { sumMatrix[i]=new int[column_len](); } //依次求0到i列累加和 for (int row=0;row<row_len;row++) { for (int col=0;col<column_len;col++) { if (row==0) { sumMatrix[row][col]=matrix[row][col]; }else { sumMatrix[row][col]=sumMatrix[row-1][col]+matrix[row][col]; } } } int* tmp_arr=new int[column_len](); for (int row=0;row<row_len;row++) { for (int rowx=row;rowx<row_len;rowx++) { for (int col=0;col<column_len;col++) { if (row>0) { tmp_arr[col]=sumMatrix[rowx][col]-sumMatrix[row-1][col]; }else { tmp_arr[col]=sumMatrix[rowx][col]; } } int col_s=0,col_e=0; int re=MaxSumOfArray2(tmp_arr,column_len,col_s,col_e); max=(max>re)?max:re; } } //释放 for (int i=0;i<row_len;i++) { delete[] sumMatrix[i]; } delete[] sumMatrix; delete[] tmp_arr; return max; }