一個有趣的等式 (搜索用:優化 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就可以證明了。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章