一.時間復雜度
一個算法中的語句執行次數稱為語句頻度或時間頻度,記為T(n)。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)) 為算法的漸進時間復雜度。
時間頻度不相同時,漸進時間復雜度O(f(n)) 有可能相同,
T(n)=n^2+3n+4與T(n)=4n^2+2n+1它們的頻度不同,但時間復雜度相同,都為O(n^2)。
現在我們根據一些書本上和網絡上對時間復雜度概念的描述進行一下總結:
T(n),語句頻度,時間頻度,亦稱為時間復雜度。
O(f(n)),漸進時間復雜度。
前者T(n)是某個算法的時間耗費,它是該算法所求解問題規模 n的函數,而后者O(f(n))是指當問題規模趨向無窮大時,該算法時間復雜度的數量級。當我們評價一個算法的時間性能時,主要標準就是算法的漸近時間復雜度O(f(n)),因此,在算法分析時,往往對兩者不予區分,經常是將漸近時間復雜度T(n)=O(f(n))簡稱為時間復雜度,其中的f(n)一般是算法中頻度最大的語句頻度。
注意:算法中語句的頻度不僅與問題規模有關,還與輸入實例中各元素的取值相關。但是我們總是考慮在最壞的情況下的時間復雜度。以保證算法的運行時間不會比它更長。
簡單的說,就是保留求出次數的最高次冪,并且把系數去掉。 如
T(n)=2n^2+n+1 =O(n^2)
二.常見的時間復雜度
在編碼方法中,時間復雜度當然越小越優:
常數階O(1)、對數階O(log2n)或O(lbn)、線性階O(n)、線性對數階O(n*log2n)、
平方階O(n^2)、立方階O(n^3)、k次方階O(n^k)、指數階O(2^n)。
例子:計算 1 + 2 + 3 + 4 + ...... + 100。
常規算法,代碼如下:
int main()
{
int i, sum = 0, n = 100; /* 執行1次 */
for( i = 1; i <= n; i++) /* 執行 n+1 次 */
{
sum = sum + i; /* 執行n次 */
//printf("%d \n", sum);
}
printf("%d", sum); /* 執行1次 */
}
上面代碼的算法時間復雜度,我們把它記作: O(n)。
再來看看高斯的算法,代碼如下:
int main()
{
int sum = 0, n = 100; /* 執行1次 */
sum = (1 + n) * n/2; /* 執行1次 */
printf("%d", sum); /* 執行1次 */
}
這個算法的時間復雜度記作 O(1)。
從感官上我們就不難看出,從算法的效率上看,O(1) < O(n) 的,所以高斯的算法更快,更優秀。
這也就難怪為什么每本算法書開篇都是拿高斯的這個例子來舉例了。
三.時間復雜度的計算題
例1:
Temp=i;
i=j;
j=temp;
以上三條單個語句的頻度均為1,該程序段的執行時間是一個與問題規模n無關的常數。算法的時間復雜度為常數階,記作T(n)=O(1)。如果算法的執行時 間不隨著問題規模n的增加而增長,即使算法中有上千條語句,其執行時間也不過是一個較大的常數。此類算法的時間復雜度是O(1)。
例2:
x=91;
y=100;
while(y>0)
if(x>100) {x=x-10;y--;}
else x++;
解答:
T(n)=O(1), 這個程序看起來有點嚇人,總共循環運行了1000次,但是我們看到n沒有? 沒。這段程序的運行是和n無關的,就算它再循環一萬年,我們也不管他,只是一個常數階的函數。
例3:
void test_(int n)
{
i = 1, k = 100;
while (i<n)
{
k = k + 1;
i += 2;
}
}
設for循環語句執行次數為T(n),則 i = 2T(n) + 1 <= n - 1,
即T(n) <= n/2 - 1 = O(n)
例4
int n = 8, count = 0;;
for(int i=1; i<=n; i = 2) {
count++;
}
好明顯,i的值是以i=i2的速度變化(1,2,4,8...),則循環體的執行次數
是以2為底數,以n為真數的對數的解,即O(
例5
int n = 8, count = 0;;
for(int i=1; i<=n; i *= 2) {
for(int j=1; j<=n; j++) {
count++;
}
}
時間復雜度為
例6
int n = 8, count = 0;;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
count++;
}
}
時間復雜度為
下面的文章,會講解常見算法的時間復雜度,記得關注。