时间复杂度与空间复杂度

简介: 时间复杂度与空间复杂度1.复杂度是什么2. 复杂度的计算方法遵循以下几个原则3. 时间复杂度与代码结构的关系4. 降低时间复杂度的必要性5. 总结1.复杂度是什么复杂度是衡量代码运行效率的重要度量因素。代码执行过程中会消耗计算时间和计算空间,那需要衡量的就是时间复杂度和空间复杂度。一般情况下代码消耗的资源不会是一个绝对量,他们的消耗程度都与输入的数据量高度相关。为了更客观地衡量消耗程度,我们通常会关注时间或空间消耗量与输入数据量之间的关系复杂度是一个关于输入数据量 n 的函数,假设

@TOC

1.复杂度是什么

  • 复杂度是衡量代码运行效率的重要度量因素。
  • 代码执行过程中会消耗计算时间和计算空间,那需要衡量的就是时间复杂度和空间复杂度
  • 一般情况下代码消耗的资源不会是一个绝对量,他们的消耗程度都与输入的数据量高度相关。为了更客观地衡量消耗程度,我们通常会关注时间或空间消耗量与输入数据量之间的关系
  • 复杂度是一个关于输入数据量 n 的函数,假设你的代码复杂度是 f(n),那么你的空间复杂度就是O(f(n))。

2. 复杂度的计算方法遵循以下几个原则

  • 复杂度与具体的常系数无关:例如 O(n) 和 O(2n) 表示的是同样的复杂度。O(2n) 等于 O(n+n),也等于 O(n) + O(n)。也就是说,一段 O(n) 复杂度的代码只是先后执行两遍 O(n),其复杂度是一致的。
  • 多项式级的复杂度相加的时候,选择高者作为结果:O(n²)+O(n) 和 O(n²) 表示的是同样的复杂度。O(n²)+O(n) = O(n²+n)。随着 n 越来越大,二阶多项式的变化率是要比一阶多项式更大的。因此,只需要通过更大变化率的二阶多项式来表征复杂度就可以了。
  • O(1) 也是表示一个特殊复杂度:含义为某个任务通过有限可数的资源即可完成。此处有限可数的具体意义是,与输入数据量 n 无关。

对于同一个问题,采用不同的编码方法,对时间和空间的消耗是有可能不一样的

下面给出两个示例:对于输入的数组,输出与之逆序的数组。例如,输入 a=[1,2,3,4,5],输出 [5,4,3,2,1]。

方法一:

public void s1_1() {

    int a[] = { 1, 2, 3, 4, 5 };
    int b[] = new int[5];

    for (int i = 0; i < a.length; i++) {
        b[i] = a[i];
    }

    for (int i = 0; i < a.length; i++) {
        b[a.length - i - 1] = a[i];
    }
    System.out.println(Arrays.toString(b));

}

这段代码的输入数据是 a,数据量就等于数组 a 的长度。代码中有两个 for 循环,作用分别是给b 数组初始化和赋值,其执行次数都与输入数据量相等。因此,代码的时间复杂度就是 O(n)+O(n),也就是 O(n)。

空间方面主要体现在计算过程中,对于存储资源的消耗情况。上面这段代码中,我们定义了一个新的数组 b,它与输入数组 a 的长度相等。因此,空间复杂度就是 O(n)。

方法二:

public void s1_2() {

    int a[] = { 1, 2, 3, 4, 5 };
    int tmp = 0;

    for (int i = 0; i < (a.length / 2); i++) {
        tmp = a[i];
        a[i] = a[a.length - i - 1];
        a[a.length - i - 1] = tmp;
    }

    System.out.println(Arrays.toString(a));

}

这段代码包含了一个 for 循环,执行的次数是数组长度的一半,时间复杂度变成了 O(n/2)。根据复杂度与具体的常系数无关的性质,这段代码的时间复杂度也就是 O(n)。

空间方面,我们定义了一个 tmp 变量,它与数组长度无关。也就是说,输入是 5 个元素的数组,需要一个 tmp 变量;输入是 50 个元素的数组,依然只需要一个 tmp 变量。因此,空间复杂度与输入数组长度无关,即 O(1)。

3. 时间复杂度与代码结构的关系

代码的时间复杂度,与代码的结构有非常强的关系我们一起来看一些具体的例子。

例 1,定义了一个数组 a = [1, 4, 3],查找数组 a 中的最大值,代码如下:

public void s1_3() {

    int a[] = { 1, 4, 3 };
    int max_val = -1;

    for (int i = 0; i < a.length; i++) {
        if (a[i] > max_val) {
            max_val = a[i];
        }
    }

    System.out.println(max_val);
}

这个例子比较简单,实现方法就是,暂存当前最大值并把所有元素遍历一遍即可。因为代码的结构上需要使用一个 for 循环,对数组所有元素处理一遍,所以时间复杂度为 O(n)。

例2,下面的代码定义了一个数组 a = [1, 3, 4, 3, 4, 1, 3],并会在这个数组中查找出现次数最多的那个数字:

public void s1_4() {

    int a[] = { 1, 3, 4, 3, 4, 1, 3 };
    int val_max = -1;
    int time_max = 0;
    int time_tmp = 0;

    for (int i = 0; i < a.length; i++) {
        time_tmp = 0;
        for (int j = 0; j < a.length; j++) {
            if (a[i] == a[j]) {
            time_tmp += 1;
        }
        if (time_tmp > time_max) {
            time_max = time_tmp;
            val_max = a[i];
        }
    }

    System.out.println(val_max);

}

这段代码中,我们采用了双层循环的方式计算:第一层循环,我们对数组中的每个元素进行遍历;第二层循环,对于每个元素计算出现的次数,并且通过当前元素次数 time_tmp 和全局最大次数变量 time_max 的大小关系,持续保存出现次数最多的那个元素及其出现次数。由于是双层循环,这段代码在时间方面的消耗就是 n*n 的复杂度,也就是 O(n²)。

在这里,我们给出一些经验性的结论:

  • 一个顺序结构的代码,时间复杂度是 O(1)。
  • 二分查找,或者更通用地说是采用分而治之的二分策略,时间复杂度都是 O(logn)。
  • 一个简单的 for 循环,时间复杂度是 O(n)。
  • 两个顺序执行的 for 循环,时间复杂度是 O(n)+O(n)=O(2n),其实也是 O(n)。
  • 两个嵌套的 for 循环,时间复杂度是 O(n²)。

4. 降低时间复杂度的必要性

为了更好理解,我们来看一些数据。假设某个计算任务需要处理 10 万 条数据。你编写的代码:

  • 如果是 O(n²) 的时间复杂度,那么计算的次数就大概是 100 亿次左右。
  • 如果是 O(n),那么计算的次数就是 10 万 次左右。
  • 如果这个工程师再厉害一些,能在 O(log n) 的复杂度下完成任务,那么计算的次数就是 17 次左右(log 100000 = 16.61,计算机通常是二分法,这里的对数可以以 2 为底去估计)。

5. 总结

  • 它与具体的常系数无关,O(n) 和 O(2n) 表示的是同样的复杂度。
  • 复杂度相加的时候,选择高者作为结果,也就是说 O(n²)+O(n) 和 O(n²) 表示的是同样的复杂度。
  • O(1) 也是表示一个特殊复杂度,即任务与算例个数 n 无关。
目录
相关文章
|
7月前
|
存储 人工智能 缓存
|
6天前
|
机器学习/深度学习 算法
时间复杂度和空间复杂度
时间复杂度和空间复杂度
15 1
|
3月前
|
机器学习/深度学习 算法 Windows
时间复杂度与空间复杂度
如何理解时间复杂度与空间复杂度
|
7月前
|
机器学习/深度学习 算法
时间复杂度和空间复杂度详解
时间复杂度和空间复杂度详解
65 0
|
4月前
|
机器学习/深度学习 算法 搜索推荐
2.时间复杂度与空间复杂度
2.时间复杂度与空间复杂度
30 0
|
6月前
|
算法
【时间复杂度和空间复杂度】
【时间复杂度和空间复杂度】
31 0
|
7月前
|
存储 机器学习/深度学习 并行计算
空间复杂度
空间复杂度(Space Complexity)是用于描述算法在执行过程中所需占用空间大小的量度。空间复杂度通常与算法的输入规模成正比,表示算法在处理不同规模数据时所需的空间资源。空间复杂度可以帮助我们评估算法的效率,以及在实际应用中可能产生的内存消耗。
37 0
|
8月前
|
算法 测试技术
复杂度分析:时间复杂度、空间复杂度
复杂度分析:时间复杂度、空间复杂度
|
9月前
|
算法 程序员
时间复杂度详解
时间复杂度详解
|
10月前
|
机器学习/深度学习 算法
那些年忽略的知识:时间复杂度和空间复杂度详解
那些年忽略的知识:时间复杂度和空间复杂度详解