关于时间复杂度和空间复杂度的问题,常见时间复杂度

一. 如何衡量一个算法的好坏?

1.这个算法必须是可以实现的并执行无误的
2.这个算法是友好的,不装逼的,是让人能看懂的
3.这个算法时间复杂度和空间复杂度是可观的.(越小越好)

二. 什么是时间复杂度?

在计算机科学中,算法的时间复杂度是一个函数,它定量的描述了该算法的运行时间.
通俗的讲,一个算法所花费的时间与其中语句的执行次数成正比,算法中的基本操作的执行次数,为算法的时间复杂度

三. 时间复杂度为什么不使用时间来衡量而使用基本语句的运行次数来衡量?

算法程序执行的具体时间受到所使用的计算机,程序设计语言以及算法实现过程中的许多细节的影响
这个在运行的过程中是无法估量的,而且每次运行的时间是稍微有差别的,所以我们没办法这样来统计
所以用使用基本语句的运行次数来衡量时间复杂度.

四.时间复杂度的O渐进表示法

定义:如果一个问题的规模是n,解这一问题的某一算法所需要的时间为T(n),它是n的某一函数 T(n)称为这一算法的“时间复杂性”。
当输入量n逐渐加大时,时间复杂性的极限情形称为算法的“渐近时间复杂性”。
大o表示法:表示程序的执行时间或占用空间随数据规模的增长趋势,它是一种趋势
在时间复杂度的计算中,他将代码所有步骤转换为关于数据规模n的全项式

比如下面这段程序:

void Fun1(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<N;k++) {
			count++;
		}
		int M = 10;
		while(M--) {
			++count;
		}
		pritnf("%d",count);
	}

Fun1 执行的基本次数为 : F(N) = N^2+2*N+10

随着问题规模N的不同我们得出的基本次数也不相同
实际中我们计算复杂度时候,我们只使用大o渐进表示法表示出程序的趋势就行
大o符号 :是用于描述函数渐进行为的数学符号

T(n) = o(f(n))

在这里插入图片描述

推导大O阶方法:

1.用常数1取代运行时间中的所有加法常数
2.在修改后的运行次数函数中,只保留最高阶项
3.如果最高阶项存在且不是1,则去除与这个项目相乘的常数,得到的结果就是大O阶

那么上面函数中时间复杂度为 O(N^2)

五. 时间复杂度的:最优、平均、最差情况,为什么时间复杂度看的是最差情况?

我们以一个长度为N的数组举例,我们需要找到一个数据X,这个数组对我们来说是未知的
我们用遍历方法来搜寻这个数据是否存在

那么结果是
最好的情况:1次找到
最坏的结果:N次找到了
平均情况: N/2次找到

首先我们必须有一个保障,也就是需要一个程序的最坏保障,在这个保障下,我们的程序是可以实现的,那么复杂度就要采用O(N)
当然我们也不能排除这个数字并没有在我们的数组中搜索了N次也没有找到
那么这个时候我们就需要综合考虑了,不排除这个数字没在数组中,所以我们就要采用最坏的情况来考虑了O(N)
另外一个方面,我们需要考虑内存的消耗,在最坏的情况我们的计算机都可以接受,那么最好的和平均的情况
也就不是问题了

我们考虑最好情况是没有意义的,因为一旦数据改变了,那就没有意义了

平均运行时间是所有情况中最有意义的,因为它是期望的运行时间。也就是说,我们运行一段程序代码时,
是希望看到平均运行时间的。可现实中,平均运行时间很难通过分析得到,一般都是通过运行一定数量的实验数据后估算出来的。

所以一段程序我们是需要这些方面来综合衡量的,衡量下来我们就要采用最坏情况来定义时间复杂度

六.什么是空间复杂度?

空间复杂度是对一个算法运行过程中临时占用存储空间大小的度量,空间复杂度不是程序占用了多少bytes 空间,是没有意义的
所以空间复杂度算的是变量的个数
也使用大O渐进表示法

七.如何求空间复杂度? 普通函数&递归函数

普通函数:冒泡排序

	void SeqListBulesort(int* Psl,size_t size) {
		int exchage = 0;
		size_t i;
		size_t j;
		for(i = 0;i<size-1;i++) {
			exchage = 0;
			for(j = 0;j<size-j;j++) {
				if(arr[j]>arr[j+1]) {
					Swap(&arr[j],&arr[j+1]);
					exchage = 1;
				}
			}
			if(exchage == 0) {
				break;
			}
		}
	}  

在进行排序时候只使用了常数个额外的空间,所以复杂度为O(1)

	long long * Fib(size_t N) {
		if(N == 0) {
			return  NULL;
		}
		long long *fibArray = new long 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个空间,空间复杂度为O(N)

		long long  Fac(size_t N) {
			if(N == 1) {
				return 1;
			}
			else return Fac(N-1)*N;
	}

在上面函数中递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间,空间复杂度为O (N);

八. 总结常见时间复杂度

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44077227/article/details/89488394