1. Time efficiency
There are two kinds of algorithm efficiency analysis: the first is time efficiency and the second is space efficiency. Time efficiency is called time complexity, and space efficiency is called space complexity. Time complexity mainly measures the running speed of an algorithm, while space complexity mainly measures the additional space required by an algorithm.
2. Time complexity
2.1 concept of time complexity
1. Definition of time complexity: in computer science, the time complexity of an algorithm is a function that quantitatively describes the running time of the algorithm. The execution times of basic operations in the algorithm is the time complexity of the algorithm.
2.2 progressive representation of large O
1. Code:
// Please calculate how many times func1 basic operations have been performed? 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); } Func1 Number of basic operations performed: F(N)=N^2+2N+10 Func1 Use big O After order representation: F(N)=N^2;
In fact, when we calculate the time complexity, we do not have to calculate the exact execution times, but only the approximate execution times. Here, we use the asymptotic representation of large O.
Big O notation: a mathematical symbol used to describe the asymptotic behavior of a function.
2. Derivation of large O-order method:
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.
3. Through the above, we can find that the progressive representation of big O removes those items that have little impact on the results, and succinctly shows the execution times.
3. The time complexity of the algorithm has the best, average and worst cases:
Worst case: maximum number of runs of any input scale (upper bound)
Average case: expected number of runs of any input scale
Best case: minimum number of runs of any input scale (lower bound)
2.3 common time complexity calculation examples
1. 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 basic operation of example 1 was performed 2N+10 times. It is known that the time complexity is O(N) by deriving the large O-order method
2. 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 basic operation of example 2 is executed M+N times, with two unknowns M and N, and the time complexity is O(N+M).
3. Example 3:
void func4(int N) { int count = 0; for (int k = 0; k < 100; k++) { count++; } System.out.println(count); }
The basic operation of example 3 is performed 100 times. By deriving the large O-order method, the time complexity is O(1)
4. Example 4:
void bubbleSort(int[] array) { for (int end = array.length; end > 0; end--) { boolean sorted = true; for (int i = 1; i < end; i++) { if(arr[i-1]>arr[i]){ Swap(array, i - 1, i); sorted = false; } } if (sorted == true) { break; } } }
In example 4, the basic operation was performed for the best N times and the worst (N*(N-1))/2 times. By deriving the large O-order method + time complexity, it is generally the worst, and the time complexity is O(N^2)
5. Example 5:
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; }
In example 5, the basic operation is performed for the best time and the worst time O(logN) times. The time complexity is O(logN) ps: logN is expressed as base 2 and logarithm N in algorithm analysis.
6. Example 6:
long factorial(int N) { return N < 2 ? N : factorial(N-1) * N; }
Through calculation and analysis, it is found that the basic operation recurses N times and the time complexity is O(N).
7. Example 7:
int fibonacci(int N) { return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2); }
Through calculation and analysis, it is found that the basic operation recurses 2^N times
, time complexity is O(2^N)
3. Space complexity
1. Space complexity is a measure of the amount of storage space temporarily occupied by an algorithm during operation. Space complexity is not how many bytes the program occupies, because it doesn't make much sense, so space complexity is the number of variables. The calculation rules of spatial complexity are basically similar to the practical complexity, and the large O asymptotic representation is also used.
2. Example 1:
void bubbleSort(int[] array) { for (int end = array.length; end > 0; end--) { boolean sorted = true; for (int i = 1; i < end; i++) { if (array[i - 1] > array[i]) { Swap(array, i - 1, i); sorted = false; } } if (sorted == true) { break; } } }
The space complexity is O(1) because two extra spaces are used
3. Example 2:
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; }
N spaces are opened up dynamically, and the space complexity is O(N).
4. Example 3:
long factorial(int N) { return N < 2 ? N : factorial(N-1)*N; }
Recursively called N times, opened up N stack frames, and each stack frame uses a constant space. The space complexity is O(N)