如何在以下代码上计算Big-O表示法

时间:2010-11-10 22:03:07

标签: algorithm optimization complexity-theory big-o performance

我读过这个主题:

Big O, how do you calculate/approximate it?

我不确定以下函数的Big-O表示法是什么:

static int build_nspaces_pattern(const char * const value, char *pattern,
        size_t sz_pattern) {
   static char    val_buffer[1025];
   char           *ptr, *saveptr;
   size_t         szptrn;
   ptrdiff_t      offset;

   val_buffer[0] = '\0';
   strncat(val_buffer, value, sizeof(val_buffer) - 1);
   val_buffer[sizeof(val_buffer) - 1] = '\0';

   pattern[0] = '^'; pattern[1] = '('; pattern[2] = '\0';

   for ( ptr=strtok_r(val_buffer, ",", &saveptr);
         ptr!=NULL;
         ptr=strtok_r(NULL, ",", &saveptr)
       ) {
      szptrn = sz_pattern - strlen(pattern) - 1;

      if ( sanitize(ptr) != 0 ) {
         return -1;
      }
      strncat(pattern, ptr, szptrn);
      szptrn -= strlen(ptr);
      strncat(pattern, "|", szptrn);
   }     

   offset = strlen(pattern);
   pattern[offset-1] = ')'; pattern[offset] = '$'; pattern[offset+1] = '\0';

   return 0;
}

Sanitize是O(n),但for循环将运行k次(k是字符串中逗号的数量)。

那么,k * O(n)仍然是O(n),是O(n ^ 2),O(k.n)还是别的什么?

感谢。

3 个答案:

答案 0 :(得分:4)

一目了然地向我看O(n)。

  • strtok_r()遍历原始字符串= O(n)

  • 你说的
  • sanitize()是O(n),但这可能是关于令牌的长度而不是原始字符串的长度< / em>,所以将令牌长度乘以令牌数= O(n)

  • strncat()最终复制所有原始字符串,没有重叠= O(n)

  • 您将一定数量的字符附加到输出字符串(^()$和几个NULL)= O( 1)

  • 您为每个标记的字符串附加| = O(n)

但等等!

  • 对于循环的每次迭代,您在输出模式上调用strlen() = O(n ^ 2)

所以有你的答案。

答案 1 :(得分:2)

我喜欢接近它的一种方法是用运行时替换代码,例如

val_buffer[0] = '\0';
strncat(val_buffer, value, sizeof(val_buffer) - 1);
val_buffer[sizeof(val_buffer) - 1] = '\0';

变为

O(1)
O(n) (* Assume the size of value is the size of the input *)
O(1)

循环

for each k in value {
  strlen(value)
}

变为

O(n) {
  O(n)
}

或其他类似的符号,然后您可以将其制作成O(n) * O(n) = O(n^2)。然后,您可以总结所有列出的大哦时间,以获得最终的时间复杂度。

类似的伎俩是首先用你的工作量计算所有代码,然后删除执行实际工作的代码,只留下计数。然后使用简单的数学来简化计数。即,

count = 0;
for (i = 0; i < k; i++) {
    count++
}

很容易被count = k替换。

答案 2 :(得分:0)

为什么每个人都假设strlen = O(n)?我以为O(n)只用于循环。