理解大O符号 - 破解编码面试

2022-09-02 22:08:02

我需要帮助理解作者如何在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(kck),其中 k 是字符串的长度,c 是字母表中的字符数。生成每个字符串需要 O(ck) 时间。然后,我们需要检查其中每个是否都已排序,这需要O(k)时间。

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

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

这是正确答案O(k2ck)吗

此外,任何关于能够快速判断此代码的运行时中存在指数部分的建议将不胜感激。:)


答案 1

简而言之,没有。正确的答案是O(kck),就像书中一样。

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

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

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


答案 2

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

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

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