数据结构与算法( 2 ):时间空间复杂度


一、算法效率的度量规模(引入问题)

1、程序耗费时间的影响因素

(1)、算法采用的策略、方案;
(2)、编译产生的代码质量(编译器的优劣、编译器采用的解决方案的优劣);
(3)、问题的输入规模 n;
(4)、机器执行指令的速度

故 抛开计算机硬件、软件有关的因素,一个程序运行时间依赖于 算法的好坏问题的输入规模

例如:等差求和

 算法(1):

int sum = 0, n = 1000000000;     // 1
for (int i = 1; i <= n; i++)     // 判断了 n+1  次
{
	sum += i;     // 执行了 n 次
}

 算法(2):

int sum = 0, n = 1000000000;     // 1次
sum = (1 + n) * n / 2;        // 1次,而不是O(n^2),时间复杂度看的是 执行次数

分析:算法(1)执行了 1+(n+1)+ n = 2n + 2 次,而算法(2)只执行了 2 次,忽略头尾判断,那么这两个算法就是 n 和 1 的差距

一方面,如果较真研究 精确执行的次数 是非常累的;另一方面,研究算法的复杂度,侧重研究算法随着输入规模的增长量的一个抽象,而不是精确定位次数。

因此只需要看抽象出来的次数,从而得出时间复杂度

分析一个算法的运行时间时,重要的是把基本操作的 数量 和 输入模式 关联起来

2、函数的渐进增长

(1)、函数渐进增长:给定两个函数 f(n)、g(n),如果存在一个正数 N ,使得所有 n>N 使得 f(n) > g(n),那么f(n) 增长渐进快于 g(n)

(2)、例1:算法A要做 2n+3 次(2个不嵌套循环,之后有3次运算),算法B要做 3n+1 次(同上),哪个更快呢?

规模算法A1(2n+3)算法A2(2n)算法B1(3n+1)算法B2(3n)
n=15243
n=27476
n=396109
n=1023203130
n=100203200301300

当 n=1 时,A1 不如 B1;
当 n=2 时,二者效率(耗费时间)相等;
n>2 时,A1 优于 B1,算法A 逐渐拉大与 B 的差距,总体上 A 优于 B
随着规模增大,算法A1、A2 和 B1、B2基本相互覆盖,可见加一个系数对时间影响不大

(3)、例2:算法C :4n+8,算法D:2n2+1 哪个更快呢?

规模算法C1(4n+8)算法C2(n)算法D1(2n2+1)算法D2(n2
n=112131
n=216294
n=3203199
n=104810201100
n=1004081002000110000
n=10004008100020000011000000

观察发现,哪怕去掉与 n 相乘的系数,二者最终结果没有改变:算法C2 次数随着n的增长,还是远小于D2,也就是说, 与最高次项相乘的系数并不重要,可以忽略

(4)、结论:判断算法的效率,应主要考虑主项(最高次项)的阶数,而最高项的系数也不用关注

二、时间复杂度

1.定义

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

(2)、用大写的 O() 来体现算法时间复杂度的记法,称为 大O记法
(3)、一般情况下,随着输入规模 n 的增大, T(n) 增长最 慢 的算法为最优算法

2、推导大 O 阶方法

(1)、用 常数1 取代所有 相加的常数
(2)、取代后的运行次数,只保留最高阶项
(3)、如果最高阶存在,且不为1,则去除与这个项相乘的系数
(4)、分类:
              a、常数阶:

int sum, n;                    // O(1)
printf("Hello World\n");    // O(1)
printf("Hello World\n");
printf("Hello World\n");
printf("Hello World\n");
printf("Hello World\n");
printf("Hello World\n");
sum += (1 + n) * n / 2;     // O(1)

O(8)吗 ?分析一下概念“T(n)是关于问题规模 n 的函数”,再根据推导方法(1),所有 常数和的规模是O(1)
              b、线性阶: 随问题规模n的增加,计算次数线性增长

int sum, n;
for (int i = 0; i < n;i++)
{
    sum += i;
}

时间复杂度:O(n)
              c、m方阶: m 层嵌套

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

时间复杂度:O(nm
特殊情况:

int sum, n;
for (int i = 0; i < n;i++)
{
    for (int j = i; j < n;j++)	// j = i,与 i有关,通过执行次数判断
    {
        sum += i;
    }
}

执行次数:n + (n-1) + (n-2) + … + 1 = (n+1)*n/2
复杂度:O(n2)

              d、对数阶:

int i=1, x;
while (i < x)
{
    i *= 2;
}

循环次数:每次 I * 2后,离 x 更进一步,假设有 n 个2相乘后大于 x,结束循环,即 2^n = x,次数 n = log x

复杂度:O(logn)

3、常见算法时间的多项式关系:

1    <   log    <   n   <    n*log    <   n2    <   n3    <   2n   <   n!   <   nn

4、函数调用 的时间复杂度分析:

1、例子:

void function(int n)    // O(n^2)
{
    int j = 0;
    for (j = 0; j < n;j++)
    {
        printf("%d\n", j);
    }
}   

int main()
{
    int n = 10, i = 0, j = 0;
    n++;    // O(1)

    function(n);    //O(n^2)

    for (i = 0; i < n;i++)  // O(n^2)
    {
        function(i);
    }

    for (i = 0; i < n;i++)      // O(n^2)
    {
        for (j = 0; j < n;j++)
        {
            printf("%d\n", j);
        }
    }

        return 0;
}

注:对于for和function的结合,尽管function本身是O(n2 ) 可能会认为应该是O(n3),但将function带入后,与下一个for嵌套等效

5、最坏(好)情况 与 平均情况

(1)、平均运行时间是期望得到的运行时间
(2)、最坏运行时间是一种保证,在应用中,这是一种最重要的需求,除非特别指定,否则提到的时间都是最坏情况的时间



三、空间复杂度

1、定义

 (1)、算法的空间复杂度通过计算算法所需的存储空间实现
 (2)、算法的空间复杂度的计算公式:S(n) = O( f(n) ),n为问题规模,f(n) 为语句关于 n 所占存储空间的函数
 (3)、通常,用“时间复杂度”来指运行时间的需求,用“空间复杂度”指空间需求
 (4)、当直接要求求算法的“复杂度”时,通常求的是“时间复杂度”

2、例子

(1)、判断某年是否为闰年:
            算法1:想一个算法,通过输入的年份的特征,算出是否为闰年
            算法2:设立一个2050个元素的数组,所有年份输入,并用0、1标记是否为闰年
         分析:
                算法1节省空间,仅需算法计算,但消耗时间
                算法2节省时间,仅需引用查找,但消耗空间
         结论:可以通过时间换取空间,也可空间换取时间

基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip 个人大四的毕业设计、课程设计、作业、经导师指导并认可通过的高分设计项目,评审平均分达96.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 [资源说明] 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设或者课设、作业,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96.5分,放心下载使用! 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),供学习参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值