【时间复杂度常见的计算】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

对于判断一段代码的好坏,取决于该代码运行的时间与占用的空间,也就是时间复杂度与空间复杂度,本章就先讲一下时间复杂度,主要包含常见的时间复杂度的计算。

一、时间复杂度是什么?

时间复杂度是衡量算法运行效率的一个重要指标,它表示随着输入规模的增长,算法执行时间的增长趋势。以下是关于时间复杂度的计算方法与常见的时间复杂度:

二、时间复杂度的计算

1.基本步骤


  • (1) 确定算法中的基本操作,通常是一些最主要的运算或操作步骤。
  • (2) 计算基础操作执行的次数,并将其表示为输入规模 n 的函数T(n).
  • (3) 忽略T(n)中的低阶项和常数因子,只保留最高项。例如,对于函数T(n)=3nn+5n+2,忽略5n和2,只关注3nn。
  • (4) 用大O记号来表示时间复杂度,如O(n*n)。

2.常见的时间复杂度


1.常数阶O(1)
无论输入规模如何变化,算法执行的时间都是一个常数。例如,直接访问数组中的一个元素,时间复杂度为
O(1)。
总的来说:代码中只是进行了简单的加法运算,不随输入规模变化,执行时间恒定。
注意:简单说一下哈希表也是O(1)。

int add(int x,int y)
{
return a+b;
}

2.对数阶 O(log n):
算法的执行时间与输入规模的对数成正比。常见于二分查找等算法,每次操作都能将问题规模缩小一半。
例如 二分查找

int towfen(int x,int low,int high)
{
	while(low<high)
	{
		int m=low+(high-low)/2;
		if(a[m]==x)return 1;
		else if(a[m]>x)
		{
			high=m;
		}
		else
		{
			low=m+1;
		}
	}
	return 0;
}

其主要思想就是折半查找,假设有个数组{1,2,3,4,5,6,7,8,9}
要查找的元素为3,则此时的m=5,而3小于当下标为5时的数,以此只需要查找一半,每次都减少一半,直到最后找到。

3.线性阶 O(n)
算法的执行时间与输入规模 n 成正比。如上述示例中对列表元素进行求和的操作,时间复杂度为 O(n)。
简单举例

int sum(int n)
{
	int s=0;
	for(int i=1;i<=n;i++)
	s+=i;//一共循环了n次
	return s;
	}

4.线性对数阶 O(nlog n)
通常出现在一些分治算法中,如归并排序、快速排序等。这类算法将问题分成多个子问题,每个子问题的规模是原问题的一部分,然后对这些子问题分别进行处理。
就以快排的例子来说:

void quike_sort(int low,int high)
{
	if(low>=high)
	return ;
	int mid=rand()%(high-low)+low;//随机取个中间数
	int l=low,i;
	int x1=0,x2=0,x3=0;
	for(i=low;i<high;i++)
	{
		if(a[i]>a[mid])//大于所取的数存入b数组
		{
			b[x1++]=a[i];
		}
		else if(a[i]==a[mid])//把等于所取的数放入c数组
		{
			c[x2++]=a[i];
		}
		else//把小于所取的数放入d数组
		{
			d[x3++]=a[i];
		}
	}
	for(i=0;i<x3;i++)
	{
		a[l++]=d[i];
	}
	for(i=0;i<x2;i++)
	{
		a[l++]=c[i];
	}
	for(i=0;i<x1;i++)
	{
		a[l++]=b[i];
	}//对其进行合并
	quike_sort(low,low+x3);//再次进入递归将左边的数组排好顺序
	quike_sort(low+x3+x2,high);//同理排序右边数组
}

5.平方阶 O(n^2):
常见于一些嵌套循环的算法中。例如,冒泡排序、选择排序等,它们需要对数据进行多次遍历和比较,时间复杂度为 O(n^2)。
代码如下

void qsort(ll n)
{
	ll m[n];
	for(int i=0;i<n;i++)
	cin>>m[i];
	for(int i=0;i<n;i++)
	for(int j=i+1;j<n;j++)
	{
	if(m[i]>m[j])
	{
	int t=m[i];
	m[i]=m[j];
	m[j]=t;
	}
	}
}

6.立方阶 O(n^3)
一般出现在三层嵌套循环的算法中。例如,计算两个 n*n 矩阵的乘法,时间复杂度为 O(n^3)。

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
cout<<"1"<<endl;

7.指数阶 O(2^n)
当算法的时间复杂度为指数阶时,随着输入规模 n 的增加,算法的执行时间会呈指数级增长。例如,计算斐波那契数列的递归算法,时间复杂度为 O(2^n),这种算法在实际应用中效率较低,只适用于小规模问题。

#include <iostream>

// 递归函数计算斐波那契数列的第 n 项
int fibonacci(int n) {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}

该递归算法的时间复杂度是 (O(2^n)),因为在每一步递归中,问题会被分解成两个子问题,并且没有对重复子问题进行优化,所以时间复杂度会呈指数级增长。

总结

总而言之,该篇文章就是简单的介绍了一下时间复杂度,仅仅是自己的粗鄙的看法,本人也是第一次接触这些东西,就想着发一篇文章来加深一下自己的理解,新人小白一枚,大佬勿喷,有理解错的地方希望能给小弟提点一下

### 常见时间复杂度计算方法 #### O(1)常数级时间复杂度 当执行的操作数量不随输入规模变化而改变时,则认为该操作具有O(1)的时间复杂度。例如访问数组中的特定元素,无论数组大小如何,只需要一次寻址即可完成。 ```python def get_element(array, index): return array[index] # 单次访问操作 ``` #### O(n)线性时间复杂度 如果一段代码中存在单层循环结构,并且每次迭代都处理一个新数据项,在这种情况下通常会得到O(n)的时间复杂度,其中n表示输入的数据量大小[^1]。 ```python for i in range(len(data)): process_item(data[i]) # 对每一个元素做相同的工作 ``` #### O(log n)对数级别时间复杂度 二分查找是一个典型的例子,它通过不断缩小搜索范围来定位目标值的位置。每经过一轮比较就能排除掉一半的可能性,所以整个过程大约只需log₂N轮就可以结束。 ```python low, high = 0, len(list)-1 while low <= high: mid = (low + high) // 2 guess = list[mid] if guess == item: return mid elif guess > item: high = mid - 1 else: low = mid + 1 return None ``` #### O(n log n)线性对数时间复杂度 快速排序就是这样一个典型代表,其基本思路是选取一个基准值将待排序序列划分为两部分——小于等于基准的部分放在左边;大于基准的部分置于右边。接着再分别对这两边重复上述划分动作直到不能再分割为止。由于每一次递归调用都会使得问题规模减半,因此总的时间开销大致相当于n * log₂N[^3]。 ```python def quicksort(arr): if len(arr) <= 1: return arr pivot = arr[len(arr)//2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return quicksort(left)+middle+quicksort(right) ``` #### O(n²)平方阶时间复杂度 双重甚至多重嵌套循环往往会导致这样的结果,比如冒泡排序就需要遍历列表多次才能把所有元素按顺序排列好。随着输入长度的增长,所需运算次数呈指数增长趋势明显加快。 ```python for i in range(len(a)): for j in range(i+1,len(a)): temp=a[i]+a[j] # 访问两个不同位置上的元素并相加 ``` #### O(2ⁿ)指数级时间复杂度 这类算法的特点是在解决问题的过程中需要尝试几乎所有的可能性组合,像暴力破解密码或者某些NP完全问题求解方案就属于此类。它们虽然理论上可以给出正确解答但却因为效率过低而不具备实际应用价值。 ```python def fibonacci_recursive(n): if n<=1: return n else: return fibonacci_recursive(n-1)+fibonacci_recursive(n-2) # 每一步都要重新算前面的结果 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值