请教一道搜狗笔试题——计算算法的复杂度

qianshe223 2011-09-18 03:22:13
去搜狗参加了一下笔试面试,被鄙视了。。。
有一道分析算法复杂度的问题,我一直都不咋会分析算法复杂度,看到就懵了,没做。
回来求教一下版上的大虾,求指教算法复杂度的计算方式,尤其是递归算法!!!
题目:
分析给定代码的时间复杂度。

void foo();
void bar(int k){
if(k>0){
do{
k=k/2;
bar(k);
}while(k)
}else{
foo();
}
}
void xxx(int n){
for(int i=1;i<n;i+=i){
bar(i);
}
}

分析xxx函数的复杂度是多少。


...全文
888 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
当当兽 2011-11-16
  • 打赏
  • 举报
回复
bar() W(k)=kW(k/2):w(k)=lgk
xxx() n次循环:nw(k)=o(nlgn)
哲学与编程 2011-09-19
  • 打赏
  • 举报
回复
令T(n)为bar(n)的复杂度,可以推出T(n)=2*T(n/2)?可令循环展开
void bar(int n)
{
if(n>0){
k = n/2;
bar(k); // 第一次bar(n/2)
// 余下这些也相当于调用bar(n/2)一次
do{
k=k/2; bar(k);
}while(k);
}else
{
foo();
}
}

èbar(n) = bar(n/2)+bar(n/4)+…+bar(1) A
èbar(n/2) = bar(n/4)+…+bar(1) B
A-B è bar(n/4)+…+bar(1) = bar(n/2) C
C带入Aè bar(n) = 2*bar(n/2) D
由Dè bar时间复杂度0(n) E

XXX的复杂度 = o(n)+o(n/2)+…+0(1), 不妨设0(n)运算次数为2^K
2^K + 2^(K-1)+…+2^0 = 2^(k+1)-1≈2*o(n), 所以XXX的时间复杂度为o(n)

转载自我一同学。
qianshe223 2011-09-19
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 whwangfei 的回复:]

令T(n)为bar(n)的复杂度,可以推出T(n)=2*T(n/2)?可令循环展开
void bar(int n)
{
if(n>0){
k = n/2;
bar(k); // 第一次bar(n/2)
// 余下这些也相当于调用bar(n/2)一次
do{
k=……
[/Quote]

我也搞清楚了,确实是这样,你们真牛啊
哲学与编程 2011-09-18
  • 打赏
  • 举报
回复
看下面这段展开do{}while循环的第一次循环,明显bar(n)相当于调用了两次bar(n/2),因此T(n)=2*T(n/2是正确的。

void bar(int n){
if(n>0){
k = n/2;
bar(k); // 第一次bar(n/2)

// 余下这些也相当于调用bar(n/2)一次
do{
k=k/2;
bar(k);
}while(k);

}else{
foo();
}
}
TKD03072010 2011-09-18
  • 打赏
  • 举报
回复
算法题目 应该到算法专区 里面的大牛多
递归一般的复杂度是 O(2^n)
哲学与编程 2011-09-18
  • 打赏
  • 举报
回复
可以先求下bar(n)的复杂度:
另T(n)为bar(n)的复杂度,可以推出T(n)=2*T(n/2) ==> bar(n)的复杂度为O(n)。
结果就是O(n) + 0(n/2) + O(n/4) +...+O(1) = O(n)

所以我觉得是O(n),轻拍,各位大牛~
daijope 2011-09-18
  • 打赏
  • 举报
回复
i+=i相当于i = i*2;这样的话,xxx最外面的时间复杂度是log(n)。
里面 k=k/2;时间复杂度也是log(n)。但是还有递归调用,k的值只有2/k 也就是log(n/2),log(n/2) = long(n) - 1;

也就是说bar的时间复杂度是:(1 + 2 + 3 + .. + log(n)) + (1 + 2 + 3 + ... + (log(n) - 1)) + (1 + 2 + 3 + ...+ (log(n) - 2)) + ... + 1;

上面的计算一下就是:(1 + log(n))(log(n)/2 + (1 + log(n))(log(n)/2 - 1 + (1 + log(n))(log(n)/2 - 2 + ... + 2 + 1;

也就是:((1 + log(n))(log(n)/2 + 1)(1 + log(n))(log(n)/4;

化简一下时间复杂度就是O( log(n)^4)

在加上外面一层的log(n),所以总的时间复杂度应该是O(log(n)^5).

这只是我自己的想法,不知对不对,希望不要误导别人了。
  • 打赏
  • 举报
回复
算法中 O(N*lg(N)) 与 O(lg(N!)) 是一样的,呵呵,详见:

http://en.wikipedia.org/wiki/Big_O_notation#Orders_of_common_functions

O(N*lg(N)) 算法效率的算法有:快速傅立叶变换;堆排序、快速排序、归并排序等排序算法。
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 qianshe223 的回复:]

引用 2 楼 bao110908 的回复:

bar 的循环次数是 lgN(lg 表示以 2 为底的对数)
xxx 的执行的次数就是每个 bar 的次数相加,即:

1 + lg(2) + lg(3) + lg(4) + ... + lg(N)
= 1 + lg(2 * 3 * 4 * .. * N)
= 1 + lg(N!)

因此 xxx 的复杂度(忽略常数项)是 lg(N……
[/Quote]

这个效率比 N(lgN) 稍微小一些,应该算是很低的了。
DriftKing 2011-09-18
  • 打赏
  • 举报
回复
算法复杂度是 《数据结构》中讲的,有点印象,但忘记的差不多了,应该不像2楼说的那样。
楼主可以参考下面的研究下:
http://blog.csdn.net/popkiler/article/details/2110144
qianshe223 2011-09-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 bao110908 的回复:]

bar 的循环次数是 lgN(lg 表示以 2 为底的对数)
xxx 的执行的次数就是每个 bar 的次数相加,即:

1 + lg(2) + lg(3) + lg(4) + ... + lg(N)
= 1 + lg(2 * 3 * 4 * .. * N)
= 1 + lg(N!)

因此 xxx 的复杂度(忽略常数项)是 lg(N!)

没学过《算法》,不知道是不是这样分……
[/Quote]

谢谢火龙果的解析,照这样的话,那这个小算法的复杂度十分高啊。
yexiongMYBH 2011-09-18
  • 打赏
  • 举报
回复
应该是根一个数列求和一样的,只是这个数列里面的每个元素也是一个数列。。我是这么理解的。不知道有没有帮到你,呵呵。
  • 打赏
  • 举报
回复
bar 的循环次数是 lgN(lg 表示以 2 为底的对数)
xxx 的执行的次数就是每个 bar 的次数相加,即:

1 + lg(2) + lg(3) + lg(4) + ... + lg(N)
= 1 + lg(2 * 3 * 4 * .. * N)
= 1 + lg(N!)

因此 xxx 的复杂度(忽略常数项)是 lg(N!)

没学过《算法》,不知道是不是这样分析是否正确?
原来缘来 2011-09-18
  • 打赏
  • 举报
回复
不懂,帮顶

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧