1. 程式人生 > 其它 >資料結構 第6篇 演算法效率的度量

資料結構 第6篇 演算法效率的度量

技術標籤:資料結構(C++)資料結構c++

開心一刻:
      在網上碰上一群流氓並不可怕,可怕的是碰上了一堆流氓軟體。

演算法效率的度量

常見時間複雜度的比較:

O(1) < O(logn) < O(n) < O(n*logn) < O(n*n) < O(n*n*n) < O(2^n^) < O(n!) < O(n^n^)

當演算法的時間複雜度為 O(2^n^) , O(n!) 或 O(n^n^)時,即使n的值很小,實際執行時間也是不可接受的。

演算法分析示例:

int find(int a[], int n, int v)
{
	int ret = -1;
	for(int i=0; i<n; i++)
	{
		if( a[i] == v )
		{
			ret = i;
			break;
		}
	}
	return ret;
}

int arr[5] = {1,2,3,4,5};
int min = find(arr, 5, 1);  // 最好的情況,執行1次迴圈,O(1)
int max = find(arr, 5, 5);  // 最壞的情況,執行n次迴圈,O(n)

演算法最好與最壞情況的意義:

當演算法在最壞情況下仍然能滿足需求時,可以推斷,演算法的最好情況和平均情況都滿足需求。
若沒有特殊說明時,所分析演算法的時間複雜度都是指最壞時間複雜度。

演算法的空間複雜度( Space Complexity )

---定義:S(n) = S( f(n) )
n為演算法的問題規模
f(n)為空間使用函式,與n相關

推倒時間複雜度的方法同樣適用於空間複雜度
例:當演算法所需要的空間是常數時,空間複雜度為S(1)

空間複雜度的練習:

long suml(int n)               // 1 (變數所佔的記憶體單元)
{
	long ret = 0;              // 1
	int* array = new int[n];   // n
	
	for(int i=0; i<n; i++)     // 1
	{
		array[i]
= i + 1; } for(int i = 0; i < n; i++) // 1 { ret += array[i]; } delete[] array; return ret; } // ===> 所需單位記憶體: n + 4 // ===> 空間複雜度: S(n + 4) = S(n)

空間與時間的策略:

---大多數情況下,演算法的時間複雜度更令人關注
---如果有必要,==可以通過增加額外空間降低時間複雜度==
--- 同理,也可通過增加演算法的耗時降低空間複雜度

空間換時間 — 示例分析:

/*
   /*
    問題: (空間換時間)
    在一個由自然數1-1000中某些數字所組成的陣列中,每個數字可能出現零次或者多次。
    設計一個演算法,找出出現次數最多的數字。
*/ 

#include <iostream>

using namespace std;

void search(int a[], int len)     // O(n)
{
    int sp[1000] = {0};           // 這個初始化很重要,0-999個空盒子(輔助空間換時間)
    int max = 0;
    
    for(int i=0; i<len; i++)     // 遍歷a[]中元素,這是主要耗時,隨著陣列長度的增加而增加;後兩個迴圈耗時是一定的;
    {
        sp[a[i] - 1]++;          // 遍歷減一 作為陣列sp[]的下標使用,0-999個盒子中記錄了a[]陣列元素出現的次數
    } 
    
    for(int i=0; i<1000; i++)    // 出現的次數和最大值進行比較,最終確定出現次數最多的值
    {
        if( max < sp[i] )
        {
            max = sp[i];
        }
    }
    
    for(int i=0; i<1000; i++)
    {
        if( max == sp[i] )       // 當出現次數最多時,輸出最多值
        {
            cout << i + 1 << endl;
        }
    }
}

int main(int argc, char* argv[])
{
    int a[] = {1, 1, 3, 4, 5, 6, 6, 6, 3, 3};
    
    search(a, sizeof(a)/sizeof(*a));

    return 0;
}


面試題:

當兩個演算法的大O表示法相同時,是否意味著兩個演算法的效率完全相同?

答: 只能說明兩個演算法的效率事同一個級別的。
(考察了演算法時間複雜度的理解和演算法效率的理解)

總結:

--- 般而言,工程中使用的演算法,時間複雜度不超O(n*n*n)
--- 演算法分析設計時,重點考慮最壞情況下的時間複雜度
--- 資料結構中重點關注演算法的時間複雜度
--- 大O表示法同樣適用於演算法的空間複雜度
--- 時間換空間是工程開發中常用的策略

感謝關注,文章持續高速更新中······