在整数中计算尾随零的效率最高是多少?

时间:2015-07-05 18:26:55

标签: algorithm math

正常的方式是

int main(){
  int a=2000,count=0,temp;
  while(a!=0)
  {
    temp=a%10;
    if(temp==0) count++
    else break;
    a/=10;
  }
  printf("%d",count);
}

有更有效的方法吗?

3 个答案:

答案 0 :(得分:4)

对于32位整数(最大值2147483647),您最多只需要4次测试。对于64位,再添加一个16个零的测试。

从10的较大权力开始并逐渐减少:

int countTrailingZeros(int n)
{
    int zeros = 0;
    if((n % 100000000) == 0)
    {
        zeros += 8;
        n /= 100000000;
    }
    if((n % 10000) == 0)
    {
        zeros += 4;
        n /= 10000;
    }
    if((n % 100) == 0)
    {
        zeros += 2;
        n /= 100;
    }
    if((n % 10) == 0)
    {
        zeros++;
    }
    return zeros;
}

这有一个更好的最坏情况表现,但如果你传递的数字的9/10没有尾随零,那么平均情况更糟。它只取决于您在典型情况下传递给它的值。

但是,如果您传递的数字的十分之九没有尾随零,那么您可能不必担心首先优化原始代码,因为它会在循环的第一次迭代中中断90%当时。

答案 1 :(得分:3)

您可以在此处调整二进制搜索的概念。 可能很难编码,但这是一个想法(因为你要求最有效的方式,我只是提出这个想法)。

我不只是谈论32位整数或64位整数。

当0的数量很高时,这种效果非常好,否则也应该是有效的。

说出您的电话号码是n

首先检查n%(10^1) == 0是否

然后检查n%(10^2) == 0是否

然后检查n%(10^4) == 0是否为10^8 ....10^16。我想你明白了。

所以最后你会得到一个点n % 10^(2x) !=0,现在你知道没有。 0的{​​{1}}位于x2x之间。

所以再次从xx+1x+2 ....开始进行二元搜索,直到找不到n % 10^(2y) != 0 (x < y <= 2x)的情况。重复相同的过程。

时间复杂度(如果你有K 0):

最好的情况是:

    O(logK)

最坏的情况是:

     ceil(log(K)) + ceil(log(k/2)) + ..... 1 = ~ O(logK)

答案 2 :(得分:2)

至少你通过每零只有一个分区来提高速度:

c = 1;
while (a % c == 0) {
    c *= 10;
    cout ++;
}

(可能你还需要在*=10溢出时准确处理案例。

这仍然是同样的复杂性。但是,对于int我怀疑你需要更高的复杂度,因为最大可能的零数非常小。