我因为Big O复杂性而分析这种方法时遇到了问题。事实上,由于其混乱的性质,我也不确定该方法是如何工作的。现在,我所知道的是,数组中的“逐渐缩小的范围”将被搜索给定的数字。有人可以解释下面的代码,并指导我如何分析其复杂性?
static int foo(int a[], int u, int l, int x) {
while(l <= u) {
int s = (u-l+1)/3, f = l+s, b = f+s;
if(a[f] == x)
return f;
else if(a[b] == x)
return b;
else if(a[f] > x)
u = f-1;
else if(a[b] > x)
l = b+1;
else {
l = b-1;
u = f+1;
}
}
return -1;
}
答案 0 :(得分:1)
似乎l = low,u = upper,所以u-l是范围。 S则是范围的三分之一。该方法做了一些奇怪的事情,但在每次迭代中,范围缩小了三分之一。
如果范围缩小了一半(如二分搜索),那显然是log n。但是这样,每次都缩小了三分之一。你觉得怎么样?
答案 1 :(得分:0)
看起来这段代码在排序的数组a
中搜索较低的索引x
和较高的索引k
之间的值u
。它通过调整搜索区间的两端来完成此操作,并使用一系列子句调整搜索中包含的下限或上限。搜索s
的步长为范围(u - l_ + 1)
的三分之一,“暂定新界限”为f
和b
。根据解决方案是在新范围内还是现在,算法将搜索范围缩小到旧区域的三分之一。
为了更好地了解它是如何工作的,我建议你为循环的每次迭代打印出数字l
和u
;然后增加x
的大小(例如,每次加倍)并重复。
当您绘制循环次数与x的关系时,您将很快看到,对于大x,您是获得直线,抛物线还是其他东西。你可以从中获得一些见解;幸运的是,这种关系很快就会变得清晰。
认识到大多数时候你会调整到1/3的大小,所以迭代次数只会随着间隔的大小而缓慢上升 - 实际上,3倍的大间隔只需要再迭代一次。这是 O(log(n))过程的标志。
答案 2 :(得分:0)
这是ternary search,其复杂性仍为O(lgn)
。