数据结构第三课(时间复杂度)

数据结构算法分析

算法分析概述

算法分析,分析算法占用的两类资源:

  1. CPU时间 → 时间性能分析
  2. 内存空间 → 空间性能分析

时间复杂度一般是看循环几次。时间复杂度越高,时间用的就越长。

算法分析的目的:分析算法的时空效率,以便改进算法性能。

算法效率的度量:

  • 时间复杂度
  • 空间复杂度

例题

算法分析的目的是()

A.找出数据结构的合理性

B.研究算法中输入和输出的关系

C.分析算法的效率以求改进

D.分析算法的易读性和可行性

答案:C

示例:设计算法求 1+(1+2)+(1+2+3)+...+(1+2+...+n), n>2

版本1:双重循环
c 复制代码
int Sum1(int n)
{
    int sum = 0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            sum = sum + j;
        }
    }
    return sum;
}
 

版本2:一重循环

c 复制代码
int Sum2(int n)
{
    int sum = 0;
    int s = 0;
    for(int i=1;i<=n;i++)
    {
        s = s + i;
        sum = sum + s;
    }
    return sum;
}

对比:双重循环时间复杂度更高;一重循环优化后效率更好。

1.3.2 算法时间复杂度分析

一个算法由控制结构(顺序、分支、循环) 和原操作构成。

  • 原操作:固有数据类型的操作,如赋值、比较、算术运算 + - * /
  1. 顺序结构:按照顺序依次处理
  2. 分支结构:根据条件判断,改变执行路径
  3. 循环结构:当条件成立时,反复执行指定处理

示例代码

c 复制代码
void fun(int a[], int n)
{
    for(int i=0;i<n;i++)
    {
        a[i]=2*i;
        for(int j=0;j<i;j++)
        {
            printf("%d ",a[i]);
        }
        printf("\n");
    }
}

两种算法分析方式

① 事后分析统计方法

编写对应程序,统计实际运行时间。

缺点:

  1. 和机器性能有关(高性能计算机 vs 单片机)
  2. 和编程语言有关,高级语言执行效率低
  3. 和编译产生的机器指令质量有关
  4. 有些算法不能事后统计(如导弹控制系统)

② 事前估算分析方法

抛开机器、语言等外部因素,把算法执行时间看作问题规模n的函数。

算法时间复杂度:事前预估算法时间开销 T(n) 和问题规模 n 的关系。

T = time。

时间复杂度记号 O

前面这个O绝对不要忘记写!!!

T(n)=O(f(n))
读作:T(n)是f(n)的大O阶

含义:随问题规模n增大,算法执行时间的增长率和f(n)增长率相同。
大O是渐近上界,取最小的上界;忽略常数因子、低阶项。

例子:语句频度计算

c 复制代码
//示例:爱你算法
void love(int n)
{
    int i = 1;
    while(i<=n)
    {
        printf("I love you\n");
        i = i + 1;
    }
    printf("I love you More Than %d\n",n);
}

统计语句执行次数(频度):

  1. int i=1; → 1次
  2. while(i<=n) → n+1次
  3. printf("I love you\n"); → n次
  4. i=i+1; → n次
  5. printf("I love you More Than %d\n",n); →1次

T(n)=1+(n+1)+n+n+1 = 3n+3

当n足够大,常数项可以忽略:(就是这里的3,并且这里的最高次幂前面的系数也可以省略,就是这里的3n前面的系数3

再eg:f(n)=2n³+3n²+2n+1,这里只剩下n³,它是最高次幂,其他的都可以忽略。

)

T(n)=3n+3 = O(n)

化简规则:

  1. 常数项可以忽略;
  2. 只保留最高次幂;
  3. 最高次幂前面的系数忽略。

例:

  • T(n)=n²+3n+1000 ⇒ O(n²)
  • T(n)=5n³+999999 ⇒ O(n³)

循环嵌套时间复杂度计算

  1. 单层循环:循环执行次数和n成正比 ⇒ O(n)
  2. 两层嵌套循环:内外循环都和n相关 ⇒ O(n²)
  3. 三层嵌套循环 ⇒ O(n³)

示例1:两层循环

c 复制代码
void fun(int n)
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            printf("*");
        }
    }
}
 

外层循环n次,内层循环每次n次,总次数 n×n = n²,T(n)=n²,时间复杂度O(n²)

示例2:循环变量不断翻倍

c 复制代码
void fun(int n)
{
    int i=1;
    while(i<=n)
    {
        i = i * 2;
    }
}
 

i:1,2,4,8,...,2ᵏ ≤ n

2ᵏ ≤ n ⇒ k ≤ log₂n

时间复杂度:O(log n)

最好、最坏、平均时间复杂度

  1. 最坏时间复杂度:最坏输入情况下,算法的执行时间。考试最常考。
  2. 最好时间复杂度:最好输入情况下。
  3. 平均时间复杂度:所有输入等概率下的平均执行时间。

做题默认求最坏时间复杂度。

常见时间复杂度大小排序(重点)

O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2ⁿ)

  • O(1):常数阶,和n无关
  • O(log n):对数阶
  • O(n):线性阶
  • O(n log n):线性对数阶
  • O(n²):平方阶
  • O(n³):立方阶
  • O(2ⁿ):指数阶(效率很差)

例题

某算法时间复杂度为O(n²),表明该算法()

A.问题规模是n²

B.执行时间等于n²

C.执行时间与n²成正比

D.问题规模与n²成正比

答案:C(要说就说与它成正比。)

例题

下面算法时间复杂度最高的是()

A.O(log₂n) B.O(n) C.O(n²) D.O(2ⁿ)

答案:D

排序:O(log₂n) < O(n) < O(n²) < O(2ⁿ)

例题(真题)

c 复制代码
count=0;
for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
        count++;

时间复杂度:O(n²)

例题

c 复制代码
void fun(int n)
{
    int i=0,s=0;
    while(s<n)
    {
        i++;
        s = s + i;
    }
}

分析:

s=1+2+3+...+i = i(i+1)/2 < n

i² ≈ 2n ⇒ i ≈ √(2n)

时间复杂度:O(√n)

时间复杂度做题通用步骤(记下来)

  1. 找出基本原操作(最内层循环里面的语句)
  2. 统计基本操作执行次数,得到 T(n)
  3. 去掉常数、低次项、系数,得到大O表示。
  4. 多层循环:看每层循环的次数,相乘。

小技巧:

  • 一层循环:O(n)
  • 两层嵌套:O(n²)
  • 循环变量乘2/除2:O(log n)

空间复杂度

空间复杂度:算法执行过程中占用的存储空间,记为 S(n)

S(n)=O(f(n))

  • 空间复杂度O(1):原地算法,额外空间不随n变化。
  • 递归算法空间复杂度要看递归深度。

背诵总结

  1. 算法分析:分析时间复杂度、空间复杂度。
  2. 大O记号:只看最高次项,忽略常数、系数、低次项。
  3. 常见复杂度大小:O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2ⁿ)
  4. 单层循环 O(n);双层嵌套 O(n²);循环成倍增长 O(log n)
  5. 考试优先求最坏时间复杂度。
相关推荐
LGL6030A17 分钟前
Java学习历程31——初识Spring Boot
java·spring boot·学习
阿达和自己2 小时前
springboot学习-springboot引入MyBatis-Plus
spring boot·学习·mybatis
旖旎夜光2 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习
nice_lcj5203 小时前
LRU 缓存入门:它是什么、怎么用、面试怎么手写
java·数据结构·缓存·面试·lru
꧁细听勿语情꧂3 小时前
直接选择排序,堆排序,冒泡排序,递归快速排序、hoare版本、挖坑法、lomuto前后指针,非递归快速排序
c语言·开发语言·数据结构·算法
§ꦿCFོ༉14 小时前
嵌入式八股文—C语言入门学习(四)
c语言·开发语言·学习
2603_9696948516 小时前
【JavaWeb学习记录】MyBatis核心知识点与实战笔记:从入门到动态SQL
笔记·sql·学习·mysql·mybatis·javaweb·学习方法
Pniubi16 小时前
关于算法用现成数据结构和手撕
数据结构
北京云帆互联科技1 天前
云帆培训考试系统更新说明:v9.3.0
java·学习
sxlishaobin1 天前
Maven Setting详解
java·学习·maven