最大子列和函数
意识到自己代码部分的薄弱,这周起开始刷leetcode,将一些比较重要的笔记记录于此。此算法参考浙大数据结构课程(陈越,何钦铭)
给定N个整数的序列{A1,A2,…,ANA_1,A_2,\dots,A_NA1,A2,…,AN},求函数f(i,j)=max{0,Σk=1jAk}f(i,j)=max \{0,\Sigma_{k=1}^jA_k\}f(i,j)=max{0,Σk=1jAk}的最大值
(1)暴力求解
int MaxSubseqSum1(int A[],int N)
{
int ThisSum,MaxSum=0;
int i,j,k;
for(i=0;i<N;i++){//i是子列左端位置
for(j=i;j<N;j++){//j是子列右端位置
ThisSum = 0;//从A[i]到A[j]的子列和
for(k=i;k<=j;k++)
ThisSum += A[k];
if(ThisSum>MaxSum)
MaxSum = ThisSum;
}
return MaxSum;
}
}
T(N)=O(N3)T(N)=O(N^3)T(N)=O(N3)
(2)减少一层循环
int MaxSubseqSum2(int A[],int N)
{
int ThisSum,MaxSum=0;
int i,j;
for(int i=0;i<N;i++){
for(int j=i;j<N;j++){
ThisSum += A[j];//对于相同的i,不同的j,只要在j-1次循环的基础上累加1项
if(ThisSum>MaxSum)
MaxSum = ThisSum;
}
}
return MaxSum;
}
T(N)=O(N3)T(N)=O(N^3)T(N)=O(N3)
(3)分而治之
最大子列和=max{左列最大值右列最大值跨界最大值
最大子列和=max\begin{cases}左列最大值\\右列最大值\\跨界最大值\end{cases}
最大子列和=max⎩⎪⎨⎪⎧左列最大值右列最大值跨界最大值
T(N)=2T(N/2)+cNT(N)=2T(N/2)+cNT(N)=2T(N/2)+cN
=2[2T(N/22)+cN/2]+cN=2[2T(N/2^2)+cN/2]+cN=2[2T(N/22)+cN/2]+cN
=2kO(1)+ckN=2^kO(1)+ckN=2kO(1)+ckN
其中,N/2k=1N/2^k=1N/2k=1,k=log2Nk=log_2Nk=log2N
故T(N)=NlogNT(N)=NlogNT(N)=NlogN
int Max3(int A,int B,int C)
{
return A>B?(A>C?A,C):(B>C?B:C);
}
int DivideAndConquer(int List[],int left,int right){
int MaxLeftSum,MaxRightSum;//存放左右子问题的解
int MaxLeftBorderSum,MaxRightBorderSum;//存放跨分界线结果
int LeftBorderSum,RightBorderSum;
int center,i;
if(left==right){//递归终止条件
if(List[left]>0)
return List[left];
else return 0;
}
//分
center = (left+right)/2;//找到中分点
//递归求左右两边子列的最大和
MaxLeftSum = DivideAndConquer(List,left,center);
MaxRightSum = DivideAndConquer(List,center+1,right);
//求跨界子列的最大和
//左边,从右向左扫
MaxLeftBorderSum = 0;
LeftBorderSum = 0;
for(i=center;i>=left;i--){
LeftBorderSum += List[i];
if(LeftBorderSum > MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}
//右边,从左至右
MaxRightBorderSum = 0;
RightBorderSum = 0;
for(i=center+1;i<=right;i++){
RightBorderSum += List[i];
if(RightBorderSum > MaxRightBorderSum)
MaxRightBorderSum = RightBorderSum;
}
//返回治的结果
return Max3(MaxLeftSum,MaxRightSum,MaxRightBorderSum+MaxLeftBorderSum)
}
//保持形式上相同
int MaxSubseqSum3(int List[],int N)
{
return DivideAndConquer(List,0,N-1);
}
(4)在线处理
int MaxSubseqSum4(int A[],int N){
int ThisSum,MaxSum;
int i;
ThisSum = MaxSum = 0;
for(i=0;i<N;i++){
ThisSum += A[i];//向右累加
if(ThisSum>MaxSum)
MaxSum = ThisSum;//发现更大和则更新当前结果
else if(ThisSum<0)
ThisSum = 0;
}
return MaxSum;
}
T(N)=O(N)T(N)=O(N)T(N)=O(N)