我已经用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)
我的符号是否正确?还有更好的方法来做同样的功能吗?
提前致谢!
答案 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++;
}
}