算法效率的度量

时间复杂度

时间开销与问题规模n之间的关系称为时间复杂度

1、如何评估算法时间开销

让算法先运行,事后统计运行时间

事后统计存在的问题
注:以下是与算法本身无关的外界因素,无法排除
一:和机器性能有关,如:超级计算机 v.s. 单片机
二:和编程语言有关,越高级的语言执行效率越低
三:和编译程序产生的机器指令质量有关
无法事先估计
有些算法是不能事后再统计的,例如:导弹控制算法

算法时间复杂度:应采用事前预估算法时间开销T(n) 与问题规模n的关系(T表示time)

2、算法一:单循环型

public void printHelloWorld (int n) {
	1int i = 1;
	2while (i < n) {
	3:	i++;
	4:	System.out.println("Hello World");
	}
	5:System.out.println("Hello World more then" + n);
}

语句频度为(设n为3000)
第一行-------1次
第二行-------3001次
第三与第四行-------3000次
第五行-------1次
T(3000) = 1 + 3001 + 2 * 3000 + 1
则时间开销与问题规模n的关系为T(n) = 3n + 3

时间复杂度的全称为渐进时间复杂度(渐进是因为n是要趋向于无穷大的时候才能统计出时间复杂度)

对以上算法现象,思考提出两个问题
问题一:是否可以忽略表达式某些部分?
答:可以只考虑阶数,并使用大O记法表示
问题二:如果有好几千行代码怎么办,要按这种方法一行行计算?
答:只需要考虑最深层循环次数与n的关系

举例:

T(n)n = 3000n = 1,000,000
3n + 39003
3n9000
9999n29,997,0009,999,000,000
n² + 3n + 10009,010,000
9,000,0001,000,000,000,000
n³ + n² + 9,999,99927,018,999,999
27,000,000,000

结论一:可以只考虑阶数高的部分
结论二:问题规模足够大时,常数项系数也可以忽略

a)加法规则:多项相加,只保留最高阶的项,且系数变为1
T(n) = T1(n) + T2(n) = O(f(n)) + O(g(n)) = O(max(f(n),g(n)))
b)乘法规则
T(n) = T1(n) * T2(n) = O(f(n)) * O(g(n)) = O(f(n)*g(n))

3、时间复杂度排序

O(1) < O(㏒2 n) < O(n) < O(n㏒2 n) < O(n²) < O(n³) < O(2 ^ n) < O(n!) < O(n ^ n)
算法时间复杂度排序来源
O(n)与O(㏒2 n)
O(n²)与O(2 ^ n)
在这里插入图片描述
T(3000) = 1 + 3001 + 2 * 3000 + 1时间开销与问题规模n的关系为T(n) = 3n + 3,则T(n) = 3n + 3 = O(n)

结论一:顺序执行的代码只会影响常数项,可以忽略
结论二:只需挑循环中的一个基本操作分析它的执行次数与n的关系即可计算时间复杂度

4、算法二:嵌套循环型

public void printHelloWorld (int n) {
	int i = 1;
	while (i < n) {
		i++;
		System.out.println("Hello World");
		for(int j = 1; j < n; j++) {
			System.out.println("Hello World1");
		}
	}
	System.out.println("Hello World more then" + n);
}

时间复杂度:T(n) = O(n) + O(n²) = O(n²)

5、算法三:指数递增型

public void printHelloWorld (int n) {
	int i = 1;
	while (i < n) {
		i = i * 2;
		System.out.println("Hello World");
	}
	System.out.println("Hello World more then" + n);
}

时间复杂度:
设最深层循环的语句频度(总共循环的次数)为x,则由循环条件可知,循环结束时刚好满足
2 ^ x > n
x = ㏒2 n + 1
T(n) = O(x) = O(㏒2 n)

6、算法四:搜索数字型

设arr数组中乱序存放了1~n即int[] arr = {1,2,…,n-1,n}

public void searchElement (int[] arr,int n) {
	for(int i = 0; i < n; i++) {
		if(arr[i] == n) {
			System.out.println("Hello World" + i);
			break;
		}
	}
}

计算搜索算法时间复杂度

算法时间复杂度情况描述时间复杂度
最好情况最好情况下的算法的时间复杂度,此时为:元素n在第一个位置T(n) = O(1)
最坏情况最坏情况下的算法的时间复杂度,此时为:元素n在最后一个位置T(n) = O(n)
平均情况所有输入示例等概率出现的情况下,算法的期望运行时间,此时为:假设元素n在任何一个位置的概率相同为1/nT(n) = O(n)

平均情况:循环次数x = (1 + 2 + 3 +…+ n) * 1 / n = (1 + n) / 2

7、常见排序算法时间复杂度

在这里插入图片描述
注:稳定性的判断是由排序中的两个相等的数,在排序完成前的前后顺序与排序完成后的前后顺序是否改变,如果改变即为不稳定,不改变即为稳定

空间复杂度

空间开销(内存开销)与问题规模n之间的关系称为空间复杂度

1、原地工作—算法所需内存空间为常量

无论问题规模如何变化,算法运行所需的内存空间都是固定的常量,算法的空间复杂度为S(n) = O(1)
注:S表示Space

2、算法一

public void test (int n) {
	int arr[n];
	int i;
	// 省略代码。。。
}

一个int变量占4字节
则所需内存空间为= 4 + 4n + 4 = 4n + 8
即S(n) = O(n)

3、算法二

public void test (int n) {
	int arr[n][n];
	int i;
	// 省略代码。。。
}

即S(n) = O(n²)

4、算法三

public void test (int n) {
	int arr[n][n];
	int other[n];
	int i;
	// 省略代码。。。
}

即S(n) = O(n²) + O(n) + O(1) = O(n²)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值