理解大O符号 – 破解编码访谈

我需要帮助理解作者如何在Big O章节中得到问题11的答案。

问题是这样的:

以下代码打印长度为k的所有字符串,其中字符按排序顺序排列。 它通过生成长度为k的所有字符串然后检查每个字符串是否已排序来完成此操作。 它的运行时间是什么?

public static int numChars = 26; public static void printSortedStrings(int remaining) { printSortedStrings(remaining, ""); } public static void printSortedStrings(int remaining, String prefix) { if (remaining == 0) { if (isInOrder(prefix)) { System.out.println(prefix); // Printing the string } } else { for (int i = 0; i < numChars; i++) { char c = ithLetter(i); printSortedStrings(remaining - 1, prefix + c); } } } public static boolean isInOrder(String s) { for (int i = 1; i  curr) { return false; } } return true; } public static char ithLetter(int i) { return (char) (((int) 'a') + i); } public static void main(String[] args) { printSortedStrings(2); } 

书的答案:

O(kc k ),其中k是字符串的长度,c是字母表中的字符数。 生成每个字符串需要O(c k )时间。 然后,我们需要检查每个是否排序,这需要O(k)时间。

请注意,在上面的答案中没有考虑打印字符串,但我在其他问题中看到了相反的情况。

您何时考虑在运行时打印字符串?

这是正确答案O(k 2 c k吗?

此外,任何关于能够快速告知在此代码的运行时间中存在指数部分的建议将非常感激。 🙂

总之,没有。 正确答案是书中的O(kc k )。

在你查完字符串以检查其字符是否被排序后,这将需要O(k),打印它只会添加O(k) – 这不会改变你的复杂性。

假设测试字符串是否被排序需要a*k操作,打印它需要b*k 。 那么每个字符串的操作总数最多是(a+b)*k ,它仍然是O(k)。

编辑:关于问题的第二部分,遍历所有具有固定长度的单词将导致指数运行时复杂性,因为有c k这样的单词,其中c是字母表的大小, k是单词的长度。

一般来说,恒定长度字符串的打印也被认为是常量,但如果我们想要精确,让我们考虑将单个字符的打印作为基本操作:这意味着要打印ak长度字符串,我们有O(k)

由于我们有O(c k )个可能的字符串,并且对于每个字符串,我们必须检查它是否已经排序(使用O(k))并打印它们(另一个O(k)),总复杂度变为O(c k) (k + k))= O(2c k k)。

但是将函数乘以常数因子并不会改变它的复杂性,因此答案仍为O(c k k)。

打印字符串只是k时间的额外补充。

检查每个字符串是否被排序是O(k)并且说对于某个整数d (常数)打印它是O(dk) )。 加上两个得到O(k + dk) ,可以重写为O(k(1 + d)) 。 因为这只是一个标量我们知道O(k + dk) = O(k)所以答案不会改变。