數據結構2:算法時間複雜度和空間複雜度的計算

算法,即解決問題的方法。同一個問題,使用不一樣的算法,雖然獲得的結果相同,可是耗費的時間和資源是不一樣的。算法


就好比要擰一個螺母,使用扳手仍是鉗子是有區別的,雖然使用鉗子也能擰螺母,可是沒有扳手好用。

「條條大路通羅馬」,解決問題的算法有多種,這就須要判斷哪一個算法「更好」。數組

算法VS程序

不少人誤覺得程序就是算法,其實否則:算法是解決某個問題的想法、思路;而程序是在心中有算法的前提下編寫出來的能夠運行的代碼。

例如,要解決依次輸出一維數組中的數據元素的值的問題,首先想到的是使用循環結構( for 或者 while ),在有這個算法的基礎上,開始編寫程序。

因此,算法至關因而程序的雛形。當解決問題時,首先心中要有解決問題的算法,圍繞算法編寫出程序代碼。瀏覽器

有算法必定能解決問題嗎?

對於一個問題,想出解決的算法,不必定就能解決這個問題。

例如擰螺母,扳手相對於鉗子來講更好使(選擇算法的過程),可是在擰的過程(編寫程序的過程)中發現螺母生鏽擰不動,這時就須要另想辦法。

爲了不這種狀況的發生,要充分全面地思考問題,儘量地考慮到全部地可能狀況,慎重選擇算法(須要在實踐中不斷地積累經驗)。學習

「好」算法的標準

對於一個問題的算法來講,之因此稱之爲算法,首先它必須可以解決這個問題(稱爲準確性)。其次,經過這個算法編寫的程序要求在任何狀況下不能崩潰(稱爲健壯性)。

若是準確性和健壯性都知足,接下來,就要考慮最重要的一點:經過算法編寫的程序,運行的效率怎麼樣。

運行效率體如今兩方面:spa

  • 算法的運行時間。(稱爲「時間複雜度」)
  • 運行算法所需的內存空間大小。(稱爲「空間複雜度」)


好算法的標準就是:在符合算法自己的要求的基礎上,使用算法編寫的程序運行的時間短,運行過程當中佔用的內存空間少,就能夠稱這個算法是「好算法」。設計

調查代表,人們對於軟件或者 APP 的運行效率有極高的要求,例如對於網頁打開的忍耐極限是 6 秒甚至更短,若是你設計的網頁打開的時間超過 6 秒,多數人會在 4 秒甚至 3 秒的時候堅決果斷地關掉而去瀏覽其餘網頁。在這個大背景下,一個好的「算法」更注重的是時間複雜度,而空間複雜度只要在一個合理的範圍內就能夠。

時間複雜度的計算

計算一個算法的時間複雜度,不可能把全部的算法都編寫出實際的程序出來讓計算機跑,這樣會作不少無用功,效率過低。實際採用的方法是估算算法的時間複雜度。

在學習C語言的時候講過,程序由三種結構構成:順序結構、分支結構和循環結構。順序結構和分支結構中的每段代碼只運行一次;循環結構中的代碼的運行時間要看循環的次數。

因爲是估算算法的時間複雜度,相比而言,循環結構對算法的執行時間影響更大。因此,算法的時間複雜度,主要看算法中使用到的循環結構中代碼循環的次數(稱爲「頻度」)。次數越少,算法的時間複雜度越低。

例如:
a) ++x; s=0;
b) for (int i=1; i<=n; i++) { ++x; s+=x; }
c) for (int i=1; i<=n; i++) { for (int j=1; i<=n; j++) { ++x; s+=x; } }

上邊這個例子中,a 代碼的運行了 1 次,b 代碼的運行了 n 次,c 代碼運行了 n*n 次。code

時間複雜度的表示

算法的時間複雜度的表示方式爲:排序

O(頻度)

這種表示方式稱爲大「O」記法內存

注意,是大寫的字母O,不是數字0

對於上邊的例子而言,a 的時間複雜度爲O(1),b 的時間複雜度爲O(n),c 的時間複雜度爲爲O(n2)

若是a、b、c組成一段程序,那麼算法的時間複雜度爲O(n2+n+1)。但這麼表示是不對的,還須要對n2+n+1進行簡化。

簡化的過程總結爲3步:資源

  • 去掉運行時間中的全部加法常數。(例如 n2+n+1,直接變爲 n2+n)
  • 只保留最高項。(n2+n 變成 n2
  • 若是最高項存在可是係數不是1,去掉係數。(n係數爲 1)


因此,最終a、b和c合併而成的代碼的時間複雜度爲O(n2)

經常使用的時間複雜度的排序

列舉了幾種常見的算法時間複雜度的比較(又小到大):

O(1)常數階 < O(logn)對數階 < O(n)線性階 < O(n2)平方階 < O(n3)(立方階) < O(2n) (指數階)

拿時間換空間,用空間換時間

算法的時間複雜度和空間複雜度是能夠相互轉化的。

谷歌瀏覽器相比於其餘的瀏覽器,運行速度要快。是由於它佔用了更多的內存空間,以空間換取了時間。

算法中,例如判斷某個年份是否爲閏年時,若是想以時間換取空間,算法思路就是:當給定一個年份時,判斷該年份是否能被4或者400整除,若是能夠,就是閏年。

若是想以空間換時間的話,判斷閏年的思路就是:把全部的年份先判斷出來,存儲在數組中(年份和數組下標對應),若是是閏年,數組值是1,不然是0;當須要判斷某年是否爲閏年時,直接看對應的數組值是1仍是0,不用計算就能夠立刻知道。

相關文章
相關標籤/搜索