簡體   English   中英

計算字符串的所有排列(破解編碼訪談,第六章 - 示例 12)

[英]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!)。

但節點數不應該是:

foo+bar

因為調用的數量等於節點的數量(看看視頻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-11->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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM