![](/img/trans.png)
[英]Understanding Example 12 All Permutations of a string from Big O notation - Cracking the Coding Interview
[英]Counting all permutations of a string (Cracking the Coding Interview, Chapter VI - Example 12)
在 Gayle Laakman 的書“Cracking the Coding Interview”,第六章(Big O),示例 12 中,問題指出,給定以下用於計算字符串排列的 Java 代碼,需要計算代碼的復雜度
public static void permutation(String str) {
permutation(str, "");
}
public static void permutation(String str, String prefix) {
if (str.length() == 0) {
System.out.println(prefix);
} else {
for (int i = 0; i < str.length(); i++) {
String rem = str.substring(0, i) + str.substring(i + 1);
permutation(rem, prefix + str.charAt(i));
}
}
}
本書假設既然會有 n! 排列,如果我們將每個排列視為調用樹中的一個葉子,其中每個葉子都附加到長度為 n 的路徑上,那么將不再有 n*n! 樹中的節點(即:調用次數不超過 n*n!)。
但節點數不應該是:
因為調用的數量等於節點的數量(看看視頻Permutations Of String | Code Tutorial by Quinston Pimenta 中的圖)。
如果我們按照這個方法,節點的數量將是 1(對於樹的第一層/根)+ 3(對於第二層)+ 3*2(對於第三層)+ 3*2*1(對於第四層/底層)
即:節點數 = 3!/3! + 3!/2! + 3!/1! + 3!/0! = 16
但是,根據上述方法,節點數將是3*3! = 18
我們不應該把樹中的共享節點算作一個節點,因為它們表達了一個函數調用嗎?
你是對的節點數量。 該公式給出了確切的數字,但書中的方法計算了多次。
您的總和似乎也接近e * n!
對於大n
,因此可以簡化為O(n!)
。
說調用次數不超過n * n!
在技術上仍然是正確的n * n!
,因為這是一個有效的上限。 根據如何使用它,這可能沒問題,並且可能更容易證明。
對於時間復雜度,我們需要乘以每個節點完成的平均工作。
首先,檢查字符串連接。 每次迭代都會創建2
新字符串以傳遞給下一個節點。 一個 String 的長度增加1
,另一個的長度減少1
,但總長度始終為n
,每次迭代的時間復雜度為O(n)
。
每個級別的迭代次數都不同,因此我們不能只乘以n
。 而是查看整個樹的迭代總數,並獲得每個節點的平均值。 當n = 3
:
1
節點迭代3
次: 1 * 3 = 3
3
節點迭代2
次: 3 * 2 = 6
6
節點迭代1
次: 6 * 1 = 6
總迭代次數為: 3 + 6 + 6 = 15
。 這與樹中的節點數大致相同。 所以每個節點的平均迭代次數是恆定的。
總的來說,我們有O(n!)
次迭代,每次都做O(n)
工作,總時間復雜度為O(n * n!)
。
根據您的視頻,我們有 3 個字符( ABC
)的字符串,排列數為6 = 3!
,而6
恰好等於1 + 2 + 3
。 但是,如果我們有一個包含 4 個字符 ( ABCD
) 的字符串,則排列數應該是4 * 3!
因為D
可以在 1 到 4 之間的任何位置。對於D
每個位置,您可以生成3!
其余的排列。 如果您重新繪制樹並計算排列的數量,您將看到差異。
根據你的代碼,我們有n! = str.length()!
n! = str.length()!
排列,但在排列的每次調用中,您還運行從 0 到 n-1 的循環。 因此,您有O(n * n!)
。
更新以回應已編輯的問題
首先,在編程中,我們經常有0->n-1
或1->n
而不是0->n
。
其次,在這種情況下,我們不計算節點的數量,就像您再次查看剪輯中的遞歸樹一樣,您會看到節點重復。 這種情況下的排列應該是彼此唯一的葉子數。
例如,如果您有一個包含 4 個字符的字符串,那么葉子的數量應該是4 * 3! = 24
4 * 3! = 24
,這將是排列的數量。 但是,在您的代碼片段中,每個排列中還有一個0->n-1 = 0->3
循環,因此您需要計算循環數。因此,在這種情況下,您的代碼復雜度為O(n *n!) = O(4 * 4!)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.