數據結構01 算法的時間復雜度和空間復雜度


1、算法的概念:

算法 (Algorithm),是對特定問題求解步驟的一種描述。

解決一個問題往往有不止一種方法,算法也是如此。那么解決特定問題的多個算法之間如何衡量它們的優劣呢?有如下的指標:

2、衡量算法的指標:

(1)時間復雜度:執行這個算法需要消耗多少時間。

(2)空間復雜度:這個算法需要占用多少內存空間。

  同一個問題可以用不同的算法解決,而一個算法的優劣將影響到算法乃至程序的效率。算法分析的目的在於為特定的問題選擇合適算法。一個算法的評價主要從時間復雜度和空間復雜度來考慮

  算法在時間的高效性和空間的高效性之間通常是矛盾的。所以一般只會取一個平衡點。通常我們假設程序運行在足夠大的內存空間中,所以研究更多的是算法的時間復雜度。

 

3、算法的時間復雜度

  (1)語句頻度T(n): 一個算法執行所花費的時間,從理論上是不能算出來的,必須上機運行測試才能知道。但我們不可能對每個算法都上機測試,只需知道哪個算法花費的時間多,哪個算法花費的時間少就可以了。 而且一個算法花費的時間與算法中的基本操作語句的執行次數成正比例,哪個算法中語句執行次數多,它花費時間就多。一個算法中的語句執行次數稱為語句頻度,記為T(n)。
 
  (2)時間復雜度: 在剛才提到的語句頻度中,n稱為問題的規模,當n不斷變化時,語句頻度T(n)也會不斷變化。但有時我們想知道它的變化呈現什么規律。為此,我們引入時間復雜度概念。 一般情況下,算法中的基本操作語句的重復執行次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近於無窮大時,T(n) / f(n) 的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函數。記作 T(n)=O( f(n) ),稱O( f(n) )  為算法的漸進時間復雜度,簡稱時間復雜度。
  T(n) 不同,但時間復雜度可能相同。 如:T(n)=n²+5n+6 與 T(n)=3n²+3n+2 它們的T(n) 不同,但時間復雜度相同,都為O(n²)。
 
  (3)常見的時間復雜度有:常數階O(1),對數階O(log 2n),線性階O(n),線性對數階O(nlog 2n),平方階O(n 2),立方階O(n 3), k次方階O(n k),指數階O(2 n)。隨着問題規模n的不斷增大,上述時間復雜度不斷增大,算法的執行效率越低。

 

  (4)平均時間復雜度和最壞時間復雜度:

    平均時間復雜度是指所有可能的輸入實例均以等概率出現的情況下,該算法的運行時間。

    最壞情況下的時間復雜度稱最壞時間復雜度。一般討論的時間復雜度均是最壞情況下的時間復雜度。 這樣做的原因是:最壞情況下的時間復雜度是算法在任何輸入實例上運行時間的界限,這就保證了算法的運行時間不會比最壞情況更長。

    

  (5)如何求時間復雜度:  

  【1】如果算法的執行時間不隨着問題規模n的增加而增長,即使算法中有上千條語句,其執行時間也不過是一個較大的常數。此類算法的時間復雜度是O(1)。
    public static void main(String[] args) {
        int x = 91;
        int y = 100;
        while (y > 0) {
            if (x > 100) {
                x = x - 10;
                y--;
            } else {
                x++;
            }
        }
    }
該算法的時間復雜度為:O(1) 
這個程序看起來有點嚇人,總共循環運行了1100次,但是我們看到n沒有?
沒。這段程序的運行是和n無關的,
就算它再循環一萬年,我們也不管他,只是一個常數階的函數
 
  【2】當有若干個循環語句時,算法的時間復雜度是由嵌套層數最多的循環語句中最內層語句的頻度f(n)決定的。
1         int x = 1;
2         for (int i = 1; i <= n; i++) {
3             for (int j = 1; j <= i; j++) {
4                 for (int k = 1; k <= j; k++) {
5                     x++;
6                 }
7             }
8         }
該算法的時間復雜度為:O(n 3)  
該程序段中頻度最大的語句是第5行的語句,內循環的執行次數雖然與問題規模n沒有直接關系,但是卻與外層循環的變量取值有關,而最外層循環的次數直接與n有關,因此該程序段的時間復雜度為 O(n 3)  
 
  【3】算法的時間復雜度不僅僅依賴於問題的規模,還與輸入實例的初始狀態有關。
  在數值 A[n-1,n-2 ...0] 中查找給定值k的算法大致如下:   
1         int i = n - 1;
2         while (i >= 0 && (A[i] != k)) {
3             i--;
4         }
5         return i;
該算法的時間復雜度為:O(n)    
此算法中第3行語句的頻度不僅與問題規模n有關,還與輸入實例A中的各元素取值和k的取值有關:如果A中沒有與k相等的元素,那么第3行語句的頻度為 f(n)=n ,該程序段的時間復雜度為 O(n)  
 
 
  (6)用時間復雜度來評價算法的性能 
    用兩個算法A 1和A 2求解同一問題,時間復雜度分別是O(100n 2),O(5n 3)
    (1) 5n 3/100n 2=n/20 ,當輸入量n<20時,100n > 5n 3 ,這時A 2花費的時間較少。
    (2)隨着問題規模n的增大,兩個算法的時間開銷之比 5n 3/100n 2=n/20 也隨着增大。即當問題規模較大時,算法A 1比算法A 2要高效的多。 它們的漸近時間復雜度O(n2)和O(n3) 評價了這兩個算法在時間方面的性能。在算法分析時,往往對算法的時間復雜度和漸近時間復雜度不予區分,而經常是將漸近時間復雜度 O(f(n)) 簡稱為時間復雜度,其中的f(n)一般是算法中頻度最大的語句頻度。

 

4、算法的空間復雜度  

   空間復雜度(Space Complexity) 是對一個算法在運行過程中臨時占用存儲空間大小的量度,記做 S(n)=O(f(n)) ,其中n為問題的規模。利用算法的空間復雜度,可以對算法的運行所需要的內存空間有個預先估計。
  一個算法執行時除了需要存儲本身所使用的指令、常數、變量和輸入數據外,還需要一些對數據進行操作的工作單元和存儲一些計算所需的輔助空間。算法執行時所需的存儲空間包括以下兩部分。   
(1)固定部分。這部分空間的大小與輸入/輸出的數據的個數、數值無關。主要包括指令空間(即代碼空間)、數據空間(常量、簡單變量)等所占的空間。這部分屬於靜態空間。
(2)可變空間,這部分空間的主要包括動態分配的空間,以及遞歸棧所需的空間等。這部分的空間大小與算法有關。
  舉例分析算法的空間復雜度:
    public void reserse(int[] a, int[] b) {
        int n = a.length;
        for (int i = 0; i < n; i++) {
            b[i] = a[n - 1 - i];
        }
    }

上方的代碼中,當程序調用 reserse() 方法時,要分配的內存空間包括:引用a、引用b、局部變量n、局部變量i

因此 f(n)=4 ,4為常量。所以該算法的空間復雜度 S(n)=O(1)  

 

5、總結

算法的時間復雜度和兩個因素有關:算法中的最大嵌套循環層數;最內層循環結構中循環的次數。

一般來說,具有多項式時間復雜度的算法是可以接受的;具有指數(不是對數)時間復雜度的算法,只有當n足夠小時才可以使用。一般效率較好的算法要控制在O(log2n) 或者 O(n)

 

歡迎轉載,但請保留文章原始出處

本文地址:http://www.cnblogs.com/nnngu/p/8245787.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM