简体   繁体   中英

Why is this caterpillar algorithm O(n^2) not O(n^3)?

Can someone explain why this algorithm is O(n^2) ? According to this , it's O(n^2). The reason why I think it's O(n^3) is because outer loop (for x) runs n times, inner loop (for y) runs n-1 times, and in the worst scenario eg A = [8, 100, 101, 102, 103, 104, 105, 106, 107] , the while loop (for z) will run n-2 times hence overall O(n^3) .

For completeness, A is a sorted array with positive elements, a triplet (x, y, z) is a triangle if A[x] + A[y] > A[z] . Find how many triangles can be built from A.

        int TrianglesCount(int[] A)
        {
            int result = 0;
            for (int x = 0; x < A.Length; x++)
            {
                int z = x + 2;
                for (int y = x + 1; y < A.Length; y++)
                {
                    while (z < A.Length && A[x] + A[y] > A[z])
                        z++;
                    result += z - y - 1;
                }
            }
            return result;
        }

Let's take a closer look at the below snippet

int z = x + 2;
for (int y = x + 1; y < A.Length; y++)
{
   while (z < A.Length && A[x] + A[y] > A[z])
      z++;
   result += z - y - 1;
}

The for loop is clearly executed A.lenght - (x+1) times, which is O(n) . However, the inner while loop is executed at most A.length - (x+2) times in total, because each such execution increments value of z , and it can be incremented at most A.length - (x+2) times until the while condition fails. Again, this is at most O(n) . Thus, the total time complexity of this snippet can be bounded by O(n) + O(n) = O(n) .

Since the snippet is run for every of O(n) values of x , the overall time complexity is O(n^2) .

A similar idea is used in KMP algorithm for string matching.

You should note that z is initialized inside x-loop, not y-loop. And on every x-iteration z could be incremented maximum A.length - x - 2 times.

The trick lies in the fact that z is increased in total up to A.Length: Eg if we get unlucky in the first iteration:

  • x=0, y=1 and we get z to go from 2 to A.Length, in the subsequent y-loops, z won't be incremented at all.

Here is my take on explaining this.

First of all, you can't talk about complexity when n is small. The definition itself of complexity says that complexity only "means something" when n tends to infinity. For example, bubble sort on an array with 3 elements may seem like O(n).

With that taken out of the equation, here's about your algorithm:

Variable z is declared inside x-loop, not y-loop, therefore z will not be reinitialised every time y-loop is completed. What that means is that z will increase to A.length only once in each pass of x-loop. Once z reaches A.length, it won't increase any more and therefore it doesn't depend on the y-loop. I hope this explanation is adequate and that this problem is clearer to you now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM