我读过这个主题:
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)还是别的什么?
感谢。
答案 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)只用于循环。