如何衡量此算法的时间复杂度(Big-O)?

时间:2016-07-06 19:58:19

标签: java algorithm time-complexity big-o asymptotic-complexity

我试图测量以下算法的大O复杂度:

int sumSome(int[] arr){
   int sum = 0;
   for (int i=0; i<arr.length;  i++) {
      for (int j=1; j<arr.length; j = j*2) {
         if (arr[i] > arr[j])
            sum += arr[i];
      }
   }
   return sum;
}

现在从我的理解,

if (arr[i] > arr[j])
                sum += arr[i];

具有O(1)的大O,因为它是常数并且没有发生任何事情,但是听起来它的for循环虽然我很难分辨它的Big-O表示法。我以为

for (int j=1; j<arr.length; j = j*2) {
         if (arr[i] > arr[j])
            sum += arr[i];
}

是线性函数O(n),因为j可能为1,但它在O(2n)处以线性方式上升,其仅为O(n)。所以整个算法不是O(n ^ 2)吗?显然我没有在MOOC考试中正确回答这个问题。谢谢!

2 个答案:

答案 0 :(得分:7)

  

是线性函数O(n),因为j可能为1,但它在O(2n)处以线性方式上升,其仅为O(n)。因此整个算法不会是O(n ^ 2)。显然我没有在MOOC考试中正确回答这个问题。谢谢!

它没有线性上升,而是呈指数上升,因为在每次迭代时,j乘以2

j = 1, 2, 4, 8, 16, 32, ..., 2^k < n
2^k < n | apply log base 2 => k < log_2 n => k = O(log n)

所以第二个循环只执行O(log n)次,产生整个代码序列O(n log n)

严格来说,O(n^2)也是正确的答案,因为如果O(n log n)是上限,那么O(n^2)也是如此。然而,n^2的大Theta不正确,人们通常也会使用Big-Oh来指代紧张的界限。

答案 1 :(得分:5)

Big-O的关键是寻找循环,所以关键部分在这里:

for (int i=0; i<arr.length;  i++) {
   for (int j=1; j<arr.length; j = j*2) {
      if (arr[i] > arr[j])
         sum += arr[i];
   }
}

外循环执行N次,因为它以0为增量从0到N.

内部循环每次外部迭代执行Log N次,因为它以指数方式从1到N执行。 (我怀疑,你错过的那个是循环中的迭代器:j = j*2。这使得J呈指数增长,而不是线性增长,因此它将在log-base-2时间内达到N.如果它是+2,而不是*2

if-inside对Big-O无关紧要,因为它只会增加一个系数。

所以,只需乘以循环的顺序:N * Log N = N Log N