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

数据结构算法分析

算法分析概述

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

  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. 考试优先求最坏时间复杂度。
相关推荐
Logic1014 小时前
C语言/数据动态规划题解:翻转一次子数组后的最大子数组和——四状态DP(O(n)时间O(1)空间)
c语言·数据结构·动态规划·时间复杂度·算法题·状态机dp·最大子数组和
小π军5 小时前
最大重叠区间数量
数据结构·算法
泡泡鱼(敲代码中)5 小时前
MySQL基础学习笔记:从数据模型到DDL全掌握
开发语言·数据库·笔记·学习·mysql
Logic1015 小时前
C语言/数据结构字符串题解:找出DNA序列中未配对的独特序列——排序+遍历(O(nlogn))
c语言·数据结构·字符串·数组·排序·时间复杂度·算法题
fanged6 小时前
Agent的Skills(TODO)
学习
是隼人6 小时前
buuctf-pwn picoctf_2018_shellcode(ret2shellcode)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
wzdark6 小时前
基于链表的内存池设计与内存复用机制4
java·数据结构·链表
m4Rk_7 小时前
【论文阅读】Agent 记忆机制(69):STITCH——用上下文意图解决“语义相关但情境错误”的记忆检索
论文阅读·人工智能·学习·开源·github
2601_949950637 小时前
个人在线刷题的工具
学习·考研·小程序·刷题·小程序推荐