一个有趣的等式 (搜索用:优化 java 算法)

-----

搜索用 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就可以证明了。


 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值