[英]Time complexity analysis of function with recursion inside loop
我正在嘗試分析以下功能的時間復雜度。 此函數用於檢查一個字符串是否由其他字符串組成。
set<string> s; // s has been initialized and stores all the strings
bool fun(string word) {
int len = word.size();
// something else that can also return true or false with O(1) complexity
for (int i=1; i<=len; ++i) {
string prefix = word.substr(0,i);
string suffix = word.substr(i);
if (prefix in s && fun(suffix))
return true;
else
return false;
}
}
我認為時間復雜度為O(n)
,其中n是單詞的長度(我對嗎?)。 但是由於遞歸位於循環內部,所以我不知道如何證明這一點。
編輯:
此代碼不是正確的C++
代碼(例如prefix in s
)。 我只是展示了此函數的概念,並想知道如何分析其時間復雜度
分析此問題的方法是通過根據輸入的長度和前綴在s
的(未知)概率建立遞歸關系。 我們假設前綴在s
中的概率由前綴長度L的某個函數pr(L)給出。 令復雜度(操作數)由T(len)給出。
如果len == 0( word
是空字符串),則T =1。(該函數在循環后缺少最后一個return
語句,但是我們假設實際代碼只是該構思的草圖,而不是內容的縮寫)實際執行)。
對於每次循環迭代,用T(len; i)表示循環體的復雜度。 如果前綴不在s
,則主體具有恆定的復雜度(T(len; i)= 1)。 該事件的概率為1-pr(i)。
如果前綴在s
,則該函數根據對fun(suffix)
的遞歸調用返回true
或false
,其復雜度為T(len-i)。 此事件的概率為pr(i)。
因此,對於i
每個值,循環體的復雜度為:
T(len; i)= 1 *(1- pr(i))+ T(len-i)* pr(i)
最后(這取決於預期的邏輯,而不是發布的代碼),我們有
T(len)=總和i = 1 ... len (T(len; i))
為簡單起見,讓我們將pr(i)視為值為0.5的常數函數。 然后,T(len)的遞歸關系為(直到一個常數因子,這對於O()計算而言並不重要):
T(len)=總和i = 1 ... len (1 + T(len-i))= len +總和i = 0 ... len-1 (T(i))
如上所述,邊界條件為T(0)=1。這可以通過標准遞歸函數方法解決。 讓我們看一下前幾個術語:
len T(len)
0 1
1 1 + 1 = 2
2 2 + 2 + 1 = 5
3 3 + (4 + 2 + 1) = 11
4 4 + (11 + 5 + 2 + 1) = 23
5 5 + (23 + 11 + 5 + 2 + 1) = 47
模式顯然是T(len)= 2 * T(len-1)+1。這對應於指數復雜度:
T(n)= O(2 n )
當然,此結果取決於我們對pr(i)所做的假設。 (例如,如果所有i的pr(i)= 0,則T(n)= O(1)。如果pr(i)具有最大前綴長度-pr(i)=對於所有i> 0>對於某些M,M。)pr(i)獨立於i的假設可能是不現實的,但這實際上取決於s
的填充方式。
假設您已解決其他人指出的錯誤,則i
值是要分割字符串的位置(每個i
是最左側的分割點,然后遞歸i
右側的所有內容)。 這意味着,如果要平移遞歸,則要查看多達n-1
不同的拆分點,並詢問每個子字符串是否為有效單詞。 如果word
的開頭沒有您集合中的很多元素,那么事情就可以了,從那時起您可以跳過遞歸。 但是在最壞的情況下, prefix in s
始終為true,並且您嘗試n-1
分割點的所有可能子集。 這給出了2^{n-1}
不同的拆分集,乘以每個此類拆分集的長度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.