時間複雜度和空間複雜度的簡單講解

一個算法的優劣主要從算法的執行時間和所須要佔用的存儲空間兩個方面衡量。算法

把今年很流行,淡淡的基佬紫送給各位看官,原諒綠就算了,怕被打死。
文章最後,舉例使用二分查找和斐波那契的遞歸和迭代方法,分別說明時間和空間複雜度。函數

時間複雜度:
首先要說的是,時間複雜度的計算並非計算程序具體運行的時間,而是算法執行語句的次數。
當咱們面前有多個算法時,咱們能夠經過計算時間複雜度,判斷出哪個算法在具體執行時花費時間最多和最少。post

常見的時間複雜度有:
常數階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*n3+2n+100則O(n)=n3。遞歸

一般咱們計算時間複雜度都是計算最壞狀況
時間複雜度的計算:
(1)若是算法的執行時間不隨着問題規模n的增長而增加,即便算法中有上千條語句,其執行時間也不過是一個較大的常數。此類算法的時間複雜度是O(1)。ci

        int x=1;
    while (x <10)
    {
        x++;
    }

該算法執行次數是10,是一個常數,用時間複雜度表示是O(1)。
(2)當有若干個循環語句時,算法的時間複雜度是由嵌套層數最多的循環語句中最內層語句的頻度f(n)決定的。string

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

該算法for循環,最外層循環每執行一次,內層循環都要執行n次,執行次數是根據n所決定的,時間複雜度是O(n^2)。
(3)循環不只與n有關,還與執行循環所知足的判斷條件有關。it

int i=0;
while (i < n && arr[i]!=1)
    {
        i++;
    }

在此循環,若是arr[i]不等於1的話,時間複雜度是O(n)。若是arr[i]等於1的話,則循環執行一次判斷跳出,時間複雜度是O(1)。
空間複雜度
空間複雜度是對一個算法在運行過程當中臨時佔用存儲空間大小的量度。
計算方法:
一、忽略常數,用O(1)表示
②遞歸算法的空間複雜度=遞歸深度N*每次遞歸所要的輔助空間
③對於單線程來講,遞歸有運行時堆棧,求的是遞歸最深的那一次壓棧所耗費的空間的個數,由於遞歸最深的那一次所耗費的空間足以容納它全部遞歸過程。io

如:for循環

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)  

相關文章
相關標籤/搜索