【算法学习】复杂度

时间复杂度

定义

时间复杂度指输入数据大小为 N 时,算法运行所需花费的时间。
这里统计的是计算操作数量所耗费的时间,可以理解为1次操作耗费1个时间单位。并不是真正意义上的计算耗时。算法真实的运行时间受到语言、处理器等多种因素影响。但是真实计算耗时可以理解成与时间复杂度呈线性关系。
时间复杂度真正体现的是操作数量随着输入数据N的大小变化情况(注意是输入数据N,而不是代码中的其他常数)。根据输入数据的特点,时间复杂度具有最差、平均、最佳三种情况,分别使用 O , Θ ,Ω 三种符号表示。
O(1)<O(logN)<O(N)<O(NlogN)<O(N2)<O(2 N)<O(N!)
在这里插入图片描述

时间复杂度类型

常数(1)与线性(N)过于简单不加赘述。
平方O(N2):两层循环相互独立,都与 NN 呈线性关系,因此总体与 N 呈平方关系
例如:

int algorithm(int N) {
    int count = 0;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            count++;
        }
    }
    return count;
}

这段代码中有两段循环次数为N的for循环,因此时间复杂度呈现平方的关系。N2的典型算法以冒泡排序为例:

int[] bubbleSort(int[] nums) {
    int N = nums.length;
    for (int i = 0; i < N - 1; i++) {
        for (int j = 0; j < N - 1 - i; j++) {
            if (nums[j] > nums[j + 1]) {
                int tmp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = tmp;
            }
        }
    }
    return nums;
}

在计算上,虽然理论上第二次循环的时间复杂度平均为O(N/2),但是两段循环进行统计时,可以近似的看做O(N2),在N数极大的情况下,1/2带来的影响很小。

指数O(2N):常见于递归算法中

int algorithm(int N) {
    if (N <= 0) return 1;
    int count_1 = algorithm(N - 1);
    int count_2 = algorithm(N - 1);
    return count_1 + count_2;
}

阶乘O(N!) 同样常见于递归算法中,例如第一层分裂出 N 个,第二层分裂出 N - 1个,…… ,直至到第 N 层时终止并回溯。很多情况下写一个递归最开始是N!,然后优化到2N

int algorithm(int N) {
    if (N <= 0) return 1;
    int count = 0;
    for (int i = 0; i < N; i++) {
        count += algorithm(N - 1);
    }
    return count;
}

对数 O(logN):对数阶与指数阶相反,指数阶为 “每轮分裂出两倍的情况” ,而对数阶是 “每轮排除一半的情况” 。对数阶常出现于「二分法」、「分治」等算法中,体现着 “一分为二” 或 “一分为多” 的算法思想。

线性对数 O(NlogN) :两层循环相互独立,第一层和第二层时间复杂度分别为O(logN) 和 O(N),则总体时间复杂度为O(NlogN),线性对数阶常出现于排序算法,例如「快速排序」、「归并排序」、「堆排序」等。

空间复杂度

定义

通常情况下,空间复杂度指在输入数据大小为 NN 时,算法运行所使用的「暂存空间」+「输出空间」的总体大小。即存储所有中间变量和对象等数据所需的空间大小 + 存储输出数据所需的空间大小。空间复杂度统计算法在 “最差情况” 下使用的空间大小,以体现算法运行所需预留的空间量,使用符号 O 表示。

空间复杂度类型

依据从小到大排列 O(1)<O(logN)<O(N)<O(N2)<O(2N)
在这里插入图片描述
常数O(1):常量、变量、对象等数据大小与输入数据大小N无关。无累计栈帧空间使用。
线性O(N):元素数量与 N 呈线性关系的任意类型集合(常见于一维数组、链表、哈希表等),皆使用线性大小的空间
平方O(N2):元素数量与 NN 呈平方关系的任意类型集合(常见于矩阵),皆使用平方大小的空间。
指数O(2N):指数阶常见于二叉树、多叉树。例如,高度为 N 的「满二叉树」的节点数量为 2N,占用 O(2N)大小的空间;同理,高度为 NN 的「满 m 叉树」的节点数量为 mN,占用O(mN)=O(2N) 大小的空间。
对数O(logN) :对数阶常出现于分治算法的栈帧空间累计、数据类型转换等。例如快速排序等。

对于算法的性能,需要从时间和空间的使用情况来综合评价。优良的算法应具备两个特性,即时间和空间复杂度皆较低。而实际上,对于某个算法问题,同时优化时间复杂度和空间复杂度是非常困难的。降低时间复杂度,往往是以提升空间复杂度为代价的,反之亦然。

参考链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/r8ytog/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值