题目
有整数数组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;
}