![](/img/trans.png)
[英]What should be the time complexity of the given function in terms of Big O?
[英]What is the time complexity \big(O) of this specific function?
該函數(f1)的時間復雜度是多少?
如我所見,第一個循環(i = 0)->(n / 4次)第二個循環(i = 3)->(n / 4-3次)....等等,結果是:( n / 3)*(n / 4 +(n-3)/ 4 +(n-6)/ 4 +(n-9)/ 4 ....
我在這里停止,如何繼續?
int f1(int n){
int s=0;
for(int i=0; i<n; i+=3)
for (int j=n; j>i; j-=4)
s+=j+i;
return s;
}
Big(O)表示法的重要之處在於它消除了“常量”。 目的是確定輸入量增長時的趨勢 ,而不必擔心特定數字。
可以將其視為在不知道x和y軸的數字范圍的圖形上確定曲線。
因此,在您的代碼中,即使您為每個循環的每次迭代都跳過了n
范圍內的大多數值,這也是以恆定速率完成的。 因此,無論您實際上跳過了多少,這仍然相對於n^2
縮放。
計算以下任何內容都沒有關系:
1/4 * n^2
0.0000001 * n^2
(1/4 * n)^2
(0.0000001 * n)^2
1000000 + n^2
n^2 + 10000000 * n
在Big O中,這些都等效於O(n^2)
。 關鍵是,一旦n
足夠大(無論大小如何),所有的低階項和常數因子在“全局”中都將變得無關緊要。
( 值得強調的是,這就是為什么在小投入時,您應該警惕過分依賴Big O的原因。那時候,恆定的間接費用仍然會產生很大的影響。 )
關鍵觀察:內部循環在步驟i
執行(ni)/4
次,因此在步驟ni
i/4
。
現在將i = 3k, 3(k-1), 3(k-2), ..., 9, 6, 3, 0
所有這些量求和,其中3k
是n
之前3
的最大倍數(即3k <= n < 3(k+1)
):
3k/4 + 3(k-1)/4 + ... + 6/4 + 3/4 + 0/4 = 3/4(k + (k-1) + ... + 2 + 1)
= 3/4(k(k+1))/2
= O(k^2)
= O(n^2)
因為k <= n/3 <= k+1
,因此k^2 <= n^2/9 <= (k+1)^2 <= 4k^2
理論上是“ O(n * n)”,但是...
如果編譯器想要對其進行優化,該怎么辦:
int f1(int n){
int s=0;
for(int i=0; i<n; i+=3)
s += table[i];
return s;
}
甚至這個:
int f1(int n){
if(n <= 0) return 0;
return table[n];
}
那么它也可以是“ O(n)”或“ O(1)”。
請注意,從表面上看,這種優化似乎是不切實際的(由於最壞情況下的內存成本); 但是使用足夠先進的編譯器(例如,使用“整個程序優化”來檢查所有調用者並確定n
始終在某個范圍內),這是不可想象的。 以類似的方式,並非所有調用方都使用常量(例如,在功能足夠先進的編譯器可以將x = f1(123);
替換為x = constant_calculated_at_compile_time
)。
換一種說法; 實際上,原始函數的時間復雜度取決於該函數的使用方式以及編譯器的優劣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.