- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
此问题来自 Cracking the Coding Interview 第 6 版,问题 V1.11。
The following code prints all strings of length k where the characters are in sorted order. It does this by generating all strings of length k and then checking if each is sorted. What is the runtime?
package QVI_11_Print_Sorted_Strings;
public class Question {
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);
}
} 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(5);
}
}
The answer is O(k c^k) where k is the length of the string and c is the number of characters in the alphabet. It takes O(c^k) time to generate each string. Then, we need to check that each of these is sorted, which takes O(k) time.
现在,我了解 O(k) 的来源,但我不明白 O(c^k) 是如何产生的。
最佳答案
上述算法的工作原理是使用一组 c 个字符选择递归地生成所有可能的长度为 k 的字符串。从 c 个字母中可以组成的长度为 k 的可能字符串的数量等于 ck。例如,如果我有两个字母可供选择(a 和 b)并且我有长度为 3 的字符串,那么我可以制作 23 = 8 个可能的字符串:
为了更好地了解这是从哪里来的,请注意每次在字符串末尾添加一个新字母时,您都有 c 个选项可以选择该字母,因此可能的字符串数是
c · c · ... · c (k times) =
ck
这意味着上面的代码通过生成这些字符串中的每一个来工作,必须至少 Ω(ck) 工作,因为这是最小数量要检查的字符串。
那么它对每个字符串做了多少工作呢?这就是事情变得棘手的地方。这些字符串是通过不断地从可能字符列表中附加一个新字符而一次构建一个字符的。在 Java 中,附加到字符串会生成字符串的完整副本,因此附加第一个字符的成本(大约)为 1,第二个字符(大约)为 2,然后是 3,然后是 4,等等。这意味着成本构建一个长度为 k 的完整字符串将是
1 + 2 + 3 + ... + k
= Θ(k2)
所以这里的运行时间实际上看起来是 O(ck k2) 而不是 O(k ck),因为构建所有这些字符串的成本加起来相当快。
然而,这并不是一个严格的界限。例如,为形成字符串 aaa
所做的一些工作也用于形成字符串 aab
, 因为两个字符串都是从 aa
开始形成的并连接另一个字符。
为了获得更好的分析,我们可以总结在树的每个级别上执行串联所完成的总工作量。树的第 0 层有一个大小为 0 的字符串,因此没有进行任何连接。树的第一层有 c 个大小为 1 的字符串,需要进行 c 次连接操作。树的第二层有 c2 个大小为 2 的字符串,需要 2c2 的工作才能形成。三层中的第三层有 c3 个大小为 3 的字符串,需要 3c3 才能形成。更一般地说,级别 i 需要 ici 工作才能形成。这意味着我们要确定
0c0 + 1c1 + 2c2 + ... + kck.
此求和结果为 Θ(kck),其中 k 项的指数较低。
总结:
关于java - 为什么这个例子的时间复杂度是从 "Cracking the Coding Interview"O(k c^k)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44145982/
给定一个匹配词“bad”和单词列表“bird”、“cat”、“mug”、“thug”、“irk”、“kin”、“in”、“mad”、“md”从单词列表中尝试形成匹配词。每次您在给定列表中使用单词时,您
我在面试中被问到一个面试问题,但我没有得到解决方案。 以下是示例段落,我们的程序应该给出数学单词的超链接 “网络协议(protocol)驱动程序 - 完全支持 Java 技术的网络协议(protoco
我是一名 CS 学生,大约一周前我买了破解编码面试。我只是在 Big O 章节,我发现了一种算法,据说可以对数字中的数字求和;乍一看,它看起来很困惑,所以我用 Python 运行了它,但它没有按预期运
这是一个我觉得很有趣的面试问题。 编写一个方法,将指向 Node 结构的指针作为参数,并返回传入数据结构的完整拷贝。 Node 结构包含两个指向其他 Node 结构的指针。例如,方法签名可能如下所示:
这是书中的代码 - “Programming Interviews Exposed”第 2 版 - 第 78 和 79 页- 删除指定字符练习(下续) void Main() { string
来自 Cracking the Coding Interview。问题 2.1:编写代码从未排序的链表中删除重复项。这是他们提供的解决方案: public static void removeDupl
我找到了这个问题的解决方案,但它需要 O(n^2)。有没有可能做得更好? 问题:假设我们想找 D 美元。我们有一个包含 N 个元素的数组 A。面额作为美元值存在于数组中,但我们事先不知道确切的面额。然
我正在尝试解决这个问题:https://www.interviewstreet.com/challenges/dashboard/#problem/4f9a33ec1b8ea 假设 A 是 n 个数字
我尝试使用 Cracking the coding interview 中的代码来运行反向字符串函数。我不知道代码是否错误或者我应该使用另一个 IDE(我为此使用了 Xcode 5.2)。我是 C 编
在 Cracking the coding interview 一书的第 259 页,给出了 C++ 中的模板化单例(我不想发布所有代码以防其版权)。 问题是将单例实现为模板,并假设有一个名为 Loc
书上二分查找的递归版本: int binarySearch(int[] array, int target) throws BSException { return int binarySearch(
我正在阅读“Cracking the Coding Interview”一书,在这里我遇到了一些寻求答案的问题,但我需要帮助来比较我的答案与解决方案。我的算法有效,但我很难理解书中的解决方案。主要是我
我正在尝试解决一个面试问题,这样给定的链表需要围绕一个值“x”进行分区。我尝试了一下,但没有得到想要的结果。 class Node(object): def __init__(self, va
You have a stack of n boxes, with widths wi, heights hi, and depths di. The boxes cannot be rotated
You have two very large trees: T1, with millions of nodes, and T2, with hundreds of nodes. Create an
此问题来自 Cracking the Coding Interview 第 6 版,问题 V1.11。 The following code prints all strings of length
页。 Programming interviews exposed book的29有如下示例代码,用于从链表中删除一个元素: bool deleteElement(IntElement **head,
上页。 Cracking the Coding Interview 的 44,有如下算法: int f(int n) { if (n <= 1) { return 1;
假设有一个整数 vector 。现在我们想要合并,我们选择 2 个相邻元素 v[I] 和 v[I+1](对于每个有效的 I)并执行 v[I] = v[I+1] + v[I]。并删除 v[I+1]。继续
我在求职面试中被问到以下问题。 给定一个大小未知的输入数组,开头全为 1,结尾全为 0。从 0 开始查找数组中的索引。考虑数组中有数百万个 1 和 0。即数组非常大......例如数组内容 11111
我是一名优秀的程序员,十分优秀!