求数组的子数组之和的最大值

吐舌头解法一:

先明确题意:
  1.题目说的子数组,是连续的。
  2.题目只需要求和,并不需要返回子数组的具体位置。
  3.数组的元素是整数,所以数组可能只包含有正整数,零,负整数。

举几个例子:
数组:[1,-2,3,5,-3,2]应返回8.
数组:[0,-2,3,5,-1,2]应返回9。
数组:[-9,-2,-3,-5,-3]应返回-2。

最直接的方法:
     记sum[i,....,j]为数组A中第i个元素到第j个元素的和,(其中0<=i<=j<n),遍历所有可能的Sum[i,...j],那么时间复杂度为O(N3). N3表示N的立方。
int  MaxSum(int* A, int n)
{
int maximum = -INF;
int sum;
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
for (int k = i; k <= j; k++)
{
sum += A[k];
}
if (sum > maximum)
maximum = sum;
}
}
return maximum;
}

方法一的改进:       
       由于Sum[i,...,j]=Sum[i,...,j-1]+A[j].则可以将算法中的最后一个for循环省略。这时时间复杂度为O(N2).N2为N的平方。 代码如下:

int MaxSum(int *A, int n)
{
int maximum = -INF;
int sum;
for (int i = 0; i < n; i++)
{
sum = 0;
for (int j = i; j < n; j++)
{
sum += A[j];
if (sum > maximum)
maximum = sum;
}


}
return maximum;
}


微笑解法二:

吐舌头解法三:
     从分治算法中得到提示:可以考虑数组的第一个元素A[0],以及最大的一段数组(A[i],....,A[j])跟A[0]之间的关系。
有以下几种情况:

微笑解法二:
int max(int x, int y)
{
return (x>y) ? x : y;
}
int MaxSum(int* A, int n)
{
Start[n - 1] = A[n - 1];
All[n - 1] = A[n - 1];
for (i = n - 2; i >= 0; i--)
{
Start[i] = max(A[i], A[i] + Start[i + 1]);
All[i] = max(Start[i], All[i + 1]);
}
return A[0];
}
新方法的时间复杂度为:O(N)
但是又出现了一个新问题,额外申请了两个数组All[ ],Start[ ],能否节省空间呢?

int max(int x, int y)
{
return (x>y) ? x : y;
}
int MaxSum(int* A, int n)
{
nStart = A[n - 1];
nAll = A[n - 1];
for (i = n - 2; i >= 0; i--)
{
nStart = max(A[i], A[i] + nStart);
nAll = max(nStart, nAll);
}
return nAll;
}

尴尬换一种写法:
int MaxSum(int* A, int n)
{
nStart = A[n - 1];
nAll = A[n - 1];
for (i = n - 2; i >= 0;i--)
{
if (nStart < 0)
nStart = 0;
nStart += A[i];
if (nStart > nAll)
nAll = nStart;
}
return nAll;
}

微笑 扩展:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值