Big O的两个功能

时间:2011-11-29 04:55:36

标签: php performance optimization big-o

我已经用PHP编程很长一段时间了,因为我不是来自计算机科学/数学背景我只对Big O符号有基本的了解,所以我采取了一个函数并尝试改进它并在Big O中表达它们:

示例1

function foo($j) {
    $ids = array();
    while (count($ids) < $j) {
        $id = gen_id();  // assume this function will return you an integer
        if (!in_array($id, $ids)) {
            $ids[] = $id;
        }
    }
    return $ids;
}

我会通过删除count($ids)的while循环并用for循环替换来改进此函数,以便每次循环都不需要评估count($ids),并且将is_array替换为isset并将值移至键(isse t比in_array更快)

示例2 - 改进

function foo($j) {
    $ids = array();
    for($i = 1; $i<= $j; ++$j) {
        $id = gen_id();  // assume this function will return you an integer
        if (!isset($ids[$id])) {
            $ids[$id] = true;
        }
        else {
            --$i;
        }
    }
    return $ids;
}

我会用以下Big O表示法表达上述函数:

示例1: O(n ^ 2),示例2: O(n)

我的符号是否正确?还有更好的方法来做同样的功能吗?

提前致谢!

4 个答案:

答案 0 :(得分:1)

首先:常数系数在Big O表示法中无关紧要,对于任何常数O(n) = O(cn),这意味着c != 0

对于第一个,我知道count($ids)需要O(1)时间来评估,但in_array($id, $ids)怎么样?我完全不知道。但如果它是O(n)O(logn),那么整体将是O(n^2)O(nlogn)。我不认为这可以在O(1)时间内实施,这可能会为整个功能提供O(n)时间。

对于第二个,这是O(n),看起来比第一个快。

编辑:我只是认为维基百科以某种方式清楚地描述了the big O notation。去读一些。

答案 1 :(得分:1)

以下是我如何以更直接的方式编写该函数:内部for循环是do ... while循环的完美场景。

function foo( $j)
{
    $ids = array();
    for( $i = 0; $i < $j; $i++)
    {
        do
        {
            $id = gen_id();
        } while( isset( $ids[$id]));
        $ids[$id] = true;
    }
    return $ids;
}

修改:实际上,此功能为O($j) / O(n),因为gen_id()isset()都是常量O(1)isset()是哈希表查找)。因此,for循环的内部效率是恒定时间O(1),使整个函数O(n)

答案 2 :(得分:1)

你的想法很好,但你不正确。

以下内容将澄清你......

function foo($j) 
{
 for($i=1;$i<j;$i++)
 {
  // some code here
 }
 for($i=1;$i<j;$i++)
 {
 // some code here
 }
}

您可能认为这将是0(2n)但是常数项不表示为0表示法。所以 它的复杂度为0(n)。

查看以下内容

 function foo($j) 
{
 for($i=1;$i<j;$i++)
 {
    for($k=1;$k<i;$k++)
    {
     // some code here
    }
 }

}

它的复杂度为0(n ^ 2)。

答案 3 :(得分:1)

for ($i=0;$i<$j; ) {
  $id = gen_id();
  if (!isset($ids[$id])) {
    $ids[$id]=true;
    $i++;
  }
}