Login
首页 > 图文教程 > C++教程

时间空间复杂度入门

燃冰世纪教育 2025-06-24 15:47:16 人看过

对于初学者,你只需要记住以下几点:

1、时空复杂度用 Big O 表示法表示(类似 (1),(2),() 等)。它们都是估计值,不需要精确计算,常数项和低增长项都可以忽略,仅需保留最高增长项

比方说 (22+3+1) 等同于 (2)(1000+1000) 等同于 ()

2、我们分析算法复杂度时,分析的是最坏情况的复杂度。这一点会在下面的示例中体现。

3、时间复杂度用来衡量一个算法的执行效率,空间复杂度用来衡量算法的内存消耗,它们都是越小越好。

比方说时间复杂度 () 的算法比 (2) 的算法执行效率高,空间复杂度 (1) 的算法比 () 的算法内存消耗小。

当然,一般我们要说明这个  代表什么,比如  代表输入的数组的长度。

4、如何估算?现在你可以简单理解:时间复杂度大部分情况下就是看 for 循环的最大嵌套层数;空间复杂度就看算法申请了多少空间来存储数据


注意

以上的分析方法中,有些细节并不严谨:

1、按照 for 循环的嵌套层数来估算时间复杂度是简化的方法,其实不完全准确。

2、大部分时候我们是分析最坏情况下的复杂度,但是对于数据结构 API 的复杂度衡量,我们会分析平均复杂度。

完善的复杂度分析方法会在 算法时空复杂度分析实用指南 具体介绍,以上估算方法对于学习本章内容足够了。


举几个例子来说比较直观。

时间/空间复杂度案例分析

示例一,时间复杂度 (),空间复杂度 (1)

// 当 n 是 10 的倍数时,计算累加和,否则返回 -1
int sum(int n) {
    if (n % 10 != 0) {
        return -1;
    }
    int sum = 0;
    for (int i = 0; i <= n; i++) {
        sum += i;
    }
    return sum;
}


其实只有当 n 是 10 的倍数时,算法才会执行 for 循环,时间复杂度是 ()。其他情况下算法会直接返回,时间复杂度是 (1)

但是算法复杂度只考察最坏情况,所以这个算法的时间复杂度是 (),空间复杂度是 (1)

示例三,时间复杂度 (2),空间复杂度 (1)

// 数组是否存在两个数,它们的和为 target?
bool hasTargetSum(vector<int>& nums, int target) {
    for (int i = 0; i < nums.size(); i++) {
        for (int j = i + 1; j < nums.size(); j++) {
            if (nums[i] + nums[j] == target) {
                return true;
            }
        }
    }
    return false;
}

算法嵌套了两层 for 循环,所以时间复杂度是 (2),其中  代表 nums 数组的长度。

我们的算法只使用了 i, j 两个变量,这是常数级别的空间消耗,所以空间复杂度是 (1)

你也许会说,内层的 for 循环并没有遍历整个数组,且有可能提前 return,算法实际执行的次数应该是小于 2 的,时间复杂度还是 (2) 吗?

是的,还是 (2)。具体到不同的输入,算法的实际执行次数确实会小于 2,但我们不需要关心这些细节,估算一个最坏情况的时间复杂度就可以了。

每层 for 循环在最坏情况下都是 () 的时间复杂度,套在一起,总的时间复杂度是 (2)

示例四,时间复杂度 (),空间复杂度 ()

void exampleFn(int n) {
    vector<int> nums(n);
}

这个函数中创建了一个大小为 n 的数组,所以空间复杂度是 ()

对于 Java 来说,new int[n] 这个操作会申请数组空间并将所有元素初始化为 0。内存申请操作的时间复杂度可以认为是 (1),但初始化所有元素的操作相当于一个隐藏的 for 循环,时间复杂度是 ()。所以总的时间复杂度是 ()

时间复杂度并不仅仅体现在你看得到的 for 循环,每一行代码都可能有隐藏的时间复杂度。所以说要了解编程语言提供的常用数据结构实现原理,这是准确分析时间复杂度的基础。

示例五,时间复杂度 (),空间复杂度 ()

// 输入一个整数数组,返回一个新的数组,新数组的每个元素是原数组对应元素的平方
vector<int> squareArray(vector<int>& nums) {
    vector<int> res(nums.size());
    for (int i = 0; i < nums.size(); i++) {
        res[i] = nums[i] * nums[i];
    }
    return res;
}

算法初始化 res 数组需要 () 的时间复杂度,包含一个 for 循环,时间复杂度也是 (),总的时间复杂度是还是 () 其中 n 代表 nums 数组的长度。

我们声明了一个新的数组 res,这个数组的长度和 nums 数组一样,所以空间复杂度是 ()

好了,初学者明白上面这些基本的时间、空间复杂度分析暂时就够用了

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章