在程序员这个行当里流传着这样一句话“面试造火箭入职拧螺丝。”而“造火箭”的核心往往就是数据结构与算法。很多朋友刚入行时觉得我平时就是写写业务逻辑调调API用List、Dict存数据也没见自己手写过红黑树啊为什么面试总盯着这个考其实面试官想考察的并不是你会不会背诵“快速排序”的代码而是想看你是否具备解决复杂问题的思维。今天我就用一篇文章带你彻底搞懂数据结构与算法的底层逻辑。这篇文章可能有点长但相信我看完之后你再面对算法题时心里就有底了。一、数据结构不只是存数据的“容器”我们平时写Python张口就来list [1, 2, 3]或者dict {name: 老K}。但在计算机的世界里数据结构的定义远不止于此。1.1 什么是数据结构专业点说数据结构是为了高效访问数据而设计出的一种数据的组织和存储方式。它包含了三个要素数据元素的集合存了什么。数据元素之间的关系怎么组织的。访问和操作数据的方法怎么用的。你平时用的list、set、dict其实就是Python语言帮我们封装好的高级数据结构。它们已经帮你搞定了内存是怎么存的、元素是怎么找的这些问题。1.2 逻辑结构 vs. 物理结构这是分水岭很多新手搞不清楚为什么有了数组还要学链表这就要从“逻辑”和“物理”两个维度来看数据。1) 逻辑结构元素之间的“亲戚关系”逻辑结构是我们大脑里想象的数据关系主要分两种线性结构像一支队伍大家排成一排。除了队头和队尾每个人都知道自己前面是谁、后面是谁。典型代表数组、链表、栈、队列。非线性结构像公司的组织架构图树或者朋友圈的关系网图。一个元素可以有多个下级也可以和多个元素关联。2) 物理结构数据在内存里的“真实住址”这才是计算机真正干活的方式。内存就像一栋巨大的公寓楼每个房间都有一个门牌号内存地址。连续存储数组数据住在“连在一起的房间”里。特点找第3个人只要知道第1个人的房间号加上2个间隔就能直接找到寻址快。缺点如果想在中间插入一个人后面所有人都得挪位置增删慢。分散存储链表数据住在“随机分布的房间”里。特点每个房间里不仅住着人还放着一张纸条写着下一个人的房间号。缺点想找第3个人必须从第1个人开始按纸条挨个找过去寻址慢。优点想插入一个人只需要撕掉旧纸条写两张新纸条就行增删快。一个核心认知所有的数据结构都是基于数组连续和链表分散组合出来的。栈既可以用数组实现顺序栈也可以用链表实现链式栈。二、算法解决问题的“方法论”有了数据我们就要处理数据。算法就是处理数据的指令序列。2.1 算法的五大特性并不是所有写出来的代码都叫算法它必须满足五个条件输入0个或多个输入。输出至少1个输出没输出的代码是没意义的。有穷性不能死循环必须在有限的步骤内结束。确定性同样的输入走同样的路不能有歧义。可行性每一步都得是能执行的不能是“把大象放进冰箱”这种玄学。三、时间复杂度如何量化你的代码“快不快”这是面试中最常问的问题。当面试官问你“这个算法复杂度是多少”时他不是让你掐秒表而是在问你当数据量增大时你的代码会变慢多少3.1 什么是大O表示法我们不关心代码跑了1毫秒还是2毫秒因为机器配置不同。我们关心的是基本操作次数与数据规模n的关系。生活化类比假设你有一堆书n本书。找一本特定书二分查找随着书变多找书时间增长很慢O(log n)。数一共有多少本书遍历书多一倍时间也多一倍O(n)。给书两两配对比较大小冒泡排序书多一倍时间多四倍O(n²)。在数学上当n趋向无穷大时低阶项和常数项的影响可以忽略不计。所以我们只看最高阶。3.2 实战案例解析结合你提供的资料我们来看几个典型的复杂度这里融入了我自己的理解1. O(1) —— 常数阶pythondef add(a, b): return a b哪怕你写100行代码只要没有循环或者循环次数固定不依赖n它就是O(1)。这在算法界是“降维打击”级别的存在。2. O(log n) —— 对数阶python# 二分查找的核心 while left right: mid (left right) // 2 # ...这是我个人最欣赏的一种复杂度。它的增长曲线极其平缓。log n的增长速度肉眼几乎不可见。它的核心思想是“每轮缩减一半”。比如从10亿数据中找一个数最多只需要30次2^30 ≈ 10亿。3. O(n) —— 线性阶pythondef sum(nums): total 0 for num in nums: total num return total数据量翻倍时间翻倍。这是你能接受的底线。4. O(n log n) —— 线性对数阶这是排序算法归并排序、快速排序的最优天花板。它比O(n²)要快得多是工业级排序的基石。5. O(n²) —— 平方阶python# 冒泡排序、双层循环 for i in range(n): for j in range(n): # ...这是面试中需要警惕的“性能杀手”。如果面试题你用双重循环解出来了面试官通常会追问“能不能优化一下”6. O(2^n) 和 O(n!)—— 爆炸阶全排列、子集枚举属于这一类。这类算法通常只能处理n 20左右的数据量再大计算机就算到天荒地老了。3.3 关注最坏情况在分析算法时我们要有“底线思维”。比如查找最大值如果最大值就在第一位那可能一下就找到了最优情况但这没意义。我们关注的是最坏情况——最大值在最后一位我们得遍历全部。只有最坏时间复杂度才能给程序一个“一定能跑完”的保证。四、空间复杂度你的代码“占不占地方”以前内存很贵所以大家算法喜欢“以空间换时间”。现在虽然内存大了但如果你写的代码在手机或嵌入式设备上跑或者需要处理海量数据空间复杂度依然致命。空间复杂度统计的是额外的、临时占用的内存。O(1)原地修改。比如上面提到的反转数组只用了left和right两个指针不管数组多大就占这么点空间。O(n)新建了一个等大的数组或者像上面的has_duplicates最坏情况下把整个数组存进了set里。O(n²)新建了一个矩阵二维数组。特别提醒很多人在计算递归的空间复杂度时会犯错。递归函数本身会调用系统栈每一层递归都会占用空间。比如全排列的递归实现它的空间复杂度不仅仅是存储结果还包括递归调用的深度。总结与思考写到这里我们回顾一下今天的核心内容数据结构是骨架它决定了数据怎么存。逻辑结构线性/非线性是思想物理结构数组/链表是实体。数组和链表是所有高级数据结构的基石。算法是灵魂它决定了数据怎么处理。好的算法具备确定性、有穷性和可行性。复杂度是标尺时间复杂度看趋势大O表示法去掉常数和低阶项抓住主要矛盾。空间复杂度看额外开销不要忽视递归栈的占用。最后给想进阶的朋友一点建议不要死记硬背代码要去理解背后的逻辑。当你写代码时可以习惯性地问自己三个问题这个操作的数据量n是多少我写的这段代码是O(n)还是O(n²)如果数据量扩大100倍我的程序会不会卡死数据结构与算法本质上是一种工程思维。它训练的是你在有限的资源CPU时间、内存空间下如何做出最优解的能力。这种能力无论技术怎么迭代AI怎么发展都是程序员安身立命的根本。
面试官常问的“数据结构与算法”,到底在考什么?一文带你打通任督二脉
发布时间:2026/6/6 10:58:40
在程序员这个行当里流传着这样一句话“面试造火箭入职拧螺丝。”而“造火箭”的核心往往就是数据结构与算法。很多朋友刚入行时觉得我平时就是写写业务逻辑调调API用List、Dict存数据也没见自己手写过红黑树啊为什么面试总盯着这个考其实面试官想考察的并不是你会不会背诵“快速排序”的代码而是想看你是否具备解决复杂问题的思维。今天我就用一篇文章带你彻底搞懂数据结构与算法的底层逻辑。这篇文章可能有点长但相信我看完之后你再面对算法题时心里就有底了。一、数据结构不只是存数据的“容器”我们平时写Python张口就来list [1, 2, 3]或者dict {name: 老K}。但在计算机的世界里数据结构的定义远不止于此。1.1 什么是数据结构专业点说数据结构是为了高效访问数据而设计出的一种数据的组织和存储方式。它包含了三个要素数据元素的集合存了什么。数据元素之间的关系怎么组织的。访问和操作数据的方法怎么用的。你平时用的list、set、dict其实就是Python语言帮我们封装好的高级数据结构。它们已经帮你搞定了内存是怎么存的、元素是怎么找的这些问题。1.2 逻辑结构 vs. 物理结构这是分水岭很多新手搞不清楚为什么有了数组还要学链表这就要从“逻辑”和“物理”两个维度来看数据。1) 逻辑结构元素之间的“亲戚关系”逻辑结构是我们大脑里想象的数据关系主要分两种线性结构像一支队伍大家排成一排。除了队头和队尾每个人都知道自己前面是谁、后面是谁。典型代表数组、链表、栈、队列。非线性结构像公司的组织架构图树或者朋友圈的关系网图。一个元素可以有多个下级也可以和多个元素关联。2) 物理结构数据在内存里的“真实住址”这才是计算机真正干活的方式。内存就像一栋巨大的公寓楼每个房间都有一个门牌号内存地址。连续存储数组数据住在“连在一起的房间”里。特点找第3个人只要知道第1个人的房间号加上2个间隔就能直接找到寻址快。缺点如果想在中间插入一个人后面所有人都得挪位置增删慢。分散存储链表数据住在“随机分布的房间”里。特点每个房间里不仅住着人还放着一张纸条写着下一个人的房间号。缺点想找第3个人必须从第1个人开始按纸条挨个找过去寻址慢。优点想插入一个人只需要撕掉旧纸条写两张新纸条就行增删快。一个核心认知所有的数据结构都是基于数组连续和链表分散组合出来的。栈既可以用数组实现顺序栈也可以用链表实现链式栈。二、算法解决问题的“方法论”有了数据我们就要处理数据。算法就是处理数据的指令序列。2.1 算法的五大特性并不是所有写出来的代码都叫算法它必须满足五个条件输入0个或多个输入。输出至少1个输出没输出的代码是没意义的。有穷性不能死循环必须在有限的步骤内结束。确定性同样的输入走同样的路不能有歧义。可行性每一步都得是能执行的不能是“把大象放进冰箱”这种玄学。三、时间复杂度如何量化你的代码“快不快”这是面试中最常问的问题。当面试官问你“这个算法复杂度是多少”时他不是让你掐秒表而是在问你当数据量增大时你的代码会变慢多少3.1 什么是大O表示法我们不关心代码跑了1毫秒还是2毫秒因为机器配置不同。我们关心的是基本操作次数与数据规模n的关系。生活化类比假设你有一堆书n本书。找一本特定书二分查找随着书变多找书时间增长很慢O(log n)。数一共有多少本书遍历书多一倍时间也多一倍O(n)。给书两两配对比较大小冒泡排序书多一倍时间多四倍O(n²)。在数学上当n趋向无穷大时低阶项和常数项的影响可以忽略不计。所以我们只看最高阶。3.2 实战案例解析结合你提供的资料我们来看几个典型的复杂度这里融入了我自己的理解1. O(1) —— 常数阶pythondef add(a, b): return a b哪怕你写100行代码只要没有循环或者循环次数固定不依赖n它就是O(1)。这在算法界是“降维打击”级别的存在。2. O(log n) —— 对数阶python# 二分查找的核心 while left right: mid (left right) // 2 # ...这是我个人最欣赏的一种复杂度。它的增长曲线极其平缓。log n的增长速度肉眼几乎不可见。它的核心思想是“每轮缩减一半”。比如从10亿数据中找一个数最多只需要30次2^30 ≈ 10亿。3. O(n) —— 线性阶pythondef sum(nums): total 0 for num in nums: total num return total数据量翻倍时间翻倍。这是你能接受的底线。4. O(n log n) —— 线性对数阶这是排序算法归并排序、快速排序的最优天花板。它比O(n²)要快得多是工业级排序的基石。5. O(n²) —— 平方阶python# 冒泡排序、双层循环 for i in range(n): for j in range(n): # ...这是面试中需要警惕的“性能杀手”。如果面试题你用双重循环解出来了面试官通常会追问“能不能优化一下”6. O(2^n) 和 O(n!)—— 爆炸阶全排列、子集枚举属于这一类。这类算法通常只能处理n 20左右的数据量再大计算机就算到天荒地老了。3.3 关注最坏情况在分析算法时我们要有“底线思维”。比如查找最大值如果最大值就在第一位那可能一下就找到了最优情况但这没意义。我们关注的是最坏情况——最大值在最后一位我们得遍历全部。只有最坏时间复杂度才能给程序一个“一定能跑完”的保证。四、空间复杂度你的代码“占不占地方”以前内存很贵所以大家算法喜欢“以空间换时间”。现在虽然内存大了但如果你写的代码在手机或嵌入式设备上跑或者需要处理海量数据空间复杂度依然致命。空间复杂度统计的是额外的、临时占用的内存。O(1)原地修改。比如上面提到的反转数组只用了left和right两个指针不管数组多大就占这么点空间。O(n)新建了一个等大的数组或者像上面的has_duplicates最坏情况下把整个数组存进了set里。O(n²)新建了一个矩阵二维数组。特别提醒很多人在计算递归的空间复杂度时会犯错。递归函数本身会调用系统栈每一层递归都会占用空间。比如全排列的递归实现它的空间复杂度不仅仅是存储结果还包括递归调用的深度。总结与思考写到这里我们回顾一下今天的核心内容数据结构是骨架它决定了数据怎么存。逻辑结构线性/非线性是思想物理结构数组/链表是实体。数组和链表是所有高级数据结构的基石。算法是灵魂它决定了数据怎么处理。好的算法具备确定性、有穷性和可行性。复杂度是标尺时间复杂度看趋势大O表示法去掉常数和低阶项抓住主要矛盾。空间复杂度看额外开销不要忽视递归栈的占用。最后给想进阶的朋友一点建议不要死记硬背代码要去理解背后的逻辑。当你写代码时可以习惯性地问自己三个问题这个操作的数据量n是多少我写的这段代码是O(n)还是O(n²)如果数据量扩大100倍我的程序会不会卡死数据结构与算法本质上是一种工程思维。它训练的是你在有限的资源CPU时间、内存空间下如何做出最优解的能力。这种能力无论技术怎么迭代AI怎么发展都是程序员安身立命的根本。