我已经完成了这些问题,所以我不是在寻找一个直截了当的答案。我正在寻找关于我是否正确执行此操作的指导,如果没有,可能会解释为什么我不正确。 :)
所以我有这两个问题。我已经评论了我为什么得到答案的逻辑。如果有人可以请证实我这样做是正确的吗?
public static Integer findTripleB(int[] anArray) {
//Method Variable: n
if (anArray.length <= 2) {
return false;
} //Time Complexity: 1
// use insertion sort to sort anArray
for (int i = 1; i < anArray.length; i++) {//TC 1+(n+1)+n
// insert anArray[i]
int j = i-1; //TC 1
int element=anArray[i]; //TC 1
while (j >= 0 && anArray[j] > element) {//TC log(n)
anArray[j+1] = anArray[j]; //TC 1
j--; //TC 1
}
anArray[j+1] = element; //TC 1
} //Total TC: (2n+2)(1+1+log(n)(2)) = (2n+2)(2+2log(n)) = 4n+(2log(n))(2n)+4+4log(n)
// check whether anArray contains three consecutive
// elements of the same value
for (int i = 0; i < anArray.length-2; i++) {//TC 1+n-1+n
if (anArray[i] == anArray[i+2]) {//TC 1
return new Integer(anArray[i]);//TC 1
}
}//Total TC: (2n)(2) = 4n
return null;//TC 1
} //TOTAL TIME COMPLEXITY: 5+8n+4nlog(n)+4log(n)
为了获得最佳的时间复杂度,我得到了O(1),因为如果数组是&gt; =长度2,它将返回。在最坏的情况下,我想出了O(n * log(n))。
还有一个更简单的问题,
boolean findTripleA(int[] anArray) { //Method Variable: n
if (anArray.length <= 2) {
return false;//TC 1
}//TC 1
for (int i=0; i < anArray.length; i++) {//TC 1+n+1+n
// check if anArray[i] occurs at least three times
// by counting how often it occurs in anArray
int count = 0;//TC 1
for (int j = 0; j < anArray.length; j++) {//TC 1+n+1+n
if (anArray[i] == anArray[j]) {
count++;
}//TC 1
}//Total TC: 2n+2
if (count >= 3) {
return true;
}//TC 1
}//Total TC: (2n+2)(1+2n+2+1) = (2n+2)(2n+4) = 4n2+12n+8
return false;//TC 1
}//TOTAL TIME COMPLEXITY: 4n2+12n+9
最好的情况,与第一个问题相同,O(1)。对于最坏的情况,O(n ^ 2)。
这些是否正确,如果没有,为什么不呢?再一次,我不是在寻找答案。我正在寻找指导,因为我的教授似乎并不想提供帮助,而其他同学也同样困惑。
答案 0 :(得分:2)
第一个例子的几点:
算法的复杂性分析不是关于算法的单个案例(例如,数组大小为2),而是关于算法将在多长时间内采用的最佳/任意大小输入的最差/平均情况(所以任何给定大小的数组)。从技术上讲,您进行分析,查看行为,因为n(输入的大小)趋于无穷大。因此,循环之前的if语句不会影响算法的渐近最佳情况。
插入排序的最坏情况是O(n ^ 2 )。如果输入数组已经排序但顺序相反,则可以获得此类时间。所以你对第一种情况的结论是错误的。因此,我不必写出为什么会出现这种情况的冗长描述,这里解释为什么它来自here的O(n ^ 2):
然而,内部while循环多长时间并不完全清楚 如果我们有两倍的数组大小将采取。毕竟,它不会去 通过整个阵列。事实上,平均而言,它只能通过 大约一半的数组,如我们的图表所示,有时更少, 在排序的早期,有时更多,在后面的那种,但是一半 数组平均。即便如此,它通常不会一路走下去 它将平均再次扫描约一半 在找到正确的位置之前排序的集合。所以,这是合理的 估计内部循环必须遍历数组的1/4 每次通过外部for循环。必须排序的集合 搜索平均值是阵列大小的一半,平均而言必须是 在找到正确的位置之前,搜索已排序的一半。
但是,即使它只是阵列的1/4,如果它仍然会翻倍 数组大小加倍 - 1000的1/4是250,2000的1/4是500,两倍 许多。因此,当数组大小加倍时,内部while循环占用 平均两倍,并且必须执行两次 通过外部for循环。因此插入排序需要4倍的时间 当数组大小加倍时运行。它的运行时间与n ^ 2成正比, 我们说它是O(n ^ 2)。
对于最好的情况,你也错了。即使它“只是返回”,你仍然会经历与数组中元素数量成比例(实际上,相等)的多个比较(即使它只是2个元素)。所以最好的情况是O(n)比较,因为你必须检查每个元素是否在正确的位置,但O(1)交换(以防万一)它已经按正确的顺序排序,没有任何东西可以在任何地方交换。)
此外,在您的代码中,您将在一个位置返回一个布尔值,并在同一方法的另外两个位置返回Integers。这没有意义。
希望这一切都很清楚。
答案 1 :(得分:0)
一般来说,试图超出数量级是没有意义的。如果有一个N平方项,你可以称之为O(N ** 2)并保留它。如果你想要更准确,我建议在其上运行一个分析器......需要注意的是,热点优化和JIT不确定性以及GC时间都会合谋在Java中对性能进行精细测量。