时间复杂度(Time Complexity)
前言
时间复杂度
应该是计算机专业中一个很重要的知识,重要到你有可能因为没好好掌握而被面试官刷掉。正好现在大二正在学数据结构
,写这篇博客既是为了巩固一下自己的掌握程度,同时也帮大家复习复习或是介绍一下。
概念介绍
为了用一种不受算法所用语言以及编译程序不同或机器性能
影响的方法来评估算法的效率,我们通常选取所研究问题的基本操作
的执行次数
作为整个算法的时间量度。但在某些情况下,算法的执行次数计算可能难以计算。因此引入时间复杂度作为算法规模大小的衡量工具,是对算法效率好坏的一种非定量表示。
时间复杂度:
一般情况下,算法中基本操作的重复执行次数是问题规模n的某个函数f(n) ,算法的时间量度记作:
T
(
n
)
=
O
(
f
(
n
)
)
T(n)=O(f(n))
T(n)=O(f(n))
它表示随着问题规模n的增大,算法执行时间的增长率不超过f(n)的增长率,也就是所谓的时间复杂度
基本操作:
基本操作
通常指算法中最深层循环的语句,它也是算法最核心
的语句,同时基本操作的重复执行次数与整个算法的执行时间成正比
。通常是对变量的赋值、数学运算等。一般通过算法本身的目的来确定,比如,一个交换排序算法,其基本操作就是最内层的交换赋值操作。只有在确定了算法的基本操作后,才能计算算法的时间复杂度。
频度(Frequency Count)
指基本操作的重复执行次数
,属于定量
计算
如何计算时间复杂度
第一步已经介绍过,下面着重讲解中间两个核心步骤
1.计算基本操作的频度
拿几个简单的例子来说:
例1
int x=1;
++x;
那么很简单,基本操作是x的自增,同时它仅仅执行了一次。即频度为1,而且它的执行次数与x的赋值大小无关,也就是与问题规模n无关,因此f(n)=1,即T(n)=O(1)
例2
for(i=1;i<=n;++i){
++x;
}
与例1相似,++x的执行次数为n次,即f(n)=n,随着问题规模n的增大,所需时间越多,且与n的大小成正比
例3
for(i=1;i<=n;i++){
for(int j=1;j<=n;j++){
++x;
}
}
例3也是同样的道理,f(n)=n^2,不过是与二次方成正比
若遇到的是非常规问题,可以按以下方法处理(取自《数据结构》教材):
1.对于并列循环
结构,取各循环结构计算时间的最大值
2.对于嵌套循环
结构,取最内层循环体中语句的执行次数
3.若各循环之间无关系
,采用乘法原则,将各循环的次数相乘
4.对于递归算法,分解为两部分计算:
(1)执行目前层次的递归分解运算所需时间
(2)执行递归调用所需时间
2.将频度转为时间复杂度
由于频度是定量的精确计算
,而时间复杂度是非定量的整体规模表示
,因此要简化舍去计算所得频度,即“化简”f(n)
简化原则:
1.删掉常数项以及常数系数
2.去掉低阶项,保留最高阶项
简化举例:
对于某算法,
原
f
(
n
)
=
5
n
2
+
7
n
+
9
原f(n)=5n^2+7n+9
原f(n)=5n2+7n+9
简
化
后
F
(
n
)
=
n
2
简化后F(n)=n^2
简化后F(n)=n2
因此该算法时间复杂度为
T
(
n
)
=
O
(
n
2
)
T(n)=O(n^2)
T(n)=O(n2)
符号O的解释(也是从数学角度解释为什么可以简化):
为了不含糊,这里解释一下为什么是用符号O来表示时间复杂度。这里要特别声明这个符号与高数中表示高阶无穷小的小o()符号不是一个东西
百度百科对其定义如下:
简单来说就是用一个更简单的函数来描述一个项数较多的复杂函数的规模增长情况。形象一点说,我相信大家都去过小区售楼部吧,里面都会有一大块的模型区域用来展示整个楼盘的布局,游泳池啊,车库啊,活动中心啊这些。其实可以把这个理解为对小区规模的模拟和描述,这种模拟好处就是节约成本 (减少频度计算量),可以忽略房子内部结构布局如下水管道,光纤等 (删去低阶项和常数因子,抓主略次),更方便我们从整体的角度去分析。
当然你也可以以自己的方式理解,下面是我截取的百度对其的解释:
最后给大家来个练习巩固巩固
现有如下代码
int function(int n){
int sum=0;
for(int i=1;i<n+1;i++){
for(int j=n;j>i-1;j--)
for(int k=1;k<j+1;k++)
sum++;
}
return sum;
}
请你求出sum++的频度和函数function()的时间复杂度。欢迎大家踊跃评论
答案链接如下:
https://blog.csdn.net/WizardrK/article/details/108692972