数据结构与算法学习笔记一: 时间复杂度空间复杂度

  这篇主要讲解时间复杂度、空间复杂度概念。

复杂度分析

  数据结构和算法解决的是“快”和“省”的问题。即如何让代码运行的更快,如何让代码更省存储空间。因此代码的执行效率是一个非常重要的考量指标,那如何来衡量代码的执行效率呢?我们可以用时间复杂度、空间复杂度来对代码的执行效率、性能进行评估,也就是算法的复杂度分析。

算法的复杂度分析主要包含两个方面:
  时间复杂度分析
  空间复杂度分析

为什么要进行复杂度分析?
1.和性能测试相比,复杂度分析不依赖执行环境、成本低、效率高、易操作、指导性强的特点。
2.掌握复杂度分析,将能编写出性能更优的代码,有利于降低系统开发和维护成本。

时间复杂度表示法

  算法的执行效率,就是算法代码执行的时间,下面演示在不直接运行代码的前提下粗略的计算执行时间。

int sum(int n){
	int sum = 0; // 执行一遍
	for(int i = 1; i <=n; ++i){   // 执行n遍
		sum = sum + i; // 执行n遍
	}
	
	return sum;
}

假设每行代码执行时间都一样为: timer, 此代码的执行时间为:(2n+1)*timer。

int sum(int n){
	int sum = 0; //执行一遍
	for(int i = 1; i <= n; ++i){  //执行n遍
		for(int j = 1; j <= n; ++j) {  //执行n*n遍
			sum = sum + i * j;//执行n*n遍
		}
	}
}

同理: 此代码的执行时间为:(2n*n + n + 1) * timer

因此: 代码的执行时间T(n)与每行代码的执行次数n 成正比,可以把这本规律总结成一个公式。

T(n) = O(f(n))

解释一下:
  T(n) 表示代码的执行时间,n表示数据规模的大小,f(n)表示了代码执行次数的总和,它是一个公式因此用f(n)表示,O表示了代码执行时间与f(n)成正比。
因此第一个例子中的T(n) = O(2n + 1),第二个例子中的T(n) = O(2n*n + n + 1),这就是大O时间复杂度表示法
大O时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫渐进时间复杂度,简称时间复杂度。

当n很大时,公式中的低阶,常量,系数三部分并不左右其增长趋势,因此可以忽略,我们只需要记录一个最大的量级就可以了,因此如果用大O表示刚刚的时间复杂度
可以记录为: T(n) = O(n), T(n) = O(n*n)

时间复杂度分析方法:

  1. 代码循环次数最多原则:
    分析一个算法或者一个代码的世界复杂度时,只需关注循环执行次数最多的那一段代码即可。
  2. 加法原则:
    代码中有两段代码,复杂度分别为O(n) 和O(nn) 其结果本应该是: T(n) = O(n) + O(nn);我们取其中最大的量级,因此整段代码的复杂度为O(n*n).
    也就是说:总的时间复杂度就等于量级最大的那段代码的世界复杂度。
  3. 乘法原则:
    嵌套代码的复杂度等于嵌套内外代码复杂度的乘积,

常见的时间复杂度

1. O(1)
O(1)并不是指代码只有一行,它是一种常量级复杂度的表示方法,比如说有一段代码如下:

  public void test01(){
     int i = 0;
	 int j = 1;
	 return i + j;
  }

代码只有三行,它的复杂度也是O(1),而不是O(3)

再看如下代码:

  public void test02(){
	int i = 0;
	int sum = 0;
	for(; i < 100; i++){
		sum = sum + i;
	}
    System.out.printLn(sum);
  }

整个代码中因为循环次数是固定的就是100次,这样的代码复杂度我们认为也是O(1)

2. O(n)

  public void test03(int n){
	int i = 0;
	int sum = 0;
	for(; i < n; i++){
		sum = sum + i;
	}
    System.out.printLn(sum);
  }

3. O(logn), O(nlogn)
对数阶的复杂度非常的常见,但同时也是很难分析的一种复杂度。

//复杂度为: O(logn)
public void test04(int n){
	int i = 1;
	while(i <= n){
		i = i * 2;
	}
}

//复杂度为: O(nlogn)
public void test06(int n){
	int i = 0;
	for(; i <= n; i++) {
	 test04(n);
	}
}

空间复杂度

  时间复杂度的全称是渐进时间复杂度,表示算法的执行时间与数据规模之间的增长关系,类似的,空间复杂度全称是渐进空间复杂度,表示算法占用的存储空间与数据规模之间的增长关系。

用一段代码说明:

 void print(int n){
	int i = 0;
	int[] a = new int[n];
	for(i; i < n; ++i){
		a[i] = i * i;
	}
	
	for(i = n -1; i >= 0; --i){
	    System.out.println(a[i]);
	} 
 }

代码第二行,申请一个空间存储变量i,但是是常量阶的,跟数据规模n没有关系,第三行申请了一个大小为n的int数组,
此外后面的代码几乎没有占用更多的空间,因此整段代码的空间复杂度就是O(n)。

我们常见的空间复杂度就是O(1),O(n), O(n*n),其他对数阶的复杂度几乎用不到,因此空间复杂度比时间复杂度分析要简单的多,因此掌握这些足够。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值