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次,但我无法确定内循环运行的次数。
答案 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)
对于大型n
和a
,我们有
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
,其中m
为log(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)
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
}
使用调试器查看计数器的增量精确程度。