Java -- detailed explanation of time complexity and space complexity

Keywords: Java Algorithm

Algorithm efficiency

In use, the algorithm efficiency is divided into two types: one is time efficiency (time complexity) and the other is space efficiency (space complexity). Time complexity refers to the speed at which the program runs. Spatial complexity refers to the additional space required by an algorithm.

Time complexity

What is time complexity

The running time of a computing program cannot be calculated with a simple time, because the ability of different processors to process data is different. Therefore, only an approximate number of times is enough, just like the execution times of basic operations in the algorithm. It is expressed by the asymptotic method of large O

Example: the basic operation of calculating func1 has been performed several times

void func1(int N){
    int count = 0;
    for (int i = 0; i < N ; i++) {
        for (int j = 0; j < N ; j++) {
            count++;
        }
    }
    for (int k = 0; k < 2 * N ; k++) {
        count++;
    }
    int M = 10;
    while ((M--) > 0) {
        count++;
    }
    System.out.println(count);
}

The basic execution times of func1 are: F(N) = N^2 + 2*N + 10

Method for deriving large O-order

1. Replace all addition constants in the run time with constant 1.
2. In the modified run times function, only the highest order term is retained.
3. If the highest order term exists and is not 1, the constant multiplied by this item is removed. The result is large O-order.

Therefore, after using the asymptotic method of large o, the time complexity of func1 is O(N^2)

Algorithm situation

Because when we use the algorithm, there will be the best case, the worst case and the average case. The time complexity we often say is O(N), and the time complexity here is the worst case.
The best case is the minimum number of runs.

Example 1:

void func2(int N){
    int count = 0;
    for (int k = 0; k < 2 * N ; k++) {
        count++;
    }
    int M = 10;
    while ((M--) > 0) {
        count++;
    }
    System.out.println(count);
}

The result here is O(N). Because the constant is removed according to the calculation method of time complexity, 2*N is N. M is 10, which can also be ignored.

Example 2:

void func3(int N, int M) {
    int count = 0;
    for (int k = 0; k < M; k++) {
        count++;
    }
    for (int k = 0; k < N ; k++) {
        count++;
    }
    System.out.println(count);
}

The time complexity here is O(M+N). Because the values of M and N are unknown, it is O(M+N)

Example 3:

void func4(int N) {
    int count = 0;
    for (int k = 0; k < 100; k++) {
        count++;
    }
    System.out.println(count);
}

The time complexity of this is O(1). Because there are constants in the loop, according to the large o asymptotic method, the result is O(1)

Calculating the time complexity of bubble sorting

public static void bubbleSort(int[] arr){
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if(arr[j] > arr[j+1]){
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }
    }
}

Because of the particularity of bubble sorting, it may be arranged at one time or until the end, so there are the best and worst cases.

Best case: compare once, that is, O(N)
Worst case: O(N^2) is the last one

Calculating the time complexity of binary search

int binarySearch(int[] array, int value) {
    int begin = 0;
    int end = array.length - 1;
    while (begin <= end) {
        int mid = begin + ((end-begin) / 2);
        if (array[mid] < value)
            begin = mid + 1;
        else if (array[mid] > value)
            end = mid - 1;
        else
            return mid;
    }
    return -1;
}

Because binary search is half and half, the search range will be halved after each search. For example, finding 8 in a 1 - 8 ordered array is the worst case. The diagram is as follows:

As shown in the figure, it takes log2n - 1 times to complete the binary search in the array, that is, the time complexity is log2n (that is, the logarithm of log with base n of 2)

Computing the time complexity of factorial recursion

long factorial(int N) {
	return N < 2 ? N : factorial(N-1) * N;
}

Calculate the time complexity of recursion: the number of recursions * the number of times each recursion is executed.

Therefore, during this recursion, the basic operation recurses N times, so the time complexity is O(N)

Calculate the time complexity of Fibonacci recursion?

int fibonacci(int N) {
	return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);
}

Suppose N is 5, let's expand the solution


As shown in the figure: each calculation will calculate the next layer, but each time it is less and more. So it can be calculated directly according to the same on each side. As shown below:


Therefore, there is a formula to calculate the times of each calculation, that is, 2 ^ (n - 1), so the calculation result is: 2 ^ \ 0 + 2 ^ 1 + 2 ^ 2 + 2 ^ 3... 2^(n-1) = 2^n+1, so it is calculated according to the big O asymptotic method, and the result is 2^n.

So the time complexity of Fibonacci sequence is 2^n.

Spatial complexity

Space complexity measures the size of additional storage space occupied by an algorithm during operation, because it is not necessary to calculate according to bytes, but the number of variables. It is also expressed by the large O asymptotic method.

Calculating the spatial complexity of bubble sorting

public static void bubbleSort(int[] arr){
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if(arr[j] > arr[j+1]){
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }
    }
}

The space complexity is O(1) because the variables of bubble sorting do not change and the additional space is constant.

Calculate the spatial complexity of Fibonacci sequence (non recursive)

int[] fibonacci(int n) {
    long[] fibArray = new long[n + 1];
    fibArray[0] = 0;
    fibArray[1] = 1;
    for (int i = 2; i <= n ; i++) {
        fibArray[i] = fibArray[i - 1] + fibArray [i - 2];
    }
    return fibArray;
}

Because the Fibonacci sequence here opens up n additional spaces, the spatial complexity is O(n).

Time complexity of computing Factorial recursive Factorial

int factorial(int N) {
	return N < 2 ? N : factorial(N-1)*N;
}

Because it is recursive, each recursion will open up stack frames, and each stack frame occupies a constant space, so the space complexity is O(N).

Posted by ol4pr0 on Thu, 04 Nov 2021 15:35:04 -0700