Data structure (2.1) - time complexity and space complexity calculation

foreword

(1) Because of the previous blog: data structure (2) - the algorithm has too little explanation for the calculation of time complexity and space complexity. So I will add multiple case explanations again.
(2) The previous article has already introduced in detail why our algorithm uses the concept of complexity. Therefore, my article will focus on how to calculate the complexity.

Time Complexity Calculation

(1) As mentioned in the previous blog, under normal circumstances, we will not consider space complexity. So I will focus on the calculation of time complexity.
(2) As we said before, the time complexity is the big O method used . (Note: If you don’t understand, please read the time complexity part of the algorithm in the previous article. I have already introduced it in detail.) (
3) Next, I will go directly to the code for calculation. I'll post the code first, then explain. If you are interested, you can look at the code and calculate it first, and then look at the analysis.

Example 1—Introduction training

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--)
	{
    
    
		++count;
	}
	printf("%d\n", count);
}

(1) According to the Big O calculation method, we know that we must first find the specific execution time of this function.
(2) First, we see that two for statements are nested, the first for statement needs to be executed N times, and the second for statement is nested inside, so the final number of executions is N^2 times.

	for (int i = 0; i < N ; ++ i)  //执行N次
	{
    
    
		for (int j = 0; j < N ; ++ j)  //执行N*N次,所以最终结果是执行了N^2次
		{
    
    
			++count;
		}
	}

(3) There is no nesting in the second for statement, the condition is judged to be <2*N, and it is incremented to 1 each time. So it needs to be executed 2N times here.

	for (int k = 0; k < 2 * N ; ++ k)
	{
    
    
		++count;
	}

(4) Execute M times in the last while, and M is given a constant of 10. So this while is executed 10 times.

	int M = 10;
	while (M--)
	{
    
    
		++count;
	}

(5) In summary, the final conclusion is that the number of executions of this code is as follows
T ( n ) = n 2 + 2 n + 10 T (n) = n^{2} + 2n +10Tn=n2+2 n+10
(6) According to the Big O method, it can be seen that when f(n) is n^2. n tends to infinity, and finally T(n)/f(n) is a constant. So the time complexity is O(n^2).
(7) To sum up, the Big O calculation method is to retain the highest number of code execution words.

Example 2—The constant for the highest term is not unique

void Func2(int N)
{
    
    
	int count = 0;
	for (int k = 0; k < 2 * N ; ++ k)
	{
    
    
		++count;
	}
	int M = 10;
	while (M--)
	{
    
    
		++count;
	}
	printf("%d\n", count);
}

(1) Similarly, first calculate the overall execution times of this function.
(2) For the first for loop, the judgment condition is k < 2 * N, and K is incremented to 1 each time, so it needs to be executed 2N times.

	for (int k = 0; k < 2 * N ; ++ k)
	{
    
    
		++count;
	}

(3) Similarly, this while is executed 10 times.

	int M = 10;
	while (M--)
	{
    
    
		++count;
	}

(4) Therefore, the final execution times of this function is 2N+10. So according to the Big O method, is this time complexity O(2N)?
(5) Seeing what I said, then the answer must be wrong. The Big O calculation method stipulates that if the constant of the highest term is not 1, the highest constant needs to be removed. For example, the highest item of this question is N, and its constant is 2, so the time complexity of this question is O(N).

Example 3—Multiple variables appear

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;
	}
	printf("%d\n", count);
}

(1) For this topic, we will find that there are two variables, so how to calculate the time complexity? In fact, it is not as complicated as imagined, just need to analyze according to the situation.
(2) First, assuming that N and M are about the same size, then the time complexity is O(N+M).
(3) Second, assuming that N is much larger than M, then the time complexity is O(N).
(4) Second, assuming that N is much smaller than M, then the time complexity is O(M).

Example 4 - unique number of executions

void Func4(int N)
{
    
    
	int count = 0;
	for (int k = 0; k < 100; ++ k)
	{
    
    
		++count;
	}
	printf("%d\n", count);
}

(1) When we look at this function, we will find that the incoming formal parameter N is not used. In other words, this function is fixed to run 100 times.
(2) For this situation, some people may be a little confused. So what is his time complexity?
(3) The Big O calculation method stipulates that if it is a function with a fixed number of executions. The time complexity is O(1).

Example 5—Multiple cases of execution times

const char * strchr ( const char * str, int character )
{
    
    
	while(*str != '\0')
	{
    
    
		if(*str == character)
		{
    
    
			return str;
		}
		str++;
	}
	return NULL;
}

(1) First explain the function of this function. Suppose we have a string "sdyzscx", I want to find the character 'y' of this string, then he will traverse this string. If the character 'y' is found, the position of that character will be returned. Otherwise a null pointer is returned.
(2) For this topic, we will find that it is difficult to find its specific running time. Because assuming that the character we are looking for is always the first character in the string, then the execution word count of this function is always 1, and the time complexity is O(1).We call this situation the best case.
(3) But if the character we are looking for always appears in the middle position every time, that is, it only needs to be executed N/2 times.This is called the average case.
(4) The last one is that we maintain an absolutely pessimistic attitude, assuming that the character we are looking for will always be the last character of the string, or cannot be found. Then the number of executions is N, and the time complexity is O(n).This is called worst case.
(5) In practice, we generally pay attention to the worst running situation, so the time complexity of this question is O(n).

Example 6—Number of executions is not intuitive

void BubbleSort(int* a, int n)
{
    
    
	assert(a);
	for (size_t end = n; end > 0; --end)
	{
    
    
		int exchange = 0;
		for (size_t i = 1; i < end; ++i)
		{
    
    
			if (a[i-1] > a[i])
			{
    
    
				Swap(&a[i-1], &a[i]);
				exchange = 1;
			}
		}
		if (exchange == 0)
			break;
	}
}

(1) This is a bubble sorting algorithm, but we will find that it seems that the number of runs of this topic is not easy to calculate. At this time, the best way is to bring in specific values.
(2) Suppose n is 10, and there are 10 elements in the incoming array.
<1> For the first run, the first for statement enters the judgment, and the judgment end of the second for statement is 10. So here it is executed 9 times.
<2> The second run, this time, end is 9. Then the second for statement is executed 8 times.
<3> By analogy, we can know that here is the implementation of 9! (Note that '!' means factorial, if you don't understand, you can read high school textbooks).
<4> If the specific number is converted into variable n, it can be concluded that the actual number of executions of this function is: (n-1)! According to elementary school knowledge, we can know that the number of executions is
( n − 1 + 1 ) ( n − 1 ) ) 2 = n 2 − n 2 \frac{(n-1+1)(n-1))}{ 2}=\frac{n^{2}-n}{2}2(n1+1)(n1))=2n2n
<5> According to the Big O method, the final time complexity is O(n^2)

Example 7 - Time Complexity of Binary Search

/* 作用:二分查找,用于寻找有序数组的值
 * 传入参数 : 
     * a : 有序数组的首元素地址
     * n : 该元素的长度
     * x : 要查找的元素
 * 返回值 : 如果找到了元素,返回该元素在数组的第几项。没有找到元素,返回-1。
*/
int BinarySearch(int* a, int n, int x)
{
    
    
	assert(a);
	int begin = 0;
	int end = n-1;
	while (begin < end)
	{
    
    
		int mid = begin + ((end-begin)>>1);
		if (a[mid] < x)
			begin = mid+1;
		else if (a[mid] > x)
			end = mid;
		else
			return mid;
	}
	return -1;
}

(1) This function is a binary search function for an ordered sequence .
(2) Seeing this function, I still don't have any ideas, so I still set the numbers directly. Suppose there is a sequence [0,1,2,3,4,5,6,7,8,9], because the calculation time complexity is calculated according to the worst condition, so suppose the number we need to find is 0 .
<1> First, pass in this array, begin is 0, and end is 9 (note that end is 9, but it is the last element of the pointed array, because the first element of the array starts from 0). mid = (9-0) >> 1 = 4, so min points to element 4.

insert image description here

<2> We will find that 0 is less than 4, so end=mid=4. mid=0+(4-0)>>1=2.

insert image description here

<2> At this time, we will still find that 0 is less than 2, so end=mid=2. mid=0+(2-0)>>1=1.

insert image description here

<3>0 is still less than 1, so end=mid=1. mid=0+(1-0)>>1=0.

insert image description here

<4> Finally, we will find that a[mid] == 0, and the value is returned.
(3)
<1>According to the above example, we will find that the worst case needs to be run 4 times.
<2> Therefore, we assume that an ordered array has N items. Since we discuss the worst case, 1/2 of the data is excluded every time we search.
<3> For the first search, there are still N/2 items left.
<4> For the second search, there are still N/4 items left.
<5> By analogy, we assume that the worst case is to find X times. Then finally satisfy the condition 2^(X-1)<N<2 ^X, then X is found.
<6> Therefore, the time complexity satisfies the following formula, but rarely, some data structure books are written as the following formula. (Note, it is different from the way of writing mathematics! It is not rigorous but it is often regarded as equal)
O ( log 2 N ) = O ( lg N ) O({log_{2}}^{N}) = O(lg_{N} )O(log2N)=About ( l gN)

Example 8 - Time Complexity of Recursively Calling a Function

long long Factorial(size_t N)
{
    
    
	return N < 2 ? N : Factorial(N-1)*N;
}

(1) It is still impossible to see the result directly, and it is still necessary to set specific values ​​to find ideas. Suppose N is 10. Then his function call relationship is as follows.
(2) We will find that the number of executions is the number of N passed in. So the time complexity is O(N).

insert image description here

Space Complexity Calculation

Example 1—Basic Training

(1) After reading so many examples above, we should have a better understanding of the calculation of time complexity. So how to calculate the space complexity? Take the example below to start the calculation.
(2) The space complexity is also the Big O calculation method. First, let's count how many variables have been established in the following function.
(3) We see that only one variable exchange is created in this function, but this exchange is in the for loop, so is the space complexity of this function O(N)?

void BubbleSort(int* a, int n)
{
    
    
	assert(a);
	for (size_t end = n; end > 0; --end)
	{
    
    
		int exchange = 0;
		for (size_t i = 1; i < end; ++i)
		{
    
    
			if (a[i-1] > a[i])
			{
    
    
				Swap(&a[i-1], &a[i]);
				exchange = 1;
			}
		}
		if (exchange == 0)
			break;
	}
}

(4) The answer is wrong, because in the data structure, time is accumulated, but space is not accumulated . Some people may be confused when they see this sentence. What does that mean?
(5) First of all, we have to know that although the exchange variable is in the for loop, each for loop does not create an exchange variable, but reuses the same space . As shown in the figure below, therefore, the space complexity here is O(1).

insert image description here

Example 2—Space Complexity Calculation for Recursive Calls

long long Factorial(size_t N)
{
    
    
	return N < 2 ? N : Factorial(N-1)*N;
}

(1) Based on the above knowledge, what is the space complexity of this function?
(2) The answer is very simple, O(N). why? Because when calling recursively, every function call will retain the last value.
insert image description here

(3) When Factorial(1) is finally called, the function call ends, the return starts, and the previous variables begin to be destroyed.

insert image description here

Example 3—Space Complexity Calculation of the malloc Function

long long* Fibonacci(size_t n)
{
    
    
	if(n==0)
		return NULL;
	long long * fibArray =(long long *)malloc((n+1) * sizeof(long long));
	fibArray[0] = 0;
	fibArray[1] = 1;
	for (int i = 2; i <= n ; ++i)
	{
    
    
		fibArray[i ] = fibArray[ i - 1] + fibArray [i - 2];
	}
	return fibArray ;
}

(1) This is a Fibonacci sequence, what is the space complexity?
(2)In fact, for this kind of space complexity and time complexity calculation, the most important thing is to see whether this function has anything to do with the incoming parameters. If there is no relationship, then the high probability is O(1). If there is a relationship, you only need to look at the part that is related.
(3) We will find that in this function, only the malloc function is related to the incoming parameter n, so in fact we need to read the sentence of malloc. Because the data requested by malloc is n+1, the space complexity of this function is O(N), and there is no need to look at other places.

Summarize

(1) Both time complexity and space complexity are based on the Big O calculation method. The complexity calculation only needs to look at the part related to the parameters passed in by the function .
(2) Key points of time complexity:
<1> Only need to look at the highest item.
<2> The constant of the highest item can be ignored.
<3> The time complexity generally only looks at the worst case.
(3) Key points of space complexity:
<1> Time is cumulative, but space is not.
<2> In general, we only consider time complexity, not space complexity.
(4) According to the complexity, we can well measure the advantages and disadvantages of an algorithm, and the execution time of different time complexities increases from small to large.

insert image description here

Guess you like

Origin blog.csdn.net/qq_63922192/article/details/131747518