-----
搜索用 java 算法 性能优化 web
-----
在看《计算机程序设计艺术-第一卷-基本算法》第一章时看到了一个有趣的等式,这个等式如下:
下面我们来看看这个等式的证明,建议大家自己先想想怎么去证明这个公式。
数学归纳法应该是可以证明的,好像也没什么意思,那么我们来看看下面的这个证明,最外层的每个小正方形边长为5
(看不到下面图片的请点击最下面的【查看全文】)
大家可以开动自己的脑筋去想想这个图是怎么证明上面的公式。。。。。。。。
答案可以看后面的解释。
当然我们是搞软件的,学这些数学知识干什么呢,这本书叫做程序设计艺术是不是搞错了啊,这么低级的错误应该不可能,这可是国防科技大学翻译的,看来这个东西和程序设计有关系啊,但是到底有什么用呢???
我们看等式前面如果在计算机上运行需要执行3n次乘法和n-1次加法,再看看等号后面的等式在计算机上运行会执行1次乘法和n-1次加法,这样看来用等号后面计算可以节省3n次乘法,乘法是很消耗CPU的
如果这个算法放在一个百万并发的网站上运行的话,我们就可以节省3*N*百万级次的乘法运行,有点小兴奋,看来写这个书的人,果然是大师级人物,在他看来就是艺术。。。
这个时候很好奇到底这样做能节省多少时间呢?于是写了个程序验证了等式左边和右边的所用的时间,左边执行时间平均是31秒,右边执行时间是17秒,才提升了14秒啊,问题又来了,17秒还可以优化吗?还能节省时间吗?
分析上面的时间分布可以知道,加法的时间一样,也就是说乘法使用了14秒,加法使用了17秒,想要优化后面的17秒就必须减少加法次数。
问题定位为怎么提高(1+2+...+n)的效率,相信大家都会了。
1+2+...n=n*(n+1)/2,哇塞,最后又得到左边的等式还等于(n*(n+1)/2)*(n*(n+1)/2),经过这个变换后,我们计算右边的结果的算法复杂度是2次乘法,1次加法,1次除法。
比较3个算法复杂度:
左边:3*n次乘法和n-1次加法
右边(未优化):n-1次加法
右边(优化后):2次乘法,1次加法,1次除法
很明显,优化后的算法已经和n没有关系了,不管业务上的n如果变化都不会影响到执行时间,梦寐以求的算法啊!!
下面是一个验证程序:
/*
* 创建日: 2011-6-16
*/
public class TestMain {
/**
* @param args
*/
public static void main(String[] args) {
TestMain tm = new TestMain();
long start =System.currentTimeMillis();
int index;
for(index=0;index<1000000;index++) {
tm.leftsum(10000);
}
long end =System.currentTimeMillis();
System.out.println(end-start);
//******************************
start =System.currentTimeMillis();
for(index=0;index<1000000;index++) {
tm.rightsum(10000);
}
end =System.currentTimeMillis();
System.out.println(end-start);
//******************************
start =System.currentTimeMillis();
for(index=0;index<1000000;index++) {
tm.rightsum1(10000);
}
end =System.currentTimeMillis();
System.out.println(end-start);
}
private long leftsum(int n) {
long ret =0;
for (int index=1;index<=n;index++) {
ret = ret + index*index*index;
}
return ret;
}
private long rightsum(int n) {
long ret =0;
for (int index=1;index<=n;index++) {
ret = ret + index;
}
return ret*ret;
}
private long rightsum1(int n) {
long ret =0;
ret = n*(n+1)/2;
return ret*ret;
}
}
打印的结果是:
31000
16922
0
第三个算法的执行时间是0,第三个算法执行了200万次乘法,100万次加法,100万次除法,CPU太快了,不花时间就搞定,充分说明以前听说的JAVA指令也是1秒钟可以执行上亿条的说法没问题。
其实还有一个遗留的问题,就是怎么证明上面的图形是正确的呢??
通过这个1+2+...+n=n*(n+1)/2就可以证明了。