本文是博主參考許多文章寫出來的,不能算是原創,但是轉載也不能算吧。
當我們評價某個算法的時間性能時,主要標准就是算法的漸進時間復雜度,因此,在算法分析時,往往對兩者不予區分 ,將其簡稱為時間復雜度。即T(n)= 0(f(n))
常見的算法時間復雜度由小到大依次為:
Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
這里解釋一下O(n),這里的“0”是數學符號,其定義為“若T(n)和f(n) 是定義在正整數集合上的兩個函數,則T(n)是O(f(n))表示存在正的常數 C 和 n0, 使得當n ≥ n0 s時都滿足 0 ≤ T(n) ≤ c*f(n) 。” 簡單來說,當 n→ ∞ 時,兩個函數的比值不為0。
“大O記法”:在這種描述中使用的基本參數是 n,即問題實例的規模,把復雜性或運行時間表達為n的函數。這里的“O”表示量級 (order),比如說“二分檢索是 O(logn)的”,也就是說它需要“通過logn量級的步驟去檢索一個規模為n的數組”記法 O ( f(n) )表示當 n增大時,運行時間至多將以正比於 f(n)的速度增長。
接下來我們來具體了解一下時間復雜度。
1.時間頻度
一個算法執行所耗費的時間,從理論上是不能算出來的,必須上機測試。
一個算法中的語句執行次數稱為語句頻度或時間頻度,記做T(n);
2.時間復雜度
一般情況下,算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數 f(n), 當 n→ ∞ 時,兩個函數的比值不為0,則T(n) = O(f(n)),稱O(f(n)) 為算法的漸進時間復雜度,簡稱時間復雜度。
這里我們提一下 平均時間復雜度 , 指的所有可能的輸入實例均以等概率出現的情況下,算法的期望運行時間。
基本概念到此結束,下面我們來看看時間復雜度的解法和其注意點。
求解步驟
1. 找出算法中的基本語句。
基本語句就是最內層的循環體,通俗一點就是與n 有關的執行次數最多的那條語句。
2. 計算基本語句的執行次數的數量級
只需要求出最高次冪的執行次次數, 以此來簡化算法分析,使注意率集中在最重要的地方: 增長率。
3. 用O表示算法的時間復雜度
在計算算法時間復雜度時有以下幾個簡單的程序分析法則:
1.對於一些簡單的輸入輸出語句或賦值語句,近似認為需要O(1)時間
2.對於順序結構,需要依次執行一系列語句所用的時間可采用大O下"求和法則"
求和法則:是指若算法的2個部分時間復雜度分別為 T1(n)=O(f(n))和 T2(n)=O(g(n)),則 T1(n)+T2(n)=O(max(f(n), g(n)))
特別地,若T1(m)=O(f(m)), T2(n)=O(g(n)),則 T1(m)+T2(n)=O(f(m) + g(n))
3.對於選擇結構,如if語句,它的主要時間耗費是在執行then字句或else字句所用的時間,需注意的是檢驗條件也需要O(1)時間
4.對於循環結構,循環語句的運行時間主要體現在多次迭代中執行循環體以及檢驗循環條件的時間耗費,一般可用大O下"乘法法則"
乘法法則: 是指若算法的2個部分時間復雜度分別為 T1(n)=O(f(n))和 T2(n)=O(g(n)),則 T1*T2=O(f(n)*g(n))
5.對於復雜的算法,可以將它分成幾個容易估算的部分,然后利用求和法則和乘法法則技術整個算法的時間復雜度
另外還有以下2個運算法則:
(1) 若g(n)=O(f(n)),則O(f(n))+ O(g(n))= O(f(n))
(2) O(Cf(n)) = O(f(n)),其中C是一個正常數
以下有幾種實例,方便加深理解
O(1)
Temp=i;i=j;j=temp;
以上三條單個語句的頻度均為1,該程序段的執行時間是一個與問題規模n無關的常數。算法的時間復雜度為常數階,記作T(n)=O(1)。如果算法的執行時間不隨着問題規模n的增加而增長,即使算法中有上千條語句,其執行時間也不過是一個較大的常數。此類算法的時間復雜度是O(1)。
O(n^2)
2.1. 交換i和j的內容
sum=0; (一次)
for(i=1;i<=n;i++) (n次 )
for(j=1;j<=n;j++) (n^2次 )
sum++; (n^2次 )
解:T(n)=2n^2+n+1 =O(n^2)
2.2.
for (i=1;i<n;i++)
{
y=y+1; ①
for (j=0;j<=(2*n);j++)
x++; ②
}
解: 語句1的頻度是n-1
語句2的頻度是(n-1)*(2n+1)=2n^2-n-1
f(n)=2n^2-n-1+(n-1)=2n^2-2
該程序的時間復雜度T(n)=O(n^2).
O(n)
2.3.
a=0;
b=1; ①
for (i=1;i<=n;i++) ②
{
s=a+b; ③
b=a; ④
a=s; ⑤
}
解:語句1的頻度:2,
語句2的頻度: n,
語句3的頻度: n-1,
語句4的頻度:n-1,
語句5的頻度:n-1,
T(n)=2+n+3(n-1)=4n-1=O(n).
O(log2n )
2.4.
i=1; ①
while (i<=n)
i=i*2; ②
解: 語句1的頻度是1,
設語句2的頻度是f(n), 則:2^f(n)<=n;f(n)<=log2n
取最大值f(n)= log2n,
T(n)=O(log2n )
O(n^3)
2.5.
for(i=0;i<n;i++)
{
for(j=0;j<i;j++)
{
for(k=0;k<j;k++)
x=x+2;
}
}
解:當i=m, j=k的時候,內層循環的次數為k當i=m時, j 可以取 0,1,...,m-1 , 所以這里最內循環共進行了0+1+...+m-1=(m-1)m/2次所以,i從0取到n, 則循環共進行了: 0+(1-1)*1/2+...+(n-1)n/2=n(n+1)(n-1)/6所以時間復雜度為O(n^3).
我們還應該區分算法的最壞情況的行為和期望行為。如快速排序的最 壞情況運行時間是 O(n^2),但期望時間是 O(nlogn)。通過每次都仔細 地選擇基准值,我們有可能把平方情況 (即O(n^2)情況)的概率減小到幾乎等於 0。在實際中,精心實現的快速排序一般都能以 (O(nlogn)時間運行。
訪問數組中的元素是常數時間操作,或說O(1)操作。一個算法如 果能在每個步驟去掉一半數據元素,如二分檢索,通常它就取 O(logn)時間。用strcmp比較兩個具有n個字符的串需要O(n)時間。常規的矩陣乘算法是O(n^3),因為算出每個元素都需要將n對 元素相乘並加到一起,所有元素的個數是n^2。
指數時間算法通常來源於需要求出所有可能結果。例如,n個元 素的集合共有2n個子集,所以要求出所有子集的算法將是O(2n)的。指數算法一般說來是太復雜了,除非n的值非常小,因為,在 這個問題中增加一個元素就導致運行時間加倍。不幸的是,確實有許多問題 (如著名的“巡回售貨員問題” ),到目前為止找到的算法都是指數的。如果我們真的遇到這種情況,通常應該用尋找近似最佳結果的算法替代之。
參考鏈接:http://blog.csdn.net/firefly_2002/article/details/8008987
http://blog.csdn.net/missshirly/article/details/7255889
http://wenku.baidu.com/view/dd4d6817866fb84ae45c8d3c.html