1. 程式人生 > >時間複雜度和空房間複雜度

時間複雜度和空房間複雜度

一、時間複雜度:(注意:不是指程式執行時間)

1定義:一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式,用T(n)表示,若有某個輔助函式f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函式。記作T(n)=O(f(n)),稱O(f(n)) 為演算法的漸進時間複雜度,簡稱時間複雜度。
2、 計算方法:在計算時間複雜度的時候,先找出演算法的基本操作,然後根據相應的各語句確定它的執行次數,再找出 T(n) 的同數量級(它的同數量級有以下:1,log2n,n,n log2n ,n的平方,n的三次方,2的n次方,n!),找出後,f(n) = 該數量級,若 T(n)/f(n) 求極限可得到一常數c,則時間複雜度T(n) = O(f(n))
二、空間複雜度(注意:不是計算空間,而是指物件的個數)

1、空間複雜度是對一個演算法在執行過程中臨時佔用儲存空間大小的量度,記做S(n)=O(f(n))。比如直接插入排序的時間複雜度是O(n^2),空間複雜度是O(1) 。而一般的遞迴演算法就要有O(n)的空間複雜度了,因為每次遞迴都要儲存返回資訊。一個演算法的優劣主要從演算法的執行時間和所需要佔用的儲存空間兩個方面衡量。

三、來幾段程式碼大概解釋以上兩個問題
折半查詢法–非遞迴法

 int BiSearch(int *arr,int len,int k)

 {
     int left = 0;
     int right = len;
     int mid = 0;
     while
(right>=left) { mid=left+((right-left)>>1); if (k>arr[mid]) { left=mid+1; } else if (k<arr[mid]) { right=mid-1; } else return mid; } return -1; } int main () { int
arr[]={1,2,3,4,5,6,7,8,9}; int k = 0; int len = sizeof(arr)/sizeof(arr[0])-1; printf("arr[%d]\n", BiSearch(arr,len,1)) ; printf("arr[%d]\n", BiSearch(arr,len,2)) ; printf("arr[%d]\n", BiSearch(arr,len,3)) ; printf("arr[%d]\n", BiSearch(arr,len,4)) ; printf("arr[%d]\n", BiSearch(arr,len,5)) ; printf("arr[%d]\n", BiSearch(arr,len,6)) ; printf("arr[%d]\n", BiSearch(arr,len,7)) ; printf("arr[%d]\n", BiSearch(arr,len,8)) ; printf("arr[%d]\n", BiSearch(arr,len,9)) ; printf("arr[%d]\n", BiSearch(arr,len,10)) ; printf("arr[%d]\n", BiSearch(arr,len,0)) ; return 0; }

折半查詢–遞迴法

 int BiSearch(int *arr,int left,int right,int k)
 {
     int mid = left + ((right-left)>>1);
     while (left<=right)
     {
         if (arr[mid]==k)
         {
             return mid;
         }
         else if (arr[mid]>k)
         {
             return BiSearch(arr,left,mid-1,k);
         }
         else if (arr[mid]<k)
         {
             return BiSearch(arr,mid+1,right,k);
         }
     }
     return -1;
 }


 int main ()
 {
     int arr[]={1,2,3,4,5,6,7,8,9,10};
     int left = 0;
     int len = sizeof(arr)/sizeof(arr[0]);
     int right = len -1;
     printf("%d\n",BiSearch(arr,left,right,1));
     printf("%d\n",BiSearch(arr,left,right,2));
     printf("%d\n",BiSearch(arr,left,right,3));
     printf("%d\n",BiSearch(arr,left,right,4));
     printf("%d\n",BiSearch(arr,left,right,5));
     printf("%d\n",BiSearch(arr,left,right,6));
     printf("%d\n",BiSearch(arr,left,right,7));
     printf("%d\n",BiSearch(arr,left,right,8));
     printf("%d\n",BiSearch(arr,left,right,9));
     printf("%d\n",BiSearch(arr,left,right,10));
     printf("%d\n",BiSearch(arr,left,right,0));
     return 0;
 }

 以上分別用遞迴和非遞迴進行了二分查詢,當陣列長度為N時 非遞迴的時間複雜度為O(log N),空間複雜度為O(1);遞迴的時間複雜度和空間複雜度均為O(log N)

再來幾個程式碼:
斐波拉契數——遞迴法

  long long fib(int n)
  {
      if (n<3)
          return 1;
      else
          return ((fib(n-1)+fib(n-2)));
  }

斐波拉契數——迭代法

int main ()
{
    int n = 0;
    long long a = 1;
    long long b = 1;
    scanf("%d",&n);
    if (n<3)
    {
       b=1;
    }
    else
    while (n>2)
    {
        b=a+b;
        a=b-a;
        n--;
    }
    printf("%lld\n",b);
    return 0;

四、簡單總結一下:當我們在看到某個程式時有時候我們無法進行實際測試,我們需要用時間複雜度和空間複雜度來衡量演算法的優劣性。