[系列文章]数据结构与算法之打怪升级(一)

最近正在极客时间app上学习数据结构和算法,把学完每节后的笔记、成果和想法记录下来。

算法的时间和空间复杂度分析

什么是数据结构?就是一组数据的存储结构。什么是算法?就是对数据操作的一组方法。所以,算法和数据结构是绑定在一起,相辅相成,不可割的。因为,数据是为算法服务的,而算法是作用在数据上的。比如,算法的二分查找,就要对应用数组,因为数组可以随机访问,而用链表就无法实现二分查找算法了。
如何估计一个算法的执行效率呢?效率可以通过两方面来分析:时间复杂度和空间复杂度,时间复杂度是算法执行完所花费的cpu时间,空间复杂度是算法执行过程中消耗的资源(内存)。时间或空间复杂度越高,说明算法的效率越低,算法追求的是更快、更省。
算法复杂度代表的是算法执行效率随数据规模增长的变化趋势,它不是算法实际在环境中运行的真实时间,它是分析和评判一个算法效率的预测办法。要获取算法的真实执行时间,需要用事后统计的办法,就是找个机器运行,然后统计时间。

常见的算法时间复杂度

复杂度用大O表示,通常的复杂度有以下这些:常量阶O(1)、对数阶O(logn)、线性阶O(n)、线性对数阶O(nlogn)、平方阶O(n2)或立方阶O(n3)…或k次方阶O(nk)、指数阶O(2n)、阶乘阶O(n!)
其中指数阶和阶乘阶的复杂度属于非多项式量级,以上其他都是多项式量级。当数据规模n越来越大时,非多项式量级算法的执行时间会急剧增加,求解问题的执行时间会无限增长。所以,非多项式时间复杂度的算法其实是非常低效的算法。

算法的时间复杂度分析例子

举几个例子来加强复杂度分析的方法:
1、加法法则:总复杂度等于量级最大的那段代码的复杂度

function f () {
		for(i = 0; i<= 10000; i++) {
			u += i;
		}
		for(k = 0; k<= n; k++) {
			s += s * k;
		}
	}

这里有两个循环,第一个执行了20000次,时间复杂度是O(20000),第二个执行了2n,时间复杂度是O(2n),这个函数的实际复杂度是O(20000) + O(2n) = O(2n + 20000)。因为,20000是一个常量,算法时间复杂度不会变化,不用考虑,所以这个函数的时间复杂度是O(n),n前面的系数可以忽略。

2、乘法法则:嵌套代码的复杂度等于嵌套内外复杂度的乘积

	function f () {
		for(k = 0; k<= n; k++) {
			s += s * k;
		}
	}
	function cf() {
		for (i = 0; i < n; i++) 
			f();
	}

分析下cf()的时间复杂度,函数cf()调用了f(),两个函数都有一个循环,所以,cf()的时间复杂度就是O(n*n) = O(n2)。

算法的空间复杂度分析例子

在来一个空间复杂度分析的例子:

function f(int n) {
	int * pi = new int[n];
	for(i = 0; i < n; i++) {
		pi[i] = i*i;
	}
}

空间复杂度分析,相对来说是比较简单些的,这个例子中的算法空间复杂度是分配了n个整型空间的内存,所以复杂度就是O(n)。

复杂度分析有什么作用

既然可以通过执行算法来分析、统计执行时间和查看资源消耗的情况,作复杂度分析有必要吗?复杂度分析的益处:
1、可以不用运行算法,就可以估算对比算法之间的优劣
2、可以作为评估算法优化的参考

你可能感兴趣的:(技术)