算法复杂度:从入门到面试必备

算法复杂度:从入门到面试必备

掌握算法复杂度,是通往高效编程的第一道门槛


前言

在数据结构与算法的学习道路上,算法复杂度是我们遇到的第一个重要概念。它不仅是理论分析的工具,更是校招笔试和面试中的必考内容。本文将带你从零开始理解时间复杂度和空间复杂度,掌握大O渐进表示法,并通过经典例题加深理解。


一、什么是数据结构和算法?

1.1 数据结构

数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。没有一种单一的数据结构对所有用途都有用,因此我们需要学习各式各样的数据结构,如:线性表、树、图、哈希等。

1.2 算法

算法(Algorithm)是定义良好的计算过程,它取一个或一组值作为输入,并产生一个或一组值作为输出。简单来说,算法就是一系列计算步骤,用来将输入数据转化为输出结果。

1.3 为什么重要?

  • ✅ 校园招聘笔试必考
  • ✅ 校园招聘面试必考
  • ✅ 覆盖几乎所有技术岗位:Java工程师、C++工程师、前端工程师、算法工程师、测试开发工程师等

二、为什么要学算法复杂度?

2.1 面试中的高频考点

从各大厂的面试题来看,算法复杂度几乎是必考内容:

公司 岗位 复杂度相关考题
腾讯 C++后台开发实习 快排堆排时间复杂度、推导过程
科大讯飞 研发类校招 多个算法题涉及复杂度分析
猎豹科技 C++开发实习 数组和链表插入/删除/查找的时间复杂度、最小堆复杂度

2.2 衡量算法好坏的标准

衡量一个算法的好坏,主要从两个维度考量:

维度 含义 关注程度
时间复杂度 算法运行的快慢 目前主要关注
空间复杂度 算法运行所需额外空间 早期受限于存储容量,如今关注度降低

三、时间复杂度详解

3.1 为什么不能直接计算程序运行时间?

  1. 运行时间受编译环境机器配置影响
  2. 只能在程序写完后测试,无法提前评估
  3. 不同语句编译后的指令条数不同,精确计算困难

因此,我们使用时间复杂度函数 T(N) 来计算程序的执行次数,用执行次数代表时间效率的优劣。

3.2 核心案例:Func1 的执行次数分析

c 复制代码
void Func1(int N)
{
    int count = 0;
    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            ++count;  // 执行 N² 次
        }
    }
    
    for (int k = 0; k < 2 * N; ++k)
    {
        ++count;  // 执行 2N 次
    }
    
    int M = 10;
    while (M--)
    {
        ++count;  // 执行 10 次
    }
}

基本操作次数:T(N) = N² + 2N + 10

N 的取值 T(N) N² 的占比
10 130 76.9%
100 10210 97.9%
1000 1002010 99.8%

当 N 不断增大时,低阶项和常数项对结果的影响越来越小 ,因此我们只需要关注最高阶项


四、大O渐进表示法

4.1 推导规则

规则 说明
规则1 只保留最高阶项,去掉低阶项
规则2 去除最高阶项的常数系数
规则3 若无 N 相关项,用常数 1 取代所有加法常数

4.2 示例汇总

函数 T(N) 时间复杂度
Func1 N² + 2N + 10 O(N²)
Func2 2N + 10 O(N)
Func3 M + N O(M+N)
Func4 100 O(1)

五、最好、最坏、平均情况

strchr(字符串查找字符)为例:

c 复制代码
const char* strchr(const char* str, int character)
{
    const char* p_begin = str;
    while (*p_begin != character)
    {
        if (*p_begin == '\0')
            return NULL;
        p_begin++;
    }
    return p_begin;
}
情况 执行次数 时间复杂度
最好(字符在第一位) 1 O(1)
平均(字符在中间) N/2 O(N)
最坏(字符在最后/不存在) N O(N)

⚠️ 大O渐进表示法一般关注最坏情况,即算法的上界。


六、经典时间复杂度计算

6.1 冒泡排序

c 复制代码
void BubbleSort(int* a, int n)
{
    for (size_t end = n; end > 0; --end)
    {
        int exchange = 0;
        for (size_t i = 1; i < end; ++i)
        {
            if (a[i-1] > a[i])
            {
                Swap(&a[i-1], &a[i]);
                exchange = 1;
            }
        }
        if (exchange == 0)
            break;
    }
}
情况 执行次数 时间复杂度
最好(已有序) N O(N)
最坏(降序) N(N+1)/2 O(N²)

6.2 对数阶(二分查找思想)

c 复制代码
void func5(int n)
{
    int cnt = 1;
    while (cnt < n)
    {
        cnt *= 2;
    }
}

设执行次数为 x,则 2ˣ = n,因此 x = log₂n

时间复杂度:O(log n)

💡 底数大小对结果影响不大,一般省略不写,统一表示为 O(log n)

6.3 递归函数

c 复制代码
long long Fac(size_t N)
{
    if (0 == N)
        return 1;
    return Fac(N-1) * N;
}

每次调用 Fac 函数的时间复杂度为 O(1),共递归调用 N 次

时间复杂度:O(N)


七、空间复杂度

7.1 定义

空间复杂度是算法运行过程中额外临时开辟的空间 的数学表达式,计算的是变量的个数而非字节数。

7.2 示例1:冒泡排序

c 复制代码
void BubbleSort(int* a, int n)
{
    // 仅申请了 exchange 等有限个局部变量
    // 使用了常数个额外空间
}

空间复杂度:O(1)

7.3 示例2:阶乘递归

c 复制代码
long long Fac(size_t N)
{
    if (N == 0)
        return 1;
    return Fac(N-1) * N;
}

递归调用了 N 次,额外开辟了 N 个函数栈帧,每个栈帧使用常数个空间

空间复杂度:O(N)


八、常见复杂度对比

函数 增长速度 评价
O(1) 常数阶 ⭐⭐⭐⭐⭐ 最佳
O(log n) 对数阶 ⭐⭐⭐⭐ 优秀
O(n) 线性阶 ⭐⭐⭐ 良好
O(n log n) 线性对数阶 ⭐⭐⭐ 一般
O(n²) 平方阶 ⭐⭐ 较差
O(n³) 立方阶 ⭐ 很差
O(2ⁿ) 指数阶 ⭐ 极差
O(n!) 阶乘阶 💀 灾难

九、学习建议与资源

9.1 两大秘诀

秘诀 说明
死磕代码 光看不练假把式,多写代码才能形成肌肉记忆
画图思考 数据结构的学习离不开画图,把抽象的逻辑用图形具象化

9.2 书籍推荐

书籍 作者 推荐理由
《数据结构》 严蔚敏 C语言版本,各大院校指定教材
《数据结构与算法分析》 Weiss C++版本,内容详尽,代码规整
《算法导论》 Thomas H.Cormen 叙述严谨,内容全面,深入讨论各类算法
《大话数据结构》 程杰 趣味易读,算法讲解细致深刻

结语

算法复杂度是数据结构与算法的基石,理解它不仅能帮助你在面试中脱颖而出,更能让你在实际开发中做出更优的技术决策。

掌握了大O渐进表示法后,你就可以开始分析各种数据结构和算法的时间/空间效率了。

下一站,线性表------顺序表与链表,我们不见不散!


📌 本文首发于个人技术博客,欢迎交流讨论。如有错误,敬请指正。


写作不易,如果觉得有帮助,欢迎点赞、收藏、转发支持!

相关推荐
道影子2 小时前
《黄帝内经》021章|津凝精晶 沉降为患
人工智能·深度学习·神经网络·算法·机器学习
道影子2 小时前
《黄帝内经》022章|调和双旋 伏风自消
人工智能·深度学习·神经网络·算法·机器学习
吞下星星的少年·-·2 小时前
牛客技能树:一道GCD问题(排序,数论)
算法
m沐沐2 小时前
【计算机视觉】人脸识别三大经典算法:LBPH、Eigenfaces、FisherFaces 原理与实战
图像处理·人工智能·深度学习·opencv·算法·机器学习·计算机视觉
玉宇夕落3 小时前
git 指令简单学习
面试
Lumos1863 小时前
嵌入式常用滤波算法与控制算法(5)卡尔曼滤波(下)
算法
Lumos1863 小时前
嵌入式常用滤波算法与控制算法(6)互补滤波
算法
Tisfy3 小时前
LeetCode 3536.两个数字的最大乘积:O(1)空间维护max2
数学·算法·leetcode·题解
知识分享小能手3 小时前
统计学学习教程,从入门到精通,一元线性回归 —— 知识点详解(17)
学习·算法·线性回归
ychqsq3 小时前
95.归位
经验分享·职场和发展