这个双重for循环执行了多少次?

时间:2015-10-29 09:08:58

标签: algorithm runtime

void runner(int n, int a, int b){
    for(int i = 1; i <= n; i *= a)
        for(int j = 1; j <= i*b; j++)
            //run something here
}

是否有一种简单的方法可以确定执行“在这里运行”的次数?

我认为外循环将运行n / a次,但我无法确定内循环运行的次数。

4 个答案:

答案 0 :(得分:6)

一般配方是:写出确切的公式,看看如何简化它。

在外部循环中,i变量更改为1,然后更改为a,然后更改为a*a,依此类推。对于i的每个值,内循环运行b*i次。所以我们有运行时

b + b*a + b*a*a + ... + b*a^k

其中^表示权力,k=floor(log_a(n))(此处为基数 - a对数)。

此总和为

b*(1 + a*a + ... + a^k) = b*(a^(k+1)-1)/(a-1)

这是确切的答案。对于O - 符号或近似值,您可以假设a^(k+1)大约为n(但请参见下面的注释),因此运行时

b*(n-1)/(a-1)

对于大型na,我们有

b*n/a

注意:实际上对于大a a^(k+1) n可能无效的假设;对于某些a*n,它可能与n一样大。

答案 1 :(得分:3)

外环不会运行n / a次,即i + = a。而是运行log(a,n)。 考虑n = 30,a = 2。这将提供以下内容:

运行我
1个2
2个4
3个8
4个16
5个32
所以第五次它不会执行。这类似于log(2,30)(或log(30)/ log(2))的行为,返回约4.906。

因此,第一个循环运行4次。

现在说你有这个内部循环:

for(int j = 1; j <= i; j++)

首先运行1次,然后运行2次,然后运行4次,然后运行8次,然后运行16次。总时间是:

  

1 + 2 + 4 + 8 + 16

等于(2^m)*2-1,其中mlog(2,30)。在这种情况下,它是10,所以内循环将运行31次。

现在你的内部循环中有一个i*b。这意味着它将运行b次。换句话说,((2^m)*2-1)*b

总的来说,我们有:

int m = (int)Math.floor(log(a,n));
return ((a^m)*a-1)*b/(a-1);

这可以缩短为:

Return a^Math.floor(log(a,n))*b;

如果我错了,请纠正我,因为我没有检查任何东西。我的头脑是一个有趣的挑战。

答案 2 :(得分:0)

  1. 声明一个新的int并为其赋予值&#39; 0&#39;
  2. 使内部循环增加新的int(您的注释所在的位置)
  3. 使其在结尾处或循环内打印
  4. 查看结果
  5. Java示例:

    void runner(int n, int a, int b){
        int x = 0;
        for(int i = 1; i <= n; i *= a)
            for(int j = 1; j <= i*b; j++)
                x++;
                System.out.println(x);
    }
    

答案 3 :(得分:-1)

void runner(int n, int a, int b){
    int counter=0;
   for(int i = 1; i <= n; i *= a)
        for(int j = 1; j <= i*b; j++)
           counter++;

  PRINT COUNTER'S VALUE
}

使用调试器查看计数器的增量精确程度。