時間複雜度:
首先要說的是,時間複雜度的計算並非計算程序具體運行的時間,而是算法執行語句的次數。
當咱們面前有多個算法時,咱們能夠經過計算時間複雜度,判斷出哪個算法在具體執行時花費時間最多和最少。算法
常見的時間複雜度有:
常數階O(1),
對數階O(log2 n),
線性階O(n),
線性對數階O(n log2 n),
平方階O(n^2),
立方階O(n^3)
k次方階O(n^K),
指數階O(2^n)。
隨着n的不斷增大,時間複雜度不斷增大,算法花費時間越多。函數
計算方法
①選取相對增加最高的項
②最高項係數是都化爲1
③如果常數的話用O(1)表示
如f(n)=2*n^3+2n+100則O(n)=n^3。post
一般咱們計算時間複雜度都是計算最壞狀況
時間複雜度的計算:
(1)若是算法的執行時間不隨着問題規模n的增長而增加,即便算法中有上千條語句,其執行時間也不過是一個較大的常數。此類算法的時間複雜度是O(1)。ui
int x=1; while (x <10) { x++; }
該算法執行次數是10,是一個常數,用時間複雜度表示是O(1)。spa
(2)當有若干個循環語句時,算法的時間複雜度是由嵌套層數最多的循環語句中最內層語句的頻度f(n)決定的。線程
for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { ; } }
該算法for循環,最外層循環每執行一次,內層循環都要執行n次,執行次數是根據n所決定的,時間複雜度是O(n^2)。code
(3)循環不只與n有關,還與執行循環所知足的判斷條件有關。regexp
int i=0; while (i < n && arr[i]!=1) { i++; }
在此循環,若是arr[i]不等於1的話,時間複雜度是O(n)。若是arr[i]等於1的話,則循環不能執行,時間複雜度是0。遞歸
空間複雜度
空間複雜度是對一個算法在運行過程當中臨時佔用存儲空間大小的量度。
計算方法:
①忽略常數,用O(1)表示
②遞歸算法的空間複雜度=遞歸深度N*每次遞歸所要的輔助空間
③對於單線程來講,遞歸有運行時堆棧,求的是遞歸最深的那一次壓棧所耗費的空間的個數,由於遞歸最深的那一次所耗費的空間足以容納它全部遞歸過程。ip
如:
int a; int b; int c; printf("%d %d %d \n",a,b,c);
它的空間複雜度O(n)=O(1);
int fun(int n,) { int k=10; if(n==k) return n; else return fun(++n); }
遞歸實現,調用fun函數,每次都建立1個變量k。調用n次,空間複雜度O(n*1)=O(n)。
1:實現二分查找算法的遞歸及非遞歸。(分析時間複雜度及空間複雜度)
迭代算法
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h> #include<assert.h> int BinarySearch(int arr[], int len, int num) { assert(arr); int left = 0; int right = len - 1; int mid; while (left <= right) { mid = left + (right - left) / 2; if (num > arr[mid]) { left = mid + 1; } else if (num < arr[mid]) { right = mid - 1; } else { return mid; } } return -1; } int main() { int arr[] = { 1,2,3,4,5,6,7,8,9 }; int length = sizeof(arr) / sizeof(arr[0]); int aim = 9; int result; result = BinarySearch(arr, length, aim); if (result == -1) { printf("Can't find %d\n", aim); } else { printf("%d at %d postion\n", aim,result + 1); } return 0; }
二分查找時,每次都在原有查找內容進行二分,因此時間複雜度爲O(log2 n)
由於變量值建立一次,因此空間複雜度爲O(1)
遞歸算法
int BinarySearchRecursion(int arr[5], int lef, int rig,int aim) { int mid = lef + (rig - lef) / 2; if (lef <= rig) { if (aim < arr[mid]) { rig = mid - 1; BinarySearchRecursion(arr, lef, rig, aim); } else if (arr[mid] < aim) { lef = mid + 1; BinarySearchRecursion(arr, lef, rig, aim); } else if (aim == arr[mid]) { return mid; } } else return -1; } int main() { int arr[] = { 1,2,3,5,6, }; int sz = sizeof(arr)/sizeof(arr[0]); int result; result = BinarySearchRecursion(arr, 0, sz - 1, 4); if (-1 == result) { printf("Can't find it.\n"); } else printf("Aim at %d location\n", result+1); }
時間複雜度爲O(log2 n)
每進行一次遞歸都會建立變量,因此空間複雜度爲O(log2 n)
2:實現斐波那契數列的遞歸及非遞歸。(分析時間複雜度及空間複雜度)
迭代算法
int FeiBoNaCciInteration(int a,int b,int num) { int c; if (num <= 0) return -1; else if (num == 1) return a; else if (num == 2) return b; else { while (num - 2) { c = a + b; a = b; b = c; num--; } return c; } } int main() { int n; int result; printf("Input n\n"); scanf("%d", &n); result = FeiBoNaCciInteration(2, 3, n);//可自定義輸入第一個數和第二個數 if (result == -1) { printf("Input Error!\n"); } else { printf("n is %d\n", result); } return 0; }
時間複雜度O(n)
空間複雜度爲O(1)
遞歸算法
int FeiBoNaCciRecursion(int num) { if (num < 0) return -1; if (num <= 2 && num > 0) return 1; else return FeiBoNaCciRecursion(num - 1) + FeiBoNaCciRecursion(num - 2); } int main() { int n; int result; printf("Input n\n"); scanf("%d", &n); result = FeiBoNaCciRecursion(n); if (result == -1) printf("Input Error!\n"); else printf("Result is %d\n", result); return 0; }
時間複雜度爲O(2^n) 空間複雜度爲O(n)