整数数组上的Quicksort通过递归分区整个数组的一半来实现 - 并且在这样做时,对数组进行排序。我理解分区需要O(n),并且因为它在每一半(logN次)上递归完成,所以总成本为O(NlogN)。
在Cracking the Coding Interview第6版中,问题10.2要求编写一种方法来对字符串数组进行排序,以便所有字符串彼此相邻。作者提出了两种不同的解决方案 - 其中一种是快速分配整个阵列,因此字谜最终会彼此相邻。
但是 - 她说这是时间O(NlogN)。这就是我迷失的地方。对于整数数组,快速排序必须访问每个元素并交换整数,具体取决于一个是否大于另一个。这是每N个元素的O(1)成本,总计为O(N)。但是,作者建议的两个字符串的比较会将两个字符串分解为一个char数组,对它们进行排序,然后对它们进行比较。该过程将是每个字符串O(L logL)(其中L是字符串的长度)..所以它的每N个字符串的O(LlogL)成本 - 不是O(NlogN(L) LogL))?可能会迷失在数字中,但如果有人能够向我解释作者的进程如何具有O(NlogN)字符串比较的复杂性,那么它会非常有用。以下是她的代码:
class AnagramComparator implements Comparator <String> {
public String sortChars(String s) {
char[] content = s.toCharArray();
Arrays.sort(content)
return new String(content);
}
public int compare(String s1, String s2) {
return sortChars(s1).compareTo(sortChars(s2));
}
}
答案 0 :(得分:1)
作者可能假设字符串的最大长度是一些常量,因此字符串比较仍为O(1)。
答案 1 :(得分:0)
根据您编辑的问题,您是对的 - 每次比较都需要O(L log L)时间,其中L是最大字符串长度。根据最大字符串长度的大小,这可以将排序时间乘以一个非常重要的因素。由于对每个字符串中的字符进行排序将多次完成,因此这似乎是一种处理它的低效方法。
更好的方法可能是定义一个新对象:
public class AnagramSortElement implements Comparable<AnagramSortElement> {
private String sourceString;
private String sortedChars;
// getters, constructors as needed
// compareTo that compares sortedChars
}
这样您只需为每个输入字符串计算一次sortedChars
。您首先要从原始AnagramSortElement[]
创建一个新的String[]
数组,然后使用该数组进行排序。该过程将取O(N *(L log L))而不是O((N log N)*(L log L))。然后,当您执行排序时,由于您已经对字符进行了排序,因此比较会更快;排序平均需要O(N log N)。
这似乎应该更快,但您必须对其进行分析才能确定。对于非常大的N来说,创建N个新对象会对内存资源造成压力,而对于相当小的L,原始代码可能会更快。