求最大子序列和--体会算法的魅力

算法,即我们解决问题的策略。优秀的算法可以简化复杂的问题,大大减少计算机运行的时间。

以求最大子序列和为例初步体会算法的威力。

给定一个数值数组啊a[10]={ 3, -1, 5, -3, 2, 5, -6, 4, 1, -2 },要求它的最大子序列和。最简单的想法是:从第一个元素开始依次计算每一项子序列,然后找出最大值即可。这种方法容易想到,也是可行的,可通过如下代码实现:

#include<iostream>
using namespace std;
int main()
{
int a[10] = { 3, -1, 5, -3, 2, 5, -6, 4, 1, -2 };
int max = 0;
for (int i = 0; i < 10; i++)
{
int sum = 0;
for (int j = i; j < 10; ++j)
{
sum += a[j];
if (sum > max)
max = sum;
}
}
cout << max;
return 0;
}

我们分析一下该算法可以发现在运算中进行了大量重复运算:第一个数字运算n次(数组长度),第二个数字运算n + n-1次。。。显然若n很大时会造成巨大的浪费。

我们可以用折半的思想进行简化问题:把数组一分为二,分别计算前半部分最大子序列和a和后半部分的最大子序列和b,再分别计算前半部分包含最后一项的最大序列和c,以及后半部分包含后半部分第一项的最大序列和d。然后比较a、b、c+d,最大者即为最大子序列和。这种方法较上一种的运算量少了一半左右,但数组很大时计算量依旧很大。

现在我们采用一种更为简洁的方法:

#include<iostream>
using namespace std;
int main()
{
int a[10] = { 3, -1, 5, -3, 2, 5, -6, 4, 1, -2 };
int sum = 0;
for (int i = 0; i < 10; i++)
{
sum += a[i];
if (sum > max)
max = sum;
if (sum < 0)                      //若前i项和小于0,则最大子序列和不可能包含前i项,故舍弃前i项,从i+1项计算最大子序列和;这样每个数只会运算一次。
sum = 0;
}
cout << max;
return 0;
}

这三种算法在n较小时(例如上述的10)计算速度几乎无差别,编译运行后立刻计算出结果。

但n较大时(笔者用100000做测试)会有明显的差异,第三种算法依旧可以立即运算出结果,但前两种算法则运行了较长时间(大约15s)。

优良算法的威力可见一斑。尤其是处理复杂的数据时采用优良的算法更是极为必要。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值