漫画:什么是时间复杂度?
一、引言时间复杂度的意义时间复杂度的意义究竟什么是时间复杂度呢让我们来想象一个场景某一天小灰和大黄同时加入了一个公司......一天过后小灰和大黄各自交付了代码两端代码实现的功能都差不多。大黄的代码运行一次要花100毫秒内存占用5MB。小灰的代码运行一次要花100秒内存占用500MB。于是......由此可见衡量代码的好坏包括两个非常重要的指标运行时间占用空间。二、基本操作执行次数四个生活场景比喻基本操作执行次数关于代码的基本操作执行次数我们用四个生活中的场景来做一下比喻场景1线性增长场景1给小灰一条长10寸的面包小灰每3天吃掉1寸那么吃掉整个面包需要几天答案自然是 3 × 10 30天。如果面包的长度是 N 寸呢此时吃掉整个面包需要 3 × n 3n 天。如果用一个函数来表达这个相对时间可以记作 T(n) 3n。场景2对数增长场景2给小灰一条长16寸的面包小灰每5天吃掉面包剩余长度的一半第一次吃掉8寸第二次吃掉4寸第三次吃掉2寸......那么小灰把面包吃得只剩下1寸需要多少天呢这个问题翻译一下就是数字16不断地除以2除几次以后的结果等于1这里要涉及到数学当中的对数以2为底16的对数可以简写为log₂16。因此把面包吃得只剩下1寸需要 5 × log₂16 5 × 4 20 天。如果面包的长度是 N 寸呢需要 5 × log₂n 5log₂n天记作 T(n) 5log₂n。场景3常数时间场景3给小灰一条长10寸的面包和一个鸡腿小灰每2天吃掉一个鸡腿。那么小灰吃掉整个鸡腿需要多少天呢答案自然是2天。因为只说是吃掉鸡腿和10寸的面包没有关系。如果面包的长度是 N 寸呢无论面包有多长吃掉鸡腿的时间仍然是2天记作 T(n) 2。场景4平方增长场景4给小灰一条长10寸的面包小灰吃掉第一个一寸需要1天时间吃掉第二个一寸需要2天时间吃掉第三个一寸需要3天时间.....每多吃一寸所花的时间也多一天。那么小灰吃掉整个面包需要多少天呢答案是从1累加到10的总和也就是55天。如果面包的长度是 N 寸呢此时吃掉整个面包需要 123...... n-1 n (1n)×n/2 0.5n² 0.5n。记作 T(n) 0.5n² 0.5n。三、从生活场景到代码实现上面所讲的是吃东西所花费的相对时间这一思想同样适用于对程序基本操作执行次数的统计。刚才的四个场景分别对应了程序中最常见的四种执行方式场景1线性执行场景1T(n) 3n执行次数是线性的。void eat1(int n) { for (int i 0; i n; i) { System.out.println(等待一天); System.out.println(等待一天); System.out.println(吃一寸面包); } }场景2对数执行场景2T(n) 5log₂n执行次数是对数的。void eat2(int n) { for (int i 1; i n; i * 2) { System.out.println(等待一天); System.out.println(等待一天); System.out.println(等待一天); System.out.println(等待一天); System.out.println(吃一半面包); } }场景3常数执行场景3T(n) 2执行次数是常量的。void eat3(int n) { System.out.println(等待一天); System.out.println(吃一个鸡腿); }场景4平方执行场景4T(n) 0.5n² 0.5n执行次数是一个多项式。void eat4(int n) { for (int i 0; i n; i) { for (int j 0; j i; j) { System.out.println(等待一天); } System.out.println(吃一寸面包); } }四、渐进时间复杂度大O表示法渐进时间复杂度有了基本操作执行次数的函数 T(n)是否就可以分析和比较一段代码的运行时间了呢还是有一定的困难。比如算法A的相对时间是T(n) 100n算法B的相对时间是T(n) 5n²这两个到底谁的运行时间更长一些这就要看n的取值了。所以这时候有了渐进时间复杂度asymptotic time complexity的概念官方的定义如下若存在函数 f(n)使得当n趋近于无穷大时T(n) / f(n)的极限值为不等于零的常数则称 f(n) 是 T(n) 的同数量级函数。记作 T(n) O(f(n))称 O(f(n)) 为算法的渐进时间复杂度简称时间复杂度。渐进时间复杂度用大写O来表示所以也被称为大O表示法。大O表示法的推导原则如何推导出时间复杂度呢有如下几个原则如果运行时间是常数量级用常数1表示只保留时间函数中的最高阶项如果最高阶项存在则省去最高阶项前面的系数。四个场景的时间复杂度推导让我们回头看看刚才的四个场景。场景1线性时间复杂度场景1T(n) 3n最高阶项为3n省去系数3转化的时间复杂度为T(n) O(n)场景2对数时间复杂度场景2T(n) 5log₂n最高阶项为5log₂n省去系数5转化的时间复杂度为T(n) O(log n)场景3常数时间复杂度场景3T(n) 2只有常数量级转化的时间复杂度为T(n) O(1)场景4平方时间复杂度场景4T(n) 0.5n² 0.5n最高阶项为0.5n²省去系数0.5转化的时间复杂度为T(n) O(n²)时间复杂度比较这四种时间复杂度究竟谁用时更长谁节省时间呢稍微思考一下就可以得出结论O(1) O(log n) O(n) O(n²)在编程的世界中有着各种各样的算法除了上述的四个场景还有许多不同形式的时间复杂度比如O(n log n), O(n³), O(m×n), O(2ⁿ), O(n!)今后遨游在代码的海洋里我们会陆续遇到上述时间复杂度的算法。五、时间复杂度的巨大差异时间复杂度的巨大差异我们来举一个例子算法A的相对时间规模是T(n) 100n时间复杂度是O(n)算法B的相对时间规模是T(n) 5n²时间复杂度是O(n²)算法A运行在小灰家里的老旧电脑上算法B运行在某台超级计算机上运行速度是老旧电脑的100倍。那么随着输入规模 n 的增长两种算法谁运行更快呢从表格中可以看出当n的值很小的时候算法A的运行用时要远大于算法B当n的值达到1000左右算法A和算法B的运行时间已经接近当n的值越来越大达到十万、百万时算法A的优势开始显现算法B则越来越慢差距越来越明显。这就是不同时间复杂度带来的差距。六、常见算法的时间复杂度理解了时间复杂度的基本概念和四种常见增长模式后让我们看看这些模式在实际算法中的应用。以下是几种常见算法及其对应的时间复杂度1. 二分查找Binary Search时间复杂度O(log n)对应增长模式对数增长场景2二分查找是一种在有序数组中查找特定元素的算法。每次比较都将搜索范围减半因此时间复杂度为对数级。int binarySearch(int[] arr, int target) { int left 0, right arr.length - 1; while (left right) { int mid left (right - left) / 2; if (arr[mid] target) return mid; if (arr[mid] target) left mid 1; else right mid - 1; } return -1; }2. 冒泡排序Bubble Sort时间复杂度O(n²)对应增长模式平方增长场景4冒泡排序通过重复遍历列表比较相邻元素并交换位置将最大元素逐步冒泡到末尾。需要两层嵌套循环时间复杂度为平方级。void bubbleSort(int[] arr) { int n arr.length; for (int i 0; i n - 1; i) { for (int j 0; j n - i - 1; j) { if (arr[j] arr[j 1]) { int temp arr[j]; arr[j] arr[j 1]; arr[j 1] temp; } } } }3. 快速排序Quick Sort平均时间复杂度O(n log n)对应增长模式线性对数增长文中提到的 O(n log n)快速排序采用分治策略选择一个基准元素将数组分为两部分递归排序。平均情况下时间复杂度为 O(n log n)。void quickSort(int[] arr, int low, int high) { if (low high) { int pi partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi 1, high); } } int partition(int[] arr, int low, int high) { int pivot arr[high]; int i low - 1; for (int j low; j high; j) { if (arr[j] pivot) { i; int temp arr[i]; arr[i] arr[j]; arr[j] temp; } } int temp arr[i 1]; arr[i 1] arr[high]; arr[high] temp; return i 1; }4. 斐波那契数列递归Fibonacci Recursive时间复杂度O(2ⁿ)对应增长模式指数增长文中提到的 O(2ⁿ)递归计算斐波那契数列会产生指数级的时间复杂度因为存在大量重复计算。int fibonacci(int n) { if (n 1) return n; return fibonacci(n - 1) fibonacci(n - 2); }5. 数组访问Array Access时间复杂度O(1)对应增长模式常数时间场景3通过索引直接访问数组元素无论数组多大访问时间都是常数。int getElement(int[] arr, int index) { return arr[index]; // O(1) 操作 }6. 线性搜索Linear Search时间复杂度O(n)对应增长模式线性增长场景1遍历数组中的每个元素直到找到目标或遍历完所有元素。int linearSearch(int[] arr, int target) { for (int i 0; i arr.length; i) { if (arr[i] target) return i; } return -1; }通过以上示例可以看出不同算法的时间复杂度对应着我们在前面讨论的不同增长模式。理解这些模式有助于我们在实际编程中选择合适的算法优化程序性能。

相关新闻

《深入理解java虚拟机》第1章:从零开始编译 OpenJDK 7 源码

《深入理解java虚拟机》第1章:从零开始编译 OpenJDK 7 源码

1.6 实战:自己编译 JDK 想要一探 JDK 内部的实现机制,最便捷的路径之一就是自己编译一套 JDK,通过阅读和跟踪调试 JDK 源码去了解 Java 技术体系的原理,虽然门槛会高一点,但肯定会比阅读各种书籍、文章更加贴近本质。…

2026/10/10 17:43:32 阅读更多 →
如何在Windows上实现专业级三指拖拽体验:完整配置指南

如何在Windows上实现专业级三指拖拽体验:完整配置指南

如何在Windows上实现专业级三指拖拽体验:完整配置指南 【免费下载链接】ThreeFingersDragOnWindows Enables macOS-style three-finger dragging functionality on Windows Precision touchpads. 项目地址: https://gitcode.com/gh_mirrors/th/ThreeFingersDragOn…

2026/10/10 17:43:53 阅读更多 →
Unity游戏开发中Excel数据读取的完整方案与优化技巧

Unity游戏开发中Excel数据读取的完整方案与优化技巧

1. Unity中Excel数据读取的完整方案解析 在游戏开发中,Excel表格因其直观的界面和强大的数据处理能力,常被用作游戏配置数据的载体。Unity项目需要频繁读取Excel数据来驱动游戏逻辑,但原生并不直接支持Excel文件操作。本文将分享我在多个商业…

2026/10/11 22:23:41 阅读更多 →

最新新闻

德思特 GNSS 模拟器技术参数详解:700+通道、1000Hz 迭代率、可模拟1200颗卫星的全星座仿真方案

德思特 GNSS 模拟器技术参数详解:700+通道、1000Hz 迭代率、可模拟1200颗卫星的全星座仿真方案

在高阶自动驾驶 HiL 闭环、低空无人系统及高动态 PNT(定位、导航、定时)测试中,传统户外路测往往受环境干扰大且场景难以 100% 复现。针对工程选型关注的核心参数与信号支持能力,德思特 GNSS 模拟器基于 Skydel 引擎与 SDA 软件定…

2026/10/11 22:52:37 阅读更多 →
vnpy量化实战:多因子选股+LightGBM动态仓位优化闭环

vnpy量化实战:多因子选股+LightGBM动态仓位优化闭环

简介:本资源是一套基于vn.py框架深度二次开发的量化投资实践项目,面向金融工程开发者、量化交易学习者及AI金融交叉领域从业者,解决选股自动化、策略回测工程化与机器学习模型集成等核心问题。压缩包共1656个文件,体量59.07MB&…

2026/10/11 22:52:37 阅读更多 →
vllm-metal 加载 GGUF 量化模型完整指南:Mac 本地部署 LLM 的省钱秘籍

vllm-metal 加载 GGUF 量化模型完整指南:Mac 本地部署 LLM 的省钱秘籍

【免费下载链接】vllm-metal Community maintained hardware plugin for vLLM on Apple Silicon 项目地址: https://gitcode.com/gh_mirrors/vl/vllm-metal 点击查看 免费下载 vllm-metal 是一个社区维护的硬件插件,让 vLLM 能够运行在 Apple Silicon&a…

2026/10/11 22:52:37 阅读更多 →
家电维修预约欧米到家|博世洗衣机维修预约|附近师傅上门检修|欧米到家报修热线

家电维修预约欧米到家|博世洗衣机维修预约|附近师傅上门检修|欧米到家报修热线

前言🌆 国内住宅业态丰富,各地老城老旧管网老化、水质杂质多,城市高层住宅水压波动频繁,全国大部分地区属于湿润气候,梅雨季、多雨季节潮湿多雨、空气湿度极高,冬夏温差大,差异化的居家工况让洗…

2026/10/11 22:52:37 阅读更多 →
构网型储能变流器参数整定:虚拟惯量、阻尼与下垂系数实战解析

构网型储能变流器参数整定:虚拟惯量、阻尼与下垂系数实战解析

最近在调试一个构网型储能样机,100kW 的柜子在离网工况下带 RLC 负载,光是 J 和 D 两个参数就调了两个晚上。功率波形要么像水面波纹一样持续荡漾,要么频率响应慢到让人怀疑控制器死机。后来我才意识到,构网型变流器能不能真正工程…

2026/10/11 22:52:37 阅读更多 →
MySQL子查询完全指南:分类、执行流程、性能优化与常见坑

MySQL子查询完全指南:分类、执行流程、性能优化与常见坑

子查询在MySQL里被很多人当成"会用但说不清"的技术点。SQL子查询用得好,能把复杂统计拆成清晰的嵌套逻辑;用不好,一条慢查询直接拖垮业务接口。这篇文章我把子查询从分类、执行流程到性能优化、报错排查完整过一遍,所有…

2026/10/11 22:51:36 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →