我需要帮助理解作者如何在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 < s.length(); i++) {
int prev = ithLetter(s.charAt(i - 1));
int curr = ithLetter(s.charAt(i));
if (prev > 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 )?
此外,任何关于能够快速告知在此代码的运行时间中指数部分的建议都将非常感激。 :)
答案 0 :(得分:8)
简而言之,没有。正确的答案是书中的O(kc k )。
在你查完字符串以检查它的字符是否被排序后,这将需要O(k),打印它只会添加O(k) - 这不会改变你的复杂性。
假设测试字符串是否按顺序进行a*k
操作,打印它需要b*k
。那么每个字符串的操作总数最多为(a+b)*k
,仍为O(k)。
编辑:关于问题的第二部分,遍历所有具有固定长度的单词将导致指数运行时复杂性,因为有c k 这样的单词其中c
是字母表的大小,k
是单词的长度。
答案 1 :(得分:3)
通常,恒定长度字符串的打印也被认为是常量,但如果我们想要精确,请考虑将单个字符的打印作为基本操作:这意味着打印ak长度字符串我们有templateUrl
。
因为我们有O(c k )可能的字符串,并且对于它们中的每一个,我们必须检查它是否被排序(使用O(k))并打印它们(另一个O(k) ),总复杂度变为O(c k (k + k))= O(2c k k)。
但是,将函数乘以常数因子并不会改变它的复杂性,因此答案仍为O(c k k)。
答案 2 :(得分:2)
打印字符串只是k
时间的额外补充。
检查每个字符串是否已排序为O(k)
,并且对于某个整数O(dk)
(常量)打印它是d
。添加两个O(k + dk)
,可以重写为O(k(1 + d))
。因为这只是一个标量我们知道O(k + dk) = O(k)
所以答案不会改变。