http://www.cnblogs.com/danyingjie/archive/2011/11/17/2252466.html

时间复杂度用O()来体现,我们称之为大O记法。记做:T(n)=O(f(n))

一般情况下随着n的增大,T(n)增长最慢的算法为最优算法。

O(1)叫常数阶 O(n)叫线性阶 O(n2)叫平方阶

推倒大O阶

1.       用常数1取代运行时间中的所有加法常数

2.       在修改后的运行次数函数中,只保留最高阶项。

3.       如果最高阶项存在且不是1,则去除与这个项相乘的常数。

得到的结果就是大O阶。

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

对于分支结构而言,无论是真,还是假,执行的次数都是恒定的,不会随着n的变大而发生变化,所以单纯的分支结构(不包含在循环结构中),其时间复杂度也是O(1)。

线性阶:

Int I;

For(i=0;i<n;i++)

{

}

因为循环体中的代码要执行N次,所以它的循环的时间复杂度为O(n)。

对数阶:

Int count=1;

While (count<n)

{

Count=count*2;

}

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

最坏情况运行时间是一种保证,那就是运行时间将不会再坏了。在应用中,这是一种最重要的需求,通常,除非特别指定,我们提到的运行时间都是最坏情况的运行时间。

算法空间复杂度通过计算算法所需的存储空间实现,算法空间复杂度的计算公式记做:S(n)=O(f(n)),其中n为问题的规模,f(n)为语句关于n所占存储空间的函数。

常见的时间复杂度所耗时间的大小排列

O(1)<O(logn)<O(n)<O(nlogn)<O(n2)

http://blog.csdn.net/hitwhylz/article/details/12374407

算法的时间复杂度定义为:

在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记作:T(n}=0(f(n))。它表示随问题规模n的增大,算法执行时间的埔长率和 f(n)的埔长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f( n)是问题规横n的某个函数。

根据定义,求解算法的时间复杂度的具体步骤是:

  ⑴ 找出算法中的基本语句;
  算法中执行次数最多的那条语句就是基本语句,通常是最内层循环的循环体。
  ⑵ 计算基本语句的执行次数的数量级;
  只需计算基本语句执行次数的数量级,这就意味着只要保证基本语句执行次数的函数中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数。这样能够简化算法分析,并且使注意力集中在最重要的一点上:增长率。
  ⑶ 用大Ο记号表示算法的时间性能。
  将基本语句执行次数的数量级放入大Ο记号中。

如何推导大o阶呢?我们给出了下面 的推导方法:

1.用常数1取代运行时间中的所有加法常数。
2.在修改后的运行次数函数中,只保留最髙阶项。
3.如果最高阶项存在且不是1,则去除与这个项相乘的常数。

简单的说,就是保留求出次数的最高次幂,并且把系数去掉。  如T(n)=2n^2+n+1 =O(n^2)

举个例子。

[cpp] view plaincopyprint?
  1. #include "stdio.h"
  2. int main()
  3. {
  4. int i, j, x = 0, sum = 0, n = 100;  /* 执行1次 */
  5. for( i = 1; i <= n; i++)    /* 执行n+1次 */
  6. {
  7. sum = sum + i;               /* 执行n次 */
  8. for( j = 1; j <= n; j++)    /* 执行n*(n+1)次 */
  9. {
  10. x++;                /* 执行n*n次 */
  11. sum = sum + x;      /* 执行n*n次 */
  12. }
  13. }
  14. printf("%d", sum);          /* 执行1次 */
  15. }
#include "stdio.h"
int main()
{
int i, j, x = 0, sum = 0, n = 100;  /* 执行1次 */
for( i = 1; i <= n; i++)    /* 执行n+1次 */
{
sum = sum + i;               /* 执行n次 */
for( j = 1; j <= n; j++)    /* 执行n*(n+1)次 */
{
x++;                /* 执行n*n次 */
sum = sum + x;      /* 执行n*n次 */
}
}
printf("%d", sum);          /* 执行1次 */
}

按照上面推导“大O阶”的步骤,我们来看

第一步:“用常数 1 取代运行时间中的所有加法常数”,

则上面的算式变为:执行总次数 =3n^2 + 3n + 1

(直接相加的话,应该是T(n) = 1 + n+1 + n + n*(n+1) + n*n + n*n + 1 = 3n^2 + 3n + 3。现在用常数 1 取代运行时间中的所有加法常数,就是把T(n) = 3n^2 + 3n + 3中的最后一个3改为1. 就得到了 T(n) = 3n^2 + 3n + 1)


第二步:“在修改后的运行次数函数中,只保留最高阶项”。

这里的最高阶是 n 的二次方,所以算式变为:执行总次数 = 3n^2


第三步:“如果最高阶项存在且不是 1 ,则去除与这个项相乘的常数”。

这里 n 的二次方不是 1 所以要去除这个项的相乘常数,算式变为:执行总次数 = n^2


因此最后我们得到上面那段代码的算法时间复杂度表示为: O( n^2 )

下面我把常见的算法时间复杂度以及他们在效率上的高低顺序记录在这里,使大家对算法的效率有个直观的认识。

O(1) 常数阶 < O(logn) 对数阶 < O(n) 线性阶 < O(nlogn) < O(n^2) 平方阶 < O(n^3) < { O(2^n) < O(n!) < O(n^n) }

最后三项用大括号把他们括起来是想要告诉大家,如果日后大家设计的算法推导出的“大O阶”是大括号中的这几位,那么趁早放弃这个算法,在去研究新的算法出来吧。因为大括号中的这几位即便是在 n 的规模比较小的情况下仍然要耗费大量的时间,算法的时间复杂度大的离谱,基本上就是“不可用状态”。

好了,原理就介绍到这里了。下面通过几个例子具体分析下时间复杂度计算过程。

一。计算 1 + 2 + 3 + 4 + ...... + 100。

常规算法,代码如下:

[cpp] view plaincopyprint?
  1. #include "stdio.h"
  2. int main()
  3. {
  4. int i, sum = 0, n = 100;    /* 执行1次 */
  5. for( i = 1; i <= n; i++) /* 执行 n+1 次 */
  6. {
  7. sum = sum + i;          /* 执行n次 */
  8. //printf("%d \n", sum);
  9. }
  10. printf("%d", sum);          /* 执行1次 */
  11. }
#include "stdio.h"
int main()
{
int i, sum = 0, n = 100;  /* 执行1次 */
for( i = 1; i <= n; i++) /* 执行 n+1 次 */
{
sum = sum + i;            /* 执行n次 */
//printf("%d \n", sum);
}
printf("%d", sum);            /* 执行1次 */
}

从代码附加的注释可以看到所有代码都执行了多少次。那么这写代码语句执行次数的总和就可以理解为是该算法计算出结果所需要的时间。该算法所用的时间(算法语句执行的总次数)为: 1 + ( n + 1 ) + n + 1 = 2n + 3

而当 n 不断增大,比如我们这次所要计算的不是 1 + 2 + 3 + 4 + ...... + 100 = ? 而是 1 + 2 + 3 + 4 + ...... + n = ?其中 n 是一个十分大的数字,那么由此可见,上述算法的执行总次数(所需时间)会随着 n 的增大而增加,但是在 for 循环以外的语句并不受 n 的规模影响(永远都只执行一次)。所以我们可以将上述算法的执行总次数简单的记做: 2n 或者简记 n

这样我们就得到了我们设计的算法的时间复杂度,我们把它记作: O(n)


再来看看高斯的算法,代码如下:

[cpp] view plaincopyprint?
  1. #include "stdio.h"
  2. int main()
  3. {
  4. int sum = 0, n = 100;   /* 执行1次 */
  5. sum = (1 + n) * n/2;    /* 执行1次 */
  6. printf("%d", sum);      /* 执行1次 */
  7. }
#include "stdio.h"
int main()
{
int sum = 0, n = 100; /* 执行1次 */
sum = (1 + n) * n/2;  /* 执行1次 */
printf("%d", sum);        /* 执行1次 */
}

这个算法的时间复杂度: O(3),但一般记作 O(1)。

从感官上我们就不难看出,从算法的效率上看,O(1) < O(n) 的,所以高斯的算法更快,更优秀。

这也就难怪为什么每本算法书开篇都是拿高斯的这个例子来举例了(至少我看的都是)...人家也确实有那个资本。

二。求两个n阶方阵C=A*B的乘积其算法如下:

[cpp] view plaincopyprint?
  1. //右边列为语句执行的频度
  2. void MatrixMultiply(int A[n][n],int B [n][n],int C[n][n])
  3. {
  4. (1) for(int i=0; i <n; i++)                       //n+1
  5. {
  6. (2)      for (j=0;j < n; j++)                       //n*(n+1)
  7. {
  8. (3)           C[i][j]=0;                                  //n^2
  9. (4)           for (k=0; k<n; k++)                 //n^2*(n+1)
  10. {
  11. (5)              C[i][j]=C[i][j]+A[i][k]*B[k][j]; //n^3
  12. }
  13. }
  14. }
  15. }
   //右边列为语句执行的频度
void MatrixMultiply(int A[n][n],int B [n][n],int C[n][n])
{
(1) for(int i=0; i <n; i++)                       //n+1
{
(2)      for (j=0;j < n; j++)                       //n*(n+1)
{
(3)           C[i][j]=0;                                  //n^2
(4)           for (k=0; k<n; k++)                 //n^2*(n+1)
{
(5)              C[i][j]=C[i][j]+A[i][k]*B[k][j]; //n^3
}
}
}
}

则该算法所有语句的频度之和为:

T(n) = 2n^3+3n^2+2n+1;  利用大O表示法,该算法的时间复杂度为O(n^3)。

三。分析下列时间复杂度

[cpp] view plaincopyprint?
  1. void test_(int n)
  2. {
  3. i = 1, k = 100;
  4. while (i<n)
  5. {
  6. k = k + 1;
  7. i += 2;
  8. }
  9. }
void test_(int n)
{
i = 1, k = 100;
while (i<n)
{
k = k + 1;
i += 2;
}
}

设for循环语句执行次数为T(n),则 i = 2T(n) + 1 <= n - 1,  即T(n) <= n/2 - 1 = O(n)

四。分析下列时间复杂度

[cpp] view plaincopyprint?
  1. void test_2(int b[], int n)
  2. {
  3. int i, j, k;
  4. for (i=0; i<n-1; i++)
  5. {
  6. k = i;
  7. for (j=i+1; j<n; j++)
  8. {
  9. if (b[k] > b[j])
  10. {
  11. k = j;
  12. }
  13. }
  14. x = b[i];
  15. b[i] = b[k];
  16. b[k] = x;
  17. }
  18. }
void test_2(int b[], int n)
{
int i, j, k;
for (i=0; i<n-1; i++)
{
k = i;
for (j=i+1; j<n; j++)
{
if (b[k] > b[j])
{
k = j;
}
}
x = b[i];
b[i] = b[k];
b[k] = x;
}
}

其中,算法的基本运算语句是

if (b[k] > b[j])

{

   k = j;

}

其执行次数T(n)为:

五。分析下列时间复杂度

[cpp] view plaincopyprint?
  1. void test_3(int n)
  2. {
  3. int i = 0, s = 0;
  4. while (s<n)
  5. {
  6. i++;
  7. s = s + i;
  8. }
  9. }
void test_3(int n)
{
int i = 0, s = 0;
while (s<n)
{
i++;
s = s + i;
}
}

其中,算法的基本运算语句即while循环内部分,

设while循环语句执行次数为T(n),则

六。Hanoi(递归算法)时间复杂度分析

[cpp] view plaincopyprint?
  1. void hanoi(int n, char a, char b, char c)
  2. {
  3. if (n==1)
  4. {
  5. printf("move %d disk from %c to %c \n", n, a, c);  //执行一次
  6. }
  7. else
  8. {
  9. hanoi(n-1, a, c, b);    //递归n-1次
  10. printf("move %d disk from %c to %c \n", n, a, c);  //执行一次
  11. hanoi(n-1, b, a, c);    //递归n-1次
  12. }
  13. }
void hanoi(int n, char a, char b, char c)
{
if (n==1)
{
printf("move %d disk from %c to %c \n", n, a, c);  //执行一次
}
else
{
hanoi(n-1, a, c, b);    //递归n-1次
printf("move %d disk from %c to %c \n", n, a, c);  //执行一次
hanoi(n-1, b, a, c);    //递归n-1次
}
}

对于递归函数的分析,跟设计递归函数一样,要先考虑基情况(比如hanoi中n==1时候),这样把一个大问题划分为多个子问题的求解。

故此上述算法的时间复杂度的递归关系如下:

大话数据结构之算法 时间复杂度相关推荐

  1. 大话数据结构与算法(一)

    大话数据结构与算法-程杰 第一章 数据结构绪论 一.基本概念和术语 数据结构:是相互之间存在一种或者多种特定关系的数据元素的集合: 数据:是描述客观事物的符号,是计算机可以操作的对象,是能够被计算机识 ...

  2. 数据结构与算法 -- 时间复杂度

    数据结构与算法看完了,回过头来在看时间复杂度,对它们的效率做个比较吧. 一.时间复杂度介绍 1.时间复杂度定义 参看:数据结构-算法-时间复杂度计算 在进行算法分析,语句总得执行次数 T(n) 是关于 ...

  3. python数据结构和算法 时间复杂度分析 乱序单词检测 线性数据结构 栈stack 字符匹配 表达式求值 queue队列 链表 递归 动态规划 排序和搜索 树 图

    python数据结构和算法 参考 本文github 计算机科学是解决问题的研究.计算机科学使用抽象作为表示过程和数据的工具.抽象的数据类型允许程序员通过隐藏数据的细节来管理问题领域的复杂性.Pytho ...

  4. 大话数据结构与算法:基础篇

    1.数据结构的重要性 数据结构是计算机软件相关专业的基础课程,几乎可以说,要想从事编程工作,无论是否是科班出身(比如我,标准的非科班人员,我是学医的,哈哈)都不可以绕过数据结构与算法这部分知识. 数据 ...

  5. 数据结构和算法 —— 时间复杂度+空间复杂度

    算法效率的度量方法 事后统计方法 这种方法主要是通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低. 但这种方法显然是有很大缺陷的: 必须依据算 ...

  6. 数据结构与算法——时间复杂度

    目录 文章目录 前言 一.算法时间复杂度是什么? 二.推导大O阶的方法 二.四种典型的时间复杂度 1.常数阶--O(1) 2.线性阶--O(n) 3.对数阶--O(logn) 4.平方阶--O(n^2 ...

  7. 数据结构与算法——时间复杂度的粗略计算

    1.什么是时间复杂度 首先我们来看一段代码: int cal(int n) {int sum = 0;int i = 1;int j = 1;for (; i <= n; ++i) {j = 1 ...

  8. 大话数据结构与算法:算法初步1

    1.算法的定义: 什么是算法呢?算法是描述解决问题的方法.如今普遍认可的对算法的定义是:算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作. 对于一个特定 ...

  9. 数据结构与算法-时间复杂度的级别-时间复杂度的算法

    时间复杂度分级 时间复杂度的计算 >计算规则 >基本操作,时间复杂度为 1 >程序的流程控制 顺序,分支,循环 . 按照计算规则 最终去掉常量 用大O表示法最终结果为 O(n^2)

最新文章

  1. 腾讯员工上半年人均月薪 7.8 万,网友:别人拿月薪我拿年薪。。。
  2. java enumerator_简单介绍java Enumeration
  3. apt 卸载_你所不知道的apt-get
  4. What is ieHTTPHeaders?
  5. 使用函数求最大公约数 pta_高中数学选修教材2-导数第6课时《函数的单调性与导数》教学设计...
  6. c++多边形扫描线填充算法_python 小乌龟turtle画随机正多边形
  7. 如何应对冬季暴涨的体重
  8. RFIC4463_F2C
  9. mysql 联合索引底层结构_MySQL联合索引底层数据结构
  10. TranslateAnimation祥解
  11. python5.2、输出格式控制 - 摄氏-华氏温度换算
  12. java获取用户地理位置_Java获取用户访问IP及地理位置的方法详解
  13. 2017 Top 10 Web 应用安全威胁,你的企业正在经历哪些?
  14. oracle 查看用户配额,【Quota】获取及调整用户表空间配额方法
  15. openStack cluster chk
  16. javascript之内置函数
  17. AWS Key Management Service(KMS)
  18. MTK 按键驱动流程总结
  19. pc-com串口(DB9)管脚定义和单片机uart串口
  20. XP系统装PhotoShop的CS3版本

热门文章

  1. pytorch慢到无法安装,该怎么办?
  2. SpaceX完成“星舰”空中悬停,距载人探火星还远吗?
  3. 10.2.1 CSS介绍与引入
  4. ubuntu中安装wmware-tools
  5. python中count()函数的用法
  6. 【机器视觉】 global算子
  7. 【Tools】GitBook入门教程
  8. 开源游戏机java模拟器_开源一个Flutter编写的完整终端模拟器
  9. python计算相关矩阵_Numpy使用大全(python矩阵相关运算大全)-Python数据分析基础2...
  10. 蛮力法求最大字段和时间复杂度_硬笔字应该选择的工具,你了解吗?