時間複雜度和空間複雜度

時間複雜度和空間複雜度是我們算法效率的度量方法。

 

時間複雜度我們用大O表示法,比如O(1),O(n),O(logn),O(n2)等,那麼這個是怎麼計算出來的呢。

 

簡單來說就是看某段代碼的執行次數。

注意:

  1.如果是常數級別的都是O(1),這裏的常數是指的我們已經很確定這段代碼執行多少次,不存在變化了。

  2.指數級的時候取最高階,比如n2+n,那麼是O(n2);

  3.常數我們通常忽略。

O(1)

 

        int a = 1;        
        for(int i = 0 ;i < 1000;i++){
            a = a + 1;
        }

 

這段代碼的時間複雜度就是O(1),不管他執行多少次,已經十分確定它是某一個值了

O(n):

 

        for(int i = 0 ;i < n;i++){
            a = a + 1;            
        }

 

這段代碼n是個未知數,因此它的時間複雜度是O(n)

O(logn):

 

    int i = 1;
    while( i <= n){
             i = i * 3;    
     }

 

這段代碼實際的執行次數,就是求3x=n,求出x=log3n(3爲底n的對數),忽略掉常數3,時間複雜度表示爲O(logn)

O(n2):

 

        for(i = 0 ; i < n;i++){    
            for(int j = 0 ; j < n ;j ++){        
                a = a +1;            
            }
        }

 

        for(i = 0 ; i <= n;i++){
            for(int j = i ; j <= n ;j ++){
                a = a +1;            
            }
        }

第一段代碼很好計算直接就是O(n2);

第二段代碼

i=n 運行1次

i=n-1 運行2次

i=n-2 運行3次

......

i=1 運行n次

明顯是個等差數列,總次數就是等差數列求和sn=n(n+1)/2=(n2+n)/2,忽略掉常數和低階,那麼就是O(n2)

 

 

空間複雜度

其實對於空間複雜度,我們經常都會用空間去換時間,比如一個List<Student>,要根據Student的ID去list裏面取元素,這種情況下我們並不知道index,每次都需要遍歷判斷,那麼每次取元素的時間複雜度都是O(n);我們就可以將ID作爲key,把List轉換成Map,每次從map中取就是O(1)了,但是這裏多出來了一個Map,會佔用更多內存空間。這就是用空間換時間。一般我們說的複雜度都是指的時間複雜度。

 

算法之美案例:判斷一個數是否是2的冪

算法1:

        while(n > 1){
            if (n % 2 == 0) {
                return true;
            }
            n = n / 2;
        }
        return false;

無限除以2再取模判斷是否等於0,如果最後取模2等於0,那麼說明是2的次冪。時間複雜度O(logn)

算法2:

        if (n <= 0) {
            return false;
        }
        return (n & (n-1)) == 0;

2的二進制表示:10  1的二進制:1

4的二進制表示:100  3的二進制:11

8的二進制表示:1000  7的二進制:111

利用&運算,如果n是2的次冪,那麼n&(n-1)剛好等於0,這個算法時間複雜度O(1)。

明顯算法2的性能是比算法1的性能好的。

時間複雜度優劣排行:O(1)>O(logn)>O(n)>O(nlogn)>O(n^2)>O(n^x)

 

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