Java 为什么我在这两个不同的嵌套for循环中得到不同的时间复杂性?

Java 为什么我在这两个不同的嵌套for循环中得到不同的时间复杂性?,java,performance,time-complexity,big-o,nested-loops,Java,Performance,Time Complexity,Big O,Nested Loops,好的,我知道两个嵌套的for循环,每个循环递增1,就得到了二次时间复杂度。然后我好奇地想知道如果我改变其中一个循环的更新,以2的乘法递增,我会得到O(n logn)而不是O(n^2),反之亦然 在每个内部循环中,我都有一个变量来计算循环执行的次数。数组大小为2^20,因此为1048576。我认为这两种方法应该具有相同的复杂度n logn(20*1048576)。但只有算法2接近该复杂度,算法1的复杂度为n*2 据我所知,一个循环是O(n),另一个是O(logn),所以它应该是O(n logn),

好的,我知道两个嵌套的for循环,每个循环递增1,就得到了二次时间复杂度。然后我好奇地想知道如果我改变其中一个循环的更新,以2的乘法递增,我会得到O(n logn)而不是O(n^2),反之亦然

在每个内部循环中,我都有一个变量来计算循环执行的次数。数组大小为2^20,因此为1048576。我认为这两种方法应该具有相同的复杂度n logn(20*1048576)。但只有算法2接近该复杂度,算法1的复杂度为n*2

据我所知,一个循环是O(n),另一个是O(logn),所以它应该是O(n logn),如果我切换它们,我应该得到O(logn)的复杂度,这是相同的

 int[] arr = new int[1048576];

    // Algorithm 1
    int counter1 = 0;
    for (int i = 1; i < arr.length; i++) {
        for (int j = i; j < arr.length; j *= 2) {
            counter1++;
        }
    }
    System.out.println(counter1);

    // Algorithm 2
    int counter2 = 0;
    for (int i = 1; i < arr.length; i *= 2) {
        for (int j = i; j < arr.length; j++) {
            counter2++;
        }
    }
    System.out.println(counter2);

    // counter1: 2097130 (n * 2)
    // counter2: 19922945 (n log n)
int[]arr=newint[1048576];
//算法1
int计数器1=0;
对于(int i=1;i
您发布的两个解决方案都具有相同的复杂性,我假设您忘记了将内部for循环begin子句变量交换

具有常数因子的O(n^2)。 Big-O表示法的工作原理如下:

n/2*n是循环所需的时间(两个u中的任意一个)

->1/2*n*n=1/2*n^2

1/2是因素。
复杂性是多项式,n^2是简单的数学。现在假设
w*=2
基本上需要20个步骤才能达到大约100万


Algo 1将运行大约100万个j循环,但每个循环只需要大约20个j步骤即可完成。您在algo2上运行内部循环(尤其是第一次)的次数是数百万,而另一个将运行让我们计算第二个算法每个循环中的通过次数。让我们取
N=arr.length

首先是最外层的环。i的范围从1到N,每次乘以2,这使得
log(N)
迭代

然后,在最内部的循环中,j的范围从i到N,并且每次递增1,从而进行(N-i)次迭代

现在让我们看一下
k=log(i)
。因此,当k=0时,计数器2增加的总次数为总和(N-2^k),以记录(N)

k=0到2^k的对数(N)之和是一个几何和,加起来等于2^(对数(N)+1)-1so2n-1

因此,第二个循环的总复杂度是Nlog(N)-2N+1,即O(Nlog(N)),就像第一个循环一样

差是二阶项2N。如果我们推动我们的开发,第一个循环的复杂性为:

Nlog(N) + O(1)
第二点:

Nlog(N) - 2N + O(1)

这两个循环的时间复杂度不同,因为这两个循环不是模棱两可的
n
。这是因为第一个算法的指数衰减消除了额外的步骤。