1,前置知识
我们在计算时间复杂度之前的前置知识是等差数列的通项公式和求和公式以及等比数 列的通项公式和求和公式
等差数列:
通项公式:an=a1+(n-1)d(d是公差)
求和公式:Sn=n(a1+an)/2
等比数列:
通项公式:an=a1*q^(n-1)(q是共比)
求和公式:Sn=a1*(1-q^n)/1-q
2,省略常数项
计算时间复杂度首先要抛开常数项的程序段
比如
void fun(int n)
{
int i=0;
while(i<=n)
{
i++;
}
}
这一段程序中,int i=0;这一句就是常数项的程序,他只会执行一次,所以我们只计算 while循环里面执行的次数
3,计算时间复杂度
计算时间复杂度就是计算执行某个程序需要执行多少次,着重计算带有阶数的程序段 比如上图代码while循环带有阶数,我们只计算while循环里面的时间复杂度,易知会 执行n次,所以时间复杂度为o(n)。
下面就介绍一下计算时间复杂度的通用方法是什么
比如这个例子
void fun(int n)
{
int i=1;
while(i<=n)
{
i*=2
}
}
我们省略常数项int i=0,我们只计算while循环里面执行的次数
我们知道,计算时间复杂度就是计算程序程序的次数,所以我们这里计算while循环总 共执行了多少次
执行次数 | i |
第一次执行 | i=2 |
第二次执行 | i=4 |
第三次执行 | i=8 |
…… | …… |
以此类推:2,4,8,16,……,可以发现i的值构成了一个等比数列,其中公比是2,第n 项an=2*2^(n-1)=>an=2^n
我们知道while循环执行结束的条件是i>n,我们假设执行了k次之后i>n,也就是不 满足while循环条件了,这个k值就是我们要求的时间复杂度的规模
所以根据an我们得到一个不等式,,当执行k次之后an的值>n,也就是2^k什么时候大于n,求得k值即可:
2^k=n时,k=
所以当k大于时,while循环结束,k值就是我们要求的时间复杂度规模,所以这个例子的时间复杂度就是O()
4,案例
(1)求下列程序段的时间复杂度
count=0
for(k=1;k<=n;k*=2) ①
for(j=1;j<=n;j++) ②
count++;
首先计算①执行的次数
可以发现k构成一个等比数列,an=2^(n-1),当k=n时,执行了次,也就说① 的时间复杂度为O()
我们在判断②的时间复杂度,②中执行的次数和外层循环无关,依次是:1,2,3,4……n, 所以可以发现构成一个等差数列,公差是1,an=n,当执行了n次之后循环结束时间, 故复杂度为O(n)
我们计算程序执行的次数只和内层循环执行的次数有关,也就是和count++执行的次数 有关,我们计算count++执行的次数就是计算整个程序执行的次数,也就是这个程序段 的时间复杂度
可以发现,count++执行的次数有内层循环和外出循环决定,也就是他俩相乘的结果 就是count++执行的次数,上面我们说了外层循环复杂度是,而内层循环每次执行n次,所以总的时间复杂度是n*,也就是O(n)
这个程序段内层循环和外层循环无关,所以外层循环执行一次,内层循环都会执行n 次,当内层循环收到外层循环的限制时,时间复杂度就需要另算了
(2)
int i=0,sum=0;
while(sum<n) sum+=++i;
sum的大小依次是:0+1,0+1+2,0+1+2+3,0+1+2+3+4……i,依次类推,可以发现构成一 个等差数列,Sn=i(i+1)/2,所以执行的次数满足(1+k)*k/2<n,也就是执行k=次(这 里用求根公式算,答案的规模就是)后,循环结束,所以这个程序段的时间复杂度 为O()