数据结构与算法----复习Part 2(算法复杂度)

本系列是算法通关手册LeeCode的学习笔记

算法通关手册(LeetCode) | 算法通关手册(LeetCode) (itcharge.cn)

本系列为自用笔记,如有版权问题,请私聊我删除。

目录

一,算法复杂度简介

二,时间复杂度

2.1 时间复杂度简介

2.2 渐进符号

2.2.1 Θ 渐进紧确界符号

2.2.2 O 渐进上界符号

2.2.3 Ω 渐进下界符号

2.3 时间复杂度计算

2.4 最佳,最坏,平均时间复杂度

三,空间复杂度

3.1 空间复杂度简介

3.2 空间复杂度计算

四,总结


 

一,算法复杂度简介

        算法复杂度(Algorithm complexity),在问题输入规模为  n  的条件下,程序的时间使用情况和空间使用情况。

        这里的问题规模指的是算法输入的数据量大小。

二,时间复杂度

2.1 时间复杂度简介

        时间复杂度(Time complexity),在输入规模为  n  的条件下,算法运行所需要花费的时间,可以记为T(n)。

        我们将基本操作次数作为时间复杂度的度量标准。

        基本操作是指算法运行中的每一条语句,每次基本操作都可以在常数时间内完成,是一个运行时间不依赖于操作数的操作。

如:

def algorithm(n):
    fact = 1
    for i in range(1, n + 1) :
        fact *= 1
    return fact

         上述算法中所有语句的执行次数加起来1 + n + n + 1 = 2 * n + 2,可以用一个函数 f(n) 来表达语句的执行次数:f(n) = 2 * n + 2

2.2 渐进符号

        专门用来刻画函数的增长速度。渐进符号只保留了最高阶幂,而忽略了如低阶幂,系数,常量等函数中增长较慢的部分。

        经常用到的渐进符号有三种:Θ 渐进紧确界符号、O 渐进上界符号、Ω 渐进下界符号。

2.2.1 Θ 渐进紧确界符号

       对于函数 f(n) 和 g(n),f(n) = Θ(g(n))。存在正常量 c1、c2​ 和 n0​,使得对于所有 n >= n0​ 时,有 0≤c1⋅g(n) <= f(n) <= c2⋅g(n)。

        也就是说,如果函数 f(n) = Θ(g(n)),那么我们能找到两个正数 c1、c2​,使得 f(n)被 c1⋅g(n)和 c2⋅g(n)夹在中间。

        例如:T(n)=3 * n ^ 2 + 4 * n + 5 = Θ(n^2),可以找到 c1 = 1,c2 = 12,n0 = 1,使得对于所有 n >= 1,都有 n ^ 2 <= 3 * n ^ 2 + 4 * n + 5 <= 12 * n ^ 2。

2.2.2 O 渐进上界符号

        对于函数 f(n) 和 g(n),f(n) = O(g(n))。存在常量c,n0,使得当 n > n0时

有0 <= f(n) <= c * g(n)

        在这里要注意表示形式,f(n) = O(g(n)) 意为 f(n) 的上界是 g(n)。

2.2.3 Ω 渐进下界符号

        对于函数 f(n) 和 g(n),f(n) = Ω(g(n))。存在常量c,n0,使得当 n > n0时

有0 <= c * g(n) <= f(n)。

        同样地,f(n) = Ω(g(n)) 意为 f(n) 的下界是 g(n)。

2.3 时间复杂度计算

求解时间复杂度的步骤如下:

1,找出算法中的基本操作(基本语句):算法中执行次数最多的语句就是基本语句,通常是最内层循环的循环体部分;

2,计算基本语句执行次数的数量级:保证函数中的最高次幂正确即可;

3,用渐进上界O来表示时间复杂度。

求解时应注意:

加法原则:总的时间复杂度等于量级最大的基本语句的时间复杂度;

乘法原则:循环嵌套代码的复杂度等于嵌套内外基本语句的时间复杂度乘积。

例如:

# 2.1 时间复杂度简介
# 例1
def algorithm(n):
    fact = 1
    for i in range(1, n + 1):
        fact *= 1
    return fact

# 2.3 时间复杂度的计算
# 常数级O(1) :
def Time_O1(n):
    a = 1
    b = 2
    return a + b

    # 只要不存在循环或递归结构,时间复杂度都为O(1),O(1)的意义是常数级时间

# 线性O(n)
def Time_On(n):
    sum = 0
    for i in range(n):
        sum += 1
    return sum

    # 单层循环,且语句的执行次数为n

# 平方O(n^2)
def Time_On2(n):
    ans = 0
    for i in range(n):
        for j in range(n):
            ans += i
    return ans

    # 嵌套循环中,内层执行 j 从0到n-1 即n次,外层同理,根据乘法原则,复杂度为O(n^2)

# 阶乘O(n!)
def Time_On_(start, end, count):
    if start == end:
        count[0] += 1
        return
    for i in range(start, end):
        Time_On_(start + 1, end, count)
# count = [0]
# Time_On_(1, 6, count)
# print(count[0])     # 输出为120

    # 在循环中使用了递归,则在每次递归调用中,循环次数为end - start。
    # 在第一层递归调用中,循环次数为end - start,
    # 在第二层递归调用中,循环次数为end - (start + 1),
    # 以此类推。总的循环次数可以表示为
    # (end - start) * (end - (start + 1)) * (end - (start + 2)) * ... * 1,即为n!。
    # 因此,count的最终值将等于n!,其中n为end - start的值。

# 对数O(logn)
def Time_Olngn(n):
    count = 0
    ans = 1
    while ans < n:
        ans *= 2
        count += 1
    return count

    # 每次ans * 2,即n = ans * (2^count)
    # count = logn

# 线性对数O(n * logn)
def Time_Onlogn(n):
    ans = 1
    count = 0
    while ans < n:
        ans *= 2
        for i in range(n):
            count += 1
    return count

    # 嵌套循环中,内层循环时间复杂度为O(n)
    # 外层循环的时间复杂度为O(logn)
    # 根据乘法原则,时间复杂度为O(n * logn)

根据从小到大排序,常见的时间复杂度主要有:

O(1) < O(log⁡n)< O(n) < O(n*log⁡n) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)。

2.4 最佳,最坏,平均时间复杂度

        时间复杂度是关于一个输入问题规模 n 的函数

最佳时间复杂度:每个输入规模下用时最短的输入对应的时间复杂度;

最坏时间复杂度:每个输入规模下用时最长的输入对应的时间复杂度;

平均时间复杂度:每个输入规模下所有可能输入所对应的平均用时复杂度(随机输入下期望用时的复杂度)。

        最佳时间复杂度和最坏时间复杂度都是极端条件下的时间复杂度,发生的概率其实很小。

        为了能更好的表示正常情况下的复杂度,所以我们一般采用平均时间复杂度作为时间复杂度的计算方式。

三,空间复杂度

3.1 空间复杂度简介

        空间复杂度(Space Complexity),在问题输入规模为 n 的条件下,算法所占用的空间大小,可以记作 S(n)。一般将算法的辅助空间作为衡量空间复杂度的标准。

        相比于算法的时间复杂度的计算来说,算法的空间复杂度更容易计算,主要包括

局部变量(算法范围内定义的变量)所占用的空间

系统为实现递归所使用的栈空间两个部分。

3.2 空间复杂度计算

# 常数O(1)
def Space_O1(n):
    a = 1
    b = 2
    ans = a * b + n
    return ans

    # 空间占用大小为常数阶,所以空间复杂度为O(1)

# 线性O(n)
def Space_On(n):
    if n <= 0:
        return 1
    return n * Space_On(n - 1)

    # 采用了递归,每次递归调用占用了一个栈空间,调用了n次,所以空间复杂度为O(n)

根据从小到大排序,常见的算法复杂度主要有:

O(1) < O(log⁡n) < O(n) < O(n^2) < O(2^n) 

四,总结

        算法复杂度包括 【时间复杂度】和【空间复杂度】,用来分析算法执行效率与问题输入规模n的增长关系。通常采用【渐进符号】的形式来表示算法复杂度。

https://algo.itcharge.cn/

原文内容在这里,如有侵权,请联系我删除。

  • 30
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值