时间复杂度详解

目录

一.  时间复杂度概念

例题1:

二.  推导大O阶

三.  几种常见的时间复杂度:

 

3.1常数阶:

3.2线性阶:

 例题2:

3.3对数阶

3.4 平方阶:

​编辑

例题3:​编辑

解题思路:

变式1:

3.5 总结

 四、空间复杂度

4.1 空间复杂度O(1)

4.2空间复杂度O(n)

例题4:数字排序 奇数在前偶数在后

注意:

运算符优先级问题


一.  时间复杂度概念

 

 这样用大写O(来体现算法时间复杂度的记法,我们称之为大О记法。一般情况下,随着n的增大,T(n)增长最慢的算法为最优算法。

显然,由此算法时间复杂度的定义可知,我们的三个求和算法的时间复杂度分别为o(n),o(1),0(n2)。我们分别给它们取了非官方的名称,O(1)叫常数阶、O(n)叫线性阶、O(n2)叫平方阶,当然,还有其他的一些阶.

时间复杂度:0(1)序列被执行的次数,次数一定跟问题规模相关

例题1:

 我们先看执行了多少条语句,分析如下:

当找到2时一共执行了六条语句 复杂度为O(1).

二.  推导大O阶

三.  几种常见的时间复杂度:

 

3.1常数阶:

首先顺序结构的时间复杂度。下面这个算法,也就是刚才的第二种算法(高斯算法),为什么时间复杂度不是O(3),而是O(1)。

这个算法的运行次数函数是f (n) =3。根据我们推导大О阶的方法,第一步就是把常数项3改为1。在保留最高阶项时发现,它根本没有最高阶项,所以这个算法的复杂度为O(1).

事实上无论n为多少,上面的两段代码就是3次和12次执行的差异。这种与问题的大小无关(n的多少),执行时间恒定的算法,我们称之为具有0(1)的时间复杂度,又叫常数阶。

注意:不管这个常数是多少,我们都记作0(1),而不能是o(3)、0(12)等其他任何数字.

3.2线性阶:

线性阶的循环结构会复杂很多。要确定某个算法的阶次,我们常常需要确定某个特定语句或某个语句集运行的次数。因此,我们要分析算法的复杂度,关键就是要分析循环结构的运行情况。

下面这段代码,它的循环的时间复杂度为0[n),因为循环体中的代码须要执行n次。

 

 例题2:

首先一定是与n有关系的,10个数据循环五次,20个数据循环十次

所以时间复杂度为 O(n/2),但是由于推导大n阶 我们只保留最高阶项所以依旧为O(n)

3.3对数阶

 

由于每次count乘以2之后,就距离n更近了一分。也就是说,有多少个2相乘后大于 n,则会退出循环。由2x=n得到x=bgan。所以这个循环的时间复杂度为0(logn)。

3.4 平方阶:

例题3:

解题思路:

变式1:

解题思路

轮转了一个等差数列:首项 n-1 末项 1 等差数列的和 n的平方

时间复杂度O(n^2)

3.5 总结

常用的时间复杂度耗费时间排序:

O(n^2)>O(n)>O(logn)>O(1)     

 四、空间复杂度

    空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势, 空间复杂度比较常用的有:O(1)、O(n)、O(n^2)

4.1 空间复杂度O(1)

如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为O(1)

int i=1;
int j=2;
i++;
j++;
int m=i+j;

代码中的i、j、m所分配的空间都不随着处理数据量变化,因此它的空间复杂度为O(1)

4.2空间复杂度O(n)

int [] m=new int[n]
for(i=1;i<=n;i++)
{
i=j;
j++;
}

新new了一个数组出来,这个数组占用大小为n,因此,这段代码的空间复杂度为O(n)

例题4:数字排序 奇数在前偶数在后

void Ajust(int* arr, int len) {
	
		int i = 0, j = len - 1;
		while (i < j) {
			//1. 从左-> 右元素查找,找到偶数值的位置停止
			//奇数 继续向下查找
			while (i<j && (arr[i] & 0x1) != 0) {   //优化  arr[i]%2 != 0
				i++;
			}
			//i 标记就是偶数值下标
			//2. 从右 -> 左 元素查找  找奇数值所在位置停止
			while (i<j && (arr[j] & 0x1) == 0) {
				j--;
			}
			//j 标记奇数值的位置
			if (i < j) {
				int temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
	}
	
int main() {
	int arr[] = { 1,2,3,4,5,6,7,9 };  //1,3,5
	int len = sizeof(arr) / sizeof(arr[0]);
	Ajust(arr, len);

	for (int i = 0; i < len; i++) {
		printf("%-5d", arr[i]);
	}
	return 0;
}

注意:

运算符优先级问题

i<j && (arr[i] & 0x1) != 0 需要留意 按位与 和 逻辑与 还有 等号 的优先级问题

附上优先级表:

 

 

解决方法:

所以在运算时要加上小括号 保证先进行按位与运算 而不是 == 运算

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值