【数据结构和算法】时间复杂度和空间复杂度

时间复杂度

时间复杂度是算法效率的一个重要指标,它描述了算法运行时间与输入数据量之间的关系,给出了算法运行时间的上界估计。

时间复杂度主要关注算法中基本操作的执行次数,特别是当输入规模(通常用n表示)增大时,这些操作次数的增长趋势。在表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如果为f(N),那么时间复杂度为O(f(N))。算法的时间复杂度通常为最坏情况下的时间复杂度。下面通过几个例子来说明如何计算时间复杂度:

  • 常数时间复杂度O(1):一个操作如果和样本的数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。这些操作的时间复杂度被标记为 O(1)。例如赋值操作x=1,不论给x赋值为多少,这个操作的时间都不变。

  • 线性时间复杂度O(n):

    def linear_time_example(arr):
        result = 0
        for i in range(len(arr)):
            result += arr[i]
        return result
    

    这个函数遍历数组arr的每一个元素并求和。如果数组长度为n,则循环将执行n次,因此时间复杂度为O(n)O(n)。

  • 平方时间复杂度 O(n^2)

    def quadratic_time_example(matrix):
        result = 0
        for i in range(len(matrix)):
            for j in range(len(matrix[i])):
                result += matrix[i][j]
        return result
    

    在这个例子中,我们有两个嵌套循环,它们都依赖于矩阵的行数(假设矩阵为方阵)。每个循环都将执行n次,所以总的操作次数为n×n=n2,因此时间复杂度为O(n2)。

  • 对数时间复杂度O(logn)

    def binary_search(arr, target):
        low, high = 0, len(arr) - 1
        while low <= high:
            mid = (low + high) // 2
            if arr[mid] == target:
                return mid
            elif arr[mid] < target:
                low = mid + 1
            else:
                high = mid - 1
        return -1
    

    上述代码为二分查找实现,每次迭代,搜索范围都会减半,因此操作次数与输入大小的对数成比例,即时间复杂度为O(log⁡n)。

  • 线性对数时间复杂度O(nlogn)

    归并排序是一个典型的O(nlog⁡n)算法。它将数组分为两半,递归地排序每一半,然后合并两个有序的部分。虽然每个递归调用的时间复杂度为O(n),但由于递归深度为log⁡n,总的时间复杂度为O(nlog⁡n)。

评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是“常数项时间”。

空间复杂度

空间复杂度是衡量算法在运行过程中所需存储空间的一个指标。它描述了算法消耗的内存与输入数据量之间的关系,通常也使用大O符号(Big O notation)来表示。空间复杂度分析包括了算法运行时临时占用的额外空间,但不包括输入数据本身占用的空间(除非算法需要复制输入数据)。

以下是一些常见的空间复杂度类别:

  1. 常数空间复杂度 - O(1):算法所需的额外空间不随输入数据量的增加而改变。例如,一个简单的函数,仅使用几个变量进行计算,无论输入数据多大,所占空间都是固定的。
  2. 线性空间复杂度 - O(n):算法所需的额外空间直接与输入数据量成正比。例如,在排序算法中,如果需要创建一个与输入数组同样大小的新数组,则空间复杂度为O(n)。
  3. 对数空间复杂度 - O(log⁡n):这种空间复杂度较少见,通常发生在使用分治策略的算法中,如一些递归算法,它们可能只需要存储输入数据的层次结构,而非全部数据。
  4. 平方空间复杂度 - O(n2):如果算法需要创建一个二维数组,且每个维度的大小都与输入数据量相关,那么空间复杂度可能是O(n2)。
  5. 递归算法的空间复杂度:递归算法的空间复杂度通常由递归调用栈的深度决定。例如,二叉树的前序遍历在最坏情况下可能需要O(n)的空间,因为递归调用栈的深度可能达到树的高度。

空间复杂度中最常见的就是O(1)和O(n)。理解空间复杂度对于优化算法和系统设计非常重要,特别是在资源受限的环境中,如嵌入式系统或移动设备。有时候,为了节省空间,可能需要牺牲时间效率,反之亦然。因此,在实际应用中,经常需要在时间和空间之间做出权衡。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值