这两种位计数算法具有相同的时间复杂度吗?

时间:2015-01-08 16:03:21

标签: algorithm big-o time-complexity hammingweight

下面是我在某处找到的算法(忘记确切地说,可能来自this answer)来计算整数中设置的位数,即汉明重量。

function hamming_weight($i)
{
    $i = $i - (($i >> 1) & 0x55555555);
    $i = ($i & 0x33333333) + (($i >> 2) & 0x33333333);
    return ((($i + ($i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}

(我碰巧在PHP中使用它,但这可能是任何语言。)
如果我没有特别错误,那就是在O(1)中运行 - 毕竟没有分支。

现在这里是我自己编写的一个计数函数,除了可读性之外,我认为它更低:

function hamming_weight_2($i)
{
    $weight = 0;
    for ($k = 1, $s = 0; $k < 0xFFFFFFFF; $k *= 2, $s++)
    {
        $weight += (($i & $k) >> $s);
    }
    return $weight;
}

然而,以什么方式低劣?起初我认为&#34;那里有一个循环,所以这应该在线性时间运行&#34;,但后来我意识到循环根本不取决于输入的大小。无论$ i的大小如何,迭代次数都保持不变。

我想知道的是:

  • 真的可以说这两个算法都在O(1)中运行吗?
  • 如果是这样,是否有措施区分两者?似乎第一个应该是一些方式更好。

4 个答案:

答案 0 :(得分:4)

在这种情况下,根据大O复杂度来看问题没有意义,因为变量中有一定数量的位。相反,你应该计算个别操作:

算法1:

  • Bitwise Ands:4
  • Bitshifts:4
  • 增加/减少:3
  • 乘法:1

算法2:

  • Bitwise Ands:32
  • Bitshifts:32
  • 增加/减少:64
  • 乘法:32

即使允许用额外的位移代替这些乘法,第二种算法也要做更多的工作。

答案 1 :(得分:1)

  

真的可以说这两种算法都在O(1)中运行吗?

当然,是的。任何在固定时间内独立于其输入大小运行的算法都可以说是O(1)。

  

如果是这样,是否有措施区分两者?似乎第一个应该在某种程度上更好?

具有相同渐近复杂度的算法的区别在于常数因子。这适用于任何渐近复杂度的算法,而不仅仅是O(1)算法。

您可以通过将根据这些算法执行计算所需的基本操作相加来计算常量。计数在循环外执行的操作,并在循环内添加操作计数乘以在最坏情况下(即32)循环执行的次数。

虽然这两种算法具有相同的渐近复杂度,但据说第一种算法具有小得多的常数因子,因此比第二种算法更快。

答案 2 :(得分:0)

f(n)= O(g(n))表示对于所有n≥N,f(n)小于或等于c * g(n)对于某些N> 1。 0和某些c> 0. c组件可能很重要。如果一个算法在n纳秒内运行而另一个算法在n小时内运行,则它们在Big-O表示法中都具有相同的时间,但是一个算法的速度稍微快(几千亿次)。显然,没有什么值得关注的。几乎没有任何区别。

PS。计算单个字中的位数很少很重要。为了计算单词数组中的位,两种算法都是次优的。

答案 3 :(得分:0)

嗯,这取决于。请注意,它们都不是算法,而是它们的实现。这是不同的,因为在实现中你总是有一个恒定的位数。是的,总是 - bigint也受常数限制,因为数组大小受常数限制。显然,这样思考是没用的。

所以让我们以不同的方式看待它。首先,考虑概念算法而不是实现。整数现在是n位长,你展示的代码推广到它们的n位形式。第一个是O(log n)步,第二个是O(n)。但这些步骤需要多长时间?这取决于你的抽象机器。这是一种堆栈溢出的传统,假装唯一的抽象机器存在&#34;存在&#34; (在柏拉图意义上)是RAM机器,或者可能是图灵机。但还有更多。例如,PRAM,其中您不必限于恒定数量的并行处理元素。

n位加法在具有足够处理器的PRAM机器上占用O(log n)时间(因此,至少为n),按位运算显然只在具有至少n个处理器的PRAM机器上占用O(1),因此第一个算法给出O(log(n) 2 ),第二个算法给出O(n log n)。

但是你可以更进一步,并假设n位上的所有操作都需要恒定的时间。我确定有人会评论你不能这样做,但你实际上可以假设你想要的任何东西(特别是查找超级计算)。如果你想一想,O(log n)位上的操作需要恒定时间的通常假设也很奇怪。无论如何,如果&n;位操作是O(1)&#34;是你正在使用的,第一个算法的O(log n)和第二个算法的O(n)。