算法学习(1)-------时间复杂度和空间复杂度分析

时间复杂度
算法的好与坏在于它的时间复杂度和空间复杂度。所以一开始就学习了时间复杂度的分析。
大O表示法:
将算法相对的执行时间函数T(n)简化成一个数量级,T(n) = O(f(n)),O为算法的渐进时间复杂度,简称时间复杂度,因为是用大O来进行表示的,所以也称之为大O表示法
推导时间复杂度的步骤:

  1. 如果运行时间是常数量级,用1表示,O(1);
  2. 只保留时间函数中的最高阶的一项,如 f(n) = n^2 + n,,那么时间复杂度为 O(n^2);
  3. 如果最高阶项存在,则省去最高阶项前面的系数,如f(n) = 3n^2;那么时间复杂度为 O(n^2);

时间复杂度的差异:

每个算法的时间复杂度不一样时,差距也是不同的,下面是一个例子:
算法A的执行次数是T(n) = 10n,时间复杂度为O(n);
算法B的执行次数是T(n) = 2n^2, 时间复杂度为O(n^2);
随着输入规模n的增长,我们看看会发生什么事情呢?

T(n) = 10nT(n) = 2n^2
n = 1102
n = 55050
n = 10100200
n = 100100020000
n = 1000100002000000
n = 10000100000200000000
n = 100000100000020000000000
n = 100000010000000200000000000
n = 1000000010000000020000000000000
n = 100000000100000000020000000000000

可以看出数据规模到一定程度时,O(n^2) 的 时间是远远多于 O(n)的,故在写代码时考虑时间复杂度是非常有必要的。

举例分析时间复杂度:
1.O(n)

public void fly( int n)
{
	for(int i = 0; i < n; i++)
	{
		System.out.println("我飞了" + i + "米");
		System.out.println("你飞了" + i + "米");
	}
}

以上这段代码的时间复杂度为O(n),因为其中 System.out.println(“我飞了” + i + “米”);执行n次,所以花费的时间为n,两句就是 n + n 为2n,省略系数2,得到时间复杂度为O(n)。
2.O(n^2)

public void fly( int n)
{
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < i; j++)
		{
				System.out.println("我飞了" + i  * j+ "米");
		}
	}
}

这段代码的时间复杂度为O(n^2),首先是第一层循环里的循环执行了n次,每执行一次,System.out.println()这一句就会执行i×i次,那么最后这句话就执行了 n ×n次,即n^2次,故时间复杂度为O(n^2)。

3.O(logn)

i=1;
while (i <= n) {
i = i * 2;
}

这个代码的时间复杂度是O(logn)。代码每循环一次就i乘以2,变量i的取值就是⼀个等⽐数列。如果我把它⼀个⼀个列出来,就应该是这个样⼦的:
2^0 2^1, 2^2, 23…2x = n,通过计算x = log2n,的时间复杂度为O(logn);
时间复杂度分为最好时间复杂度,最坏时间复杂度和平均时间复杂度。
最好时间复杂度:
在最理想的情况下,执⾏这段代码的时间复杂度
最坏时间复杂度:
在最糟糕的情况下,执⾏这段代码的时间复杂度
平均时间复杂度又是期望时间复杂度。

空间复杂度:
在时间复杂度分析后,影响算法运行效率的还有一个重要的因素,算法所占内存的多少。
内存空间是有限的,在时间复杂度相同的情况下,算法占用的内存空间自然是越小越好。
空间复杂度同样也使用大O表示法来表示。
下面有常见的空间复杂度:
1、常量空间
当算法的存储空间大小固定,和输入规模没有直接关系时,复杂度记作O(1)
如:

void fun1(int n){
	int var = 4;
}

2、线性空间
当算法分配的空间是一个线性的集合(如数组),并且集合的大小和输入规模成正比时,空间复杂度记作O(n).
如:

void fun2(int n){
int[] array = new int[n];
}

3.二维空间
当算法分配的是一个空间二维数组集合,并且长度和宽度都与输入规模成正比时,空间复杂度记作O(n^2)。
如:

void fun3(int n)
{
	int[][] array = new int[n][n]; 
}

4、递归空间
在递归代码执行的时候,会专门分配一块内存,用来存储方法调用栈,方法调用栈包括出栈和进栈两个行为。

下面这个程序是一个递归程序:

void fun4(int n){
	if(n<=1){
		return;
	}
	System.out.println(n);
	fun4(n-1);
}

执行递归操作所需要
的内存空间和递归的深度成正比。纯粹的递归操作的空间复杂度也是线
性的,如果递归的深度是n,那么空间复杂度就是O(n)。

在绝大多数时候,时间复杂度比较重要,宁可多分配一点内存,也要提升程序的执行速度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值