【问题标题】:Another time complexity issue [closed]另一个时间复杂度问题[关闭]
【发布时间】:2014-01-31 20:13:06
【问题描述】:

我已经解决了这些问题,所以我不是在寻找直接的答案。我正在寻找有关我是否正确执行此操作的指导,如果没有,可能会解释我为什么不正确。 :)

所以我有这两个问题。我已经评论了我为什么得到我的答案的逻辑。如果有人可以请验证我这样做是否正确?

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),因为如果数组 >= 长度 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)。

这些是否正确,如果不正确,为什么不呢?同样,我不是在寻找答案。我正在寻求指导,因为我的教授似乎不想提供帮助,而班上的其他人也很困惑。

【问题讨论】:

    标签: java math time complexity-theory


    【解决方案1】:

    第一个例子的几点说明:

    算法的复杂性分析不是关于算法的单一情况(例如数组大小为 2),而是关于算法将在多长时间内获得最佳/任意大小输入的最坏/平均情况(因此是任何给定大小的数组)。从技术上讲,您进行分析时会查看行为,因为 n(输入的大小)趋于无穷大。因此,循环之前的 if 语句不会影响算法的渐近最佳情况性能

    插入排序的最坏情况是 O(n^2)。如果输入数组已经排序但顺序相反,您可以获得这种时间。所以你对第一种情况的结论是错误的。这样我就不必写一个冗长的描述为什么会这样了,这里解释一下为什么它是来自here的O(n^2):

    不过,内部 while 循环要多长时间尚不完全清楚 如果我们有两倍的数组大小,将需要。毕竟不走 通过整个阵列。事实上,平均而言,它只会通过 大约一半的数组,正如我们的图表所示,有时更少, 在排序的早期,有时更多,在排序的后期,但一半 平均阵列。即使那样,它通常也不会一路走好 下降到索引 0。它会再次平均扫描大约一半 找到正确位置之前的排序集。所以,合情合理 估计内部while循环必须遍历数组的1/4 每次通过外部for循环。它必须的排序集 search 平均是数组大小的一半,平均而言它必须 在找到正确的位置之前搜索一半的排序集。

    但是,即使它只是数组的 ¼,如果 数组大小翻倍——1000 的 ¼ 是 250,2000 的 ¼ 是 500,两倍 很多。因此,当数组大小翻倍时,内部 while 循环会占用 平均两倍的时间,并且必须执行两倍的次数 通过外部 for 循环。因此插入排序需要 4 倍的时间 当数组大小加倍时运行。它的运行时间与 n^2 成正比, 我们说它是 O(n^2)。

    在最好的情况下,你也错了。即使它“只是返回”,您仍将经历与数组中元素数量成比例(实际上相等)的一些比较(即使它只是 2 个元素)。所以最好的情况是 O(n) 比较,因为您必须检查每个元素是否在正确的位置,但是 O(1) 交换(以防万一它已经按正确的顺序排序了,没有什么可以交换的)。

    此外,在您的代码中,您在同一方法的一个位置返回布尔值,在另外两个位置返回整数。这没有意义。

    希望一切都清楚。

    【讨论】:

    • 为什么return下面的代码如果返回了会执行?我记得,如果一个方法返回一些东西,它下面的代码就不会执行。你只会运行第一个 if()。
    • 因为算法的复杂性分析不是关于问题的单个实例,而是算法需要多长时间渐近作为n->无穷大。也就是说,对于一般的一类问题,或者在这种情况下,是一个任意大小的数组。
    • 这是有道理的。我只是不习惯看过去的回报,我想。所以对于第一个,最好的情况是 O(n),最坏的情况是 O(n^2)...对于第二个,最好的情况是 O(n),最坏的情况是 O(n^2)同样,因为我有一个嵌套的 for 循环而不是插入排序?
    • 不。当您在外部循环和完全内部循环中遍历数组时,第二个的最佳情况是 O(n^2)。这种嵌套循环往往会导致 O(n^2) 时间,除非您以某种特殊方式修改内部或外部循环索引。实际上,如果你在内循环中有 if(count >= 3),那么最好的情况会下降到 O(1),因为对于 任何数组大小,如果你的计数器达到 3,你会回来的。
    • 希望很清楚为什么最好的情况会下降到 O(1) 因为 if(counter>=3) 如果它在内部循环内,而不是在你的第一个循环之前的 ifs每个案例。
    【解决方案2】:

    一般来说,试图超越数量级是没有意义的。如果有一个 N 平方项,你可以称它为 O(N**2) 并保留它。如果您想要更高的准确度,我建议您在其上运行分析器……但需要注意的是,热点优化、JIT 不确定性和 GC 时间都会共同导致在 Java 中难以精确测量性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      • 2023-01-12
      相关资源
      最近更新 更多