[英]How do I calculate the time complexity of the following function?
這是一個遞歸的 function。 它遍歷字符串的 map ( multimap<string, string> graph
)。 檢查itr -> second
( s_tmp
) 如果s_tmp
等於所需的字符串 ( Exp
),打印它 ( itr -> first
) 並為該itr -> first
再次執行 function 。
string findOriginalExp(string Exp){
cout<<"*****findOriginalExp Function*****"<<endl;
string str;
if(graph.empty()){
str ="map is empty";
}else{
for(auto itr=graph.begin();itr!=graph.end();itr++){
string s_tmp = itr->second;
string f_tmp = itr->first;
string nll = "null";
//s_tmp.compare(Exp) == 0
if(s_tmp == Exp){
if(f_tmp.compare(nll) == 0){
cout<< Exp <<" :is original experience.";
return Exp;
}else{
return findOriginalExp(itr->first);
}
}else{
str="No element is equal to Exp.";
}
}
}
return str;
}
沒有停止的規則,它似乎是完全隨機的。 這個function的時間復雜度是怎么計算的?
我不打算分析您的 function 而是嘗試以更一般的方式回答。 似乎您正在為 function 的復雜性尋找一個簡單的表達式,例如O(n)
或O(n^2)
。 然而,復雜性並不總是那么容易估計。
在您的情況下,它在很大程度上取決於graph
的內容以及用戶作為參數傳遞的內容。
作為一個類比,考慮這個 function:
int foo(int x){
if (x == 0) return x;
if (x == 42) return foo(42);
if (x > 0) return foo(x-1);
return foo(x/2);
}
在最壞的情況下,它永遠不會返回給調用者。 如果我們忽略x >= 42
,那么最壞情況的復雜度是O(n)
。 僅此一項作為對用戶的信息並沒有那么有用。 作為用戶,我真正需要知道的是:
x >= 42
來調用它。O(1)
如果x==0
O(x)
如果x>0
O(ln(x))
如果x < 0
現在嘗試對您的 function 進行類似的考慮。 簡單的情況是Exp
不在graph
中,在這種情況下沒有遞歸。 我幾乎可以肯定,對於“正確”輸入,您的 function 可以永遠不會返回。 找出這些案例並記錄下來。 在這兩者之間,您有一些案例在有限數量的步驟后返回。 如果您完全不知道如何通過分析來掌握它們,您可以隨時設置基准和衡量標准。 測量輸入大小10
、 50
、 100
、 1000
.. 的運行時間應該足以區分線性、二次和對數相關性。
PS:只是一個提示:不要忘記代碼實際上應該做什么以及解決該問題所需的時間復雜度(通常以抽象的方式討論這個問題比深入研究代碼更容易)。 在上面的愚蠢示例中,整個 function 可以替換為等效的int foo(int){ return 0; }
int foo(int){ return 0; }
這顯然具有恆定的復雜性,不需要比這更復雜。
這個 function 采用一個有向圖和該圖中的一個頂點,並向后追逐進入它的邊以找到一個沒有邊指向它的頂點。 查找任何給定頂點“后面”的頂點的操作需要O(n)
字符串比較, n
是圖中 k/v 對的數量(這是for
循環)。 它這樣做了m
次,其中m
是它必須遵循的路徑的長度(它通過遞歸完成)。 因此,它具有時間復雜度O(m * n)
的字符串比較, n
是 k/v 對的數量, m
是路徑的長度。
請注意,對於您看到的用代碼編寫的一些 function,通常沒有“時間復雜度”之類的東西。 您必須定義要用來描述時間的變量,以及要用來測量時間的操作。 例如,如果我們想純粹根據 k/ n
對的數量來寫這個,你會遇到問題,因為如果圖形包含一個適當放置的循環,function不會終止! 如果您進一步將圖約束為無環圖,則任何路徑的最大長度受m < n
約束,然后您還可以得到此 function 對具有n
條邊的無環圖進行O(n^2)
字符串比較。
您應該使用遞歸關系來近似遞歸調用的控制流。 自從我上離散數學的大學課程以來已經有 30 年了,但通常你確實喜歡偽代碼,足以看到有多少調用。 在某些情況下,僅計算右側最長條件下有多少是有用的,但您通常需要重新插入一個展開式,並從中推導出多項式或冪關系。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.