数据结构与算法(复杂度分析之时间复杂度)

大O复杂度用于描述代码执行时间随数据规模增长的趋势,忽略了常量、低阶项和系数,只保留最高阶项。分析方法包括关注循环次数最多的代码段、加法法则(多个独立操作的时间复杂度相加)和乘法法则(嵌套循环的时间复杂度相乘)。常见的时间复杂度阶有O(1)到O(n!)等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大O复杂度表示法

求1,2,3,…,n的累加和。

int cal(int n) {
	int sum = 0;
	int i = 1;
	for (; i <= n; ++i){
		sum = sum + i;
	}
	return sum;
}

假设每行代码执行时间都是一样,为unit_time。在这个假设基础上,这段代码的总执行时间是多少?
第2、3行代码执行时间分别需要1个unit_time的执行时间,第4、5行代码都运行了n遍,所以需要2n * unit_time的执行时间,所以这段代码的执行时间就是(2n+2) * unit_time。k可以看出来,所有代码的执行时间T(n)与每行代码的执行次数成正比。

分析下面的代码:

int cal(int n){
	int sum = 0;
	int i = 1;
	int j = 1;
	for (; i <= n; ++i){
		j = 1;
		for (; j <= n; ++j){
			sum = sum + i +j;
		}
	}
}

第2、3、4行都需要一个unit_time的时间。第5、6行代码循环执行了n遍,需要2n * unit_time的执行时间,第7、8行代码循环执行了n的次方遍,所以需要2n² * unit_time的执行时间。因此,整段代码的总的执行时间T(n) = (2n²+2n+3) * unit_time。
综上可知所有代码的执行时间T(n)与每行代码的执行次数n成正比。
我们可以把这个规律总结成一个公式。

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

其中T(n)表示代码执行的时间。n表示数据规模的大小。f(n)表示每行代码执行的次数总和。
因为这是一个公式,所以用f(n)表示。公式中的O,表示代码的执行时间T(n)与f(n)表达式成正比。

总结:第一个例子中T(n) = O(2n+2);第二个例子中T(n) = O(2n²+2n+3)。

这就是大O时间复杂度表示法。大O时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势。因此,也叫渐进时间复杂度。

由于大O表示法只是一个变化趋势,因此可以忽略公式中的常量、低阶、系数,只需要记录最大阶的量级就可以了。

时间复杂度分析的方法:

1、只关注循环次数最多的一段代码。
如下面的一段代码,这段代码只需要看执行次数最多的一行代码,其中核心代码执行次数的n的量级,就是整段要分析代码的时间复杂度。

int cal(int n){
	int sum = 0;
	int i = 1;
	for(; i <= n; ++i){
		sum = sum + i;
	}
	return sum;
}

第2、3行代码都是常量级的执行时间,与n无关,直接忽略。第4、5行代码循环次数最多,与n相关,重点分析,。这两行代码被执行了n次,所以总的时间复杂度就是O(n)。

2、加法法则。

int cal (int n) {
	int sum_1 = 0;
	int p = 1;
	for (; p < 100; ++p) {
		sum_1 = sum_1 + p;
	}
	int sum_2 = 0;
	int q = 1;
	for (; q < n; ++q){
		sum_2 = sum_2 + q;
	}
	int sum_3 = 0;
	int i = 1;
	int j = 1;
	for (; i <= n; ++i){
		j = 1;
		for(; j <= n; ++j){
			sum_3 = sum_3 + i * j;
		}
	}
	return sum_1 + sum_2 + sum_3;
}

分析上面代码,可以看出第一个for循环是100次,为常量级,直接忽略。第二个for循环为O(n)。第三个嵌套for循环为O(n²)。综合一下我们取最大量级的复杂度。因此时间复杂度为O(n²)。

3、乘法法则。
乘法法则就是嵌套循环的时候,把嵌套内外代码复杂度的乘积。
如下代码

int cal (int n) {
	int ret = 0;
	int i = 1;
	for (; i < n; ++i) {
		ret = ret + f(i);
	}
}
int f(int n) {
	int sum = 0;
	int i = 1;
	for (; i < n; ++i) {
		sum = sum + i;
	}
	return sum;
}

我们单独看cal()函数,假设f()只是一个普通的操作,那第4~6行的时间复杂度就是T1(n) = O(n)。但f()函数本身不是一个简单的操作,它的时间复杂度是T2(n) = O(n),所以,整个cal()函数的时间复杂度就是,T(n) = T1(n) * T2(n) = O(n * n) = O(n²)。

总结:复杂度量级

常量阶:O(1)
对数阶:O(log n)
线性阶:O(n)
线性对数阶:O(n log n)
平方阶:O(n²)
立方阶:O(n^3)
k次方阶:O(n^k)
指数阶级:O(2^n)
阶乘阶:O(n!)

其中对数阶和线性阶对数阶最常见也是最难分析的一种

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值