您的位置:首页 > 编程语言

算法设计的几种思维(编程珠玑算法学习总结)

2016-01-14 22:21 405 查看


原题是一个一维模式识别的题:求n个浮点数向量中连续若干个子向量中的最大和。

在书中共讨论了四种算法:

第一种算法是最笨的办法,利用三重循环求出每一个子向量的和,然后求出其中的最大值,其时间复杂度为O(n3)

int maxvect(int *x,int n)

{

int maxsofar=0;

for(int i=0;i<n;i++)

{

for(int j=0;j<n;j++)

{

sum=0;

for(int k=i;k<=j;k++)

{

sum+=x[k];

}

maxsofar=max(maxsofar,sum);

}

}

return maxsofar;

}

第二种算法分了两种,其一是在求x[1...i]时利用x[1...i-1]的值,则减少了一层内循环,第二种是将计算的和的子向量存储在一个数组中,又可称为累积表,这样每个子向量的和都可由累计表中两项相减得到。这两种算法的时间复杂度都是O(n2)

第一种:

int maxvect(int *x,int n)

{

int maxsofar=0;

for(int i=0;i<n;i++)

{

sum=0;

for(int j=0;j<n;j++)

{

sum+=x[j];

maxsofar=max(maxsofar,sum);

}

}

return maxsofar;
}
第二种:

int maxvect(int *x,int n)

{

int maxsofar=0;

int *cumarr=new int[n+1];

cumarr[0]=0;

for(int i=0;i<n;i++)

{
cumarr[i+1]=cumarr[i]+x[i];

}

for(int i=0;i<n;i++)

{

sum=0;

for(int j=i;j<n;j++)

{

sum=cumarr[j+1]-cumarr[i];

maxsofar=max(maxsofar,sum);

}

}

return maxsofar;
}
第三种算法为分治算法,即分别求两个子向量的最大和,然后在划分,最后合并起来,它的时间复杂度为O(nlogn),在《算法导论》也提到了使用分治算法解这个题的详细分析过程。这里我没有仔细研究。
第四种算法扫描算法。它的思想是只扫描一次,记下遇到的子向量的总和最大的子向量,它的问题是如何有X[0...i-1]扩展为X[0...i],,它的做法是设立一个结束标志maxending,它的时间复杂度为O(n)

int maxvect(int *x,int n)

{

int maxsofar=0;

int maxendnig=0;

for(int i=0;i<n;i++)

{

maxending=max(maxending+x[i],0);

maxsofar=max(maxsofar,maxending);

}

}

return maxsofar;
}

在实际比较几种算法的运行时间时,我非常直观的体会的算法对于程序运行性能的影响。我用了10000个数的数组,第四种算法几乎瞬间完成,而第一种算法就需要若干分钟,具体性能比较我没有截图,不过《编程珠玑》第8章有详细的对比,有兴趣的查看,数据量越大,这种差距越大。

最后书中总结了几种算法设计的技术:

1.保存中间状态,避免重复计算。

2.预处理数据,存入一个结构中,如算法2中的累计表,是非常常用的一个手段。

3. 分治算法。

3. 扫描算法。利用X[0...i],扩展到X[0...i+1]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: