该算法的复杂度函数

Posted

技术标签:

【中文标题】该算法的复杂度函数【英文标题】:Complexity function of this algorithm 【发布时间】:2016-04-12 01:55:01 【问题描述】:

我正在尝试找到该算法的最坏情况复杂度函数,将比较语句视为最相关的操作。那是ifelse if总是在循环下执行的时候,所以函数是2*循环执行次数。

由于变量i 每次复杂度可能为 O(log n) 时都会增加一个更大的数字,但我如何找到执行的准确次数?谢谢。

  int find ( int a[], int n, int x )     
  int i = 0, mid;
  while ( i < n ) 
     mid = ( n + i ) / 2;
     if ( a[mid] < x )
        n = mid;
     else if ( a[mid] > x )
        i = mid + 1;
     else return mid;
     
return 0;

【问题讨论】:

每次执行循环大小减少一半。所以如果你有 n 个元素,那么 pow(2,x) = n。其中 x = 迭代次数。(因为在最坏的情况下,循环在 i >=n 时终止)。所以 x = log2 (n)。 “因为变量 i 每次都增加一个更大的数字” - 不,不是:如果它正在增加(因为 x 仍然大于 @987654326 @),每次都会减少一半 - 即每次增加一个较小的数字。无论如何......“可能O(log n)”是正确的......更具体地说是O(log-base-2(N))。 “但是我如何找到确切的执行次数?” 要找到“更糟糕的情况复杂度函数”,您不需要确切的执行次数;复杂性分析忽略了常数因素,需要不断减半搜索是最坏的情况。 谢谢各位,当 else if 为真时,你能解释一下为什么 log(2,n) 吗?当 if 语句为真时,我可以看到。 【参考方案1】:

定性理解


好吧,让我们尝试看看循环不变量,以了解这个函数要运行多长时间

我们可以看到该函数会继续执行代码,直到满足while(i &lt; n) ... 这个条件。

我们还要注意,在这个while 循环中,i n总是被变异为mid 的某些变体:

if ( a[mid] < x )        # Condition 1:
    n = mid;             #   we set n to mid
else if ( a[mid] > x )   # Condition 2:
    i = mid + 1;         #   we set i to mid+1
else return mid;         # Condition 3: we exit loop (let's not worry about this)

所以现在让我们关注mid,因为我们的while 条件似乎总是根据这个值被削减(因为while 条件取决于in,其中之一将每次循环迭代后设置为mid的值):

mid = ( n + i ) / 2;     # mid = average of n and i

查看这些函数后,我们可以有效地看到这里发生了什么:

函数将在i &lt; n时执行代码,每次循环迭代后in的值设置为平均值,有效地将in之间的空间减少了一半每次循环迭代。

这个算法被称为binary search,其背后的想法是我们每次在循环中迭代时都将数组边界减半。

所以你可以把它想象成我们一直把n切成两半,直到我们不能再切成两半

定量分析


查看此问题的数学方法是查看我们在每次迭代中有效地将 n 除以 2,直到 in 彼此相等(或 n &lt; i)。

所以让我们考虑一下我们可以将 n 除以 2 多少次直到等于 1?在这种情况下,我们希望我们的 n 等于 1,因为那是我们无法进一步拆分列表的时候。

所以我们得到了一个等式,其中x 是我们执行while 循环所需的时间:

n/2^x = 1
n = 2^x
lg(n) = lg(2^x)
lg(n) = x lg(2)
lg(n) = x

如您所见,x = lg(n) 因此我们可以得出结论,您的算法在 O(lgn) 中运行

【讨论】:

以上是关于该算法的复杂度函数的主要内容,如果未能解决你的问题,请参考以下文章

这个回文算法的时空复杂度?

算法的时间复杂度

O(n)是啥

数据结构与算法-怎样计算时间复杂度

该算法的比特成本时间复杂度是多少(Java 示例)?

[算法]时间复杂度