Day1 时间复杂度

一 概念

在 C++ 中,时间复杂度是衡量算法运行时间随输入规模增长的趋势的关键指标,用于评估算法的效率。它通过 大 O 表示法(Big O Notation) 描述,关注的是输入规模 n 趋近于无穷大时,算法时间增长的主导因素(忽略常数和低阶项)。

  • 输入规模(n):算法处理的数据量(如数组长度、链表节点数、矩阵维度等)。
  • 大 O 表示法:表示算法时间复杂度的上界,例如 O(n) 表示时间与输入规模 n 成线性关系。
  • 核心原则:只保留最高阶项,忽略常数因子和低阶项(如 O(2n + 3) 简化为 O(n)O(n² + n) 简化为 O(n²))。

二 常见时间复杂度类型 

1.O (1):常数时间

无论输入规模多大,算法执行时间恒定(与 n 无关)。

典型场景:

  • 数组 /vector 的随机访问(通过下标 [i])。
  • 哈希表(unordered_map)的插入、查找(平均情况)。

示例:访问数组元素 

#include <vector>int get_element(const std::vector<int>& vec, int index) {return vec[index];  // 随机访问,时间复杂度 O(1)
}

2. O (n):线性时间

时间与输入规模 n 成正比,需逐个处理每个元素。
典型场景

  • 线性枚举(遍历数组、链表等)。
  • 未排序数组的顺序查找。

示例:遍历 vector 求和

#include <vector>int sum_vector(const std::vector<int>& vec) {int sum = 0;for (int num : vec) {  // 遍历所有元素,时间复杂度 O(n)sum += num;}return sum;
}

3. O (logn):对数时间

时间随输入规模的对数增长,通常出现在分治算法中(如二分查找)。
典型场景

  • 有序数组的二分查找(std::lower_bound)。
  • 平衡二叉搜索树(如 std::setstd::map)的插入、查找。

示例:二分查找(C++ 标准库实现)

#include <vector>
#include <algorithm>  // for std::lower_bound// 查找目标值的位置(返回迭代器)
auto binary_search(const std::vector<int>& vec, int target) {return std::lower_bound(vec.begin(), vec.end(), target);// 时间复杂度 O(logn)(数组已排序)
}

4. O (nlogn):线性对数时间

时间增长趋势为 n × logn,常见于高效的排序算法。
典型场景

  • 快速排序、归并排序(平均情况)。
  • std::sort(C++ 标准库排序,基于快速排序 / 堆排序)。

示例:使用 std::sort 排序

#include <vector>
#include <algorithm>void sort_vector(std::vector<int>& vec) {std::sort(vec.begin(), vec.end());  // 平均时间复杂度 O(nlogn)
}

5.O (n²):平方时间

时间与输入规模的平方成正比,常见于双重循环的暴力算法。
典型场景

  • 冒泡排序、选择排序(最坏 / 平均情况)。
  • 二维数组的遍历(如矩阵元素逐个处理)。

示例:冒泡排序

#include <vector>void bubble_sort(std::vector<int>& vec) {int n = vec.size();for (int i = 0; i < n - 1; ++i) {for (int j = 0; j < n - i - 1; ++j) {  // 双重循环,时间复杂度 O(n²)if (vec[j] > vec[j + 1]) {std::swap(vec[j], vec[j + 1]);}}}
}

6. 其他复杂度

  • O(2ⁿ):指数时间(如斐波那契数列的递归实现,存在大量重复计算)。
  • O(n!):阶乘时间(如全排列生成)。

三、时间复杂度的分析方法 

1. 单循环:O (n)

单个循环遍历 n 次,时间复杂度为 O(n)

for (int i = 0; i < n; ++i) {// 操作(时间复杂度 O(1))
}
// 总时间复杂度:O(n)

2. 双重循环:O (n²)

外层循环 n 次,内层循环 n 次,总次数为 n × n = n²

for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {// 操作(O(1))}
}
// 总时间复杂度:O(n²)

当外层循环到第 i 次时,内层循环 i 次,总次数为 (1 + n)n / 2 = (n + n^2) / 2次。

for (int i = 0; i < n; ++i) {for (int j = 0; j <= i; ++j) {//操作(O(1))}
}
/*  i  0  1  2  3  ...  n-1j  1  1  2  3  ...  n总操作次数为等差数列:(1 + n)n / 2 = (n + n^2) / 2只保留最高阶项,忽略常数因子和低阶项,故时间复杂度O(n^2)
*/

3. 对数循环:O (logn)

每次循环将问题规模减半(如二分查找)。

int i = 1;
while (i < n) {i *= 2;  // 每次规模翻倍
}
// 循环次数为 log₂n,时间复杂度 O(logn)
int i = n * n;
while (i != 1) {i /= 2; //每次规模减少为原来的一半
}/*
t(操作次数) 0       1           2            3     ...
i          n^2   n^2 / 2     n^2 / 4      n^2 / 8  ...由上面规律可得:i = n^2 / 2^t
将该表达式与 i = 1 联立
得 t = 2log2(n)
所以时间复杂度为 O(log2(n)),记为 O(logn)
*/

4. 递归的时间复杂度

递归的时间复杂度需结合递归深度每层操作次数
示例:斐波那契数列的递归实现(低效版)

int fib(int n) {if (n <= 1) return n;return fib(n - 1) + fib(n - 2);  // 每次递归分裂为 2 个子问题
}
// 时间复杂度:O(2ⁿ)(存在大量重复计算)

四、时间复杂度的优化策略

1. 用哈希表优化查找(O (n) → O (1))

将线性查找(O (n))替换为哈希表(unordered_map)的键值查找(O (1)),以空间换时间。

示例:两数之和。在数组中找到两个元素值等于target,返回这两个元素组成的数组。

#include <vector>
#include <unordered_map>std::vector<int> two_sum(const std::vector<int>& nums, int target) {std::unordered_map<int, int> hash;  // 哈希表存储值→索引for (int i = 0; i < nums.size(); ++i) {int complement = target - nums[i];if (hash.count(complement)) {  // 查找时间 O(1)return {hash[complement], i};}hash[nums[i]] = i;  // 插入时间 O(1)}return {};
}
// 原暴力解法时间复杂度 O(n²),优化后 O(n)

2. 用排序 + 二分查找优化(O (n²) → O (nlogn))

将双重循环的暴力匹配替换为排序后二分查找。
示例:查找数组中是否存在两数之和为目标值

#include <vector>
#include <algorithm>bool has_two_sum(std::vector<int>& nums, int target) {std::sort(nums.begin(), nums.end());  // 排序 O(nlogn)for (int num : nums) {int complement = target - num;// 二分查找 complement,时间 O(logn)if (std::binary_search(nums.begin(), nums.end(), complement)) {return true;}}return false;
}
// 原暴力解法 O(n²),优化后 O(nlogn)

3. 避免重复计算(O (2ⁿ) → O (n))

通过动态规划或记忆化搜索,消除递归中的重复子问题。
示例:斐波那契数列的动态规划实现

#include <vector>int fib(int n) {if (n <= 1) return n;std::vector<int> dp(n + 1);  // 存储已计算的结果dp[0] = 0;dp[1] = 1;for (int i = 2; i <= n; ++i) {dp[i] = dp[i - 1] + dp[i - 2];  // 避免重复计算,时间 O(n)}return dp[n];
}
// 原递归解法 O(2ⁿ),优化后 O(n)

五 总结

时间复杂度反映算法运行时间随输入规模增长的趋势,不同复杂度的增长速度从低到高排列如下:

O(1) < O(logn) < O(n) < O(nlogn) < O(n²)

时间复杂度是评估算法效率的核心指标。在 C++ 中,通过分析循环嵌套、递归深度或操作次数,可以确定算法的时间复杂度。实际编码时,应优先选择低时间复杂度的算法(如 O (nlogn) 优于 O (n²)),并利用哈希表、排序 + 二分等优化手段降低复杂度。同时,结合数据结构的特性(如unordered_map的 O (1) 查找),可以显著提升程序性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/905344.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/905344.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PAC文件:智能代理配置的瑞士军刀

在日常上网和企业网络环境中&#xff0c;我们经常需要配置代理服务器来访问特定资源、增强安全性或管理网络流量。Windows和macOS系统自带的代理配置通常提供全局代理或简单的排除列表&#xff0c;这在某些复杂场景下显得不够灵活。例如&#xff0c;我们可能只想代理某个特定的…

获取高德地图JS API的安全密钥和Key的方法

要使用高德地图JavaScript API&#xff0c;您需要获取API Key和安全密钥(securityJsCode)。以下是获取步骤&#xff1a; 1. 注册高德开放平台账号 首先访问高德开放平台&#xff0c;如果没有账号需要先注册。 2. 创建应用获取Key 登录后进入"控制台" 点击"应…

携程酒店 phantom-token token1004 分析

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 部分python代码 搞APP搞的心态有点崩…

小红书多账号运营效率优化:技术方案与自动化实践

目录 一、效率瓶颈与流程优化方向 二、技术实现方案与效率提升路径 1. 多账号统一管理&#xff1a;环境隔离与批量操作 2. 自动化任务设计&#xff1a;RPA与脚本化执行 四、效果验证与数据对比 五、总结与开源工具推荐 六、下载地址&#xff1a; 一、效率瓶颈与流程优化…

FastDDS Transport功能模块初步整理

一. 总体结构 二. 主要类的功能 2.1 TransportDescriptor和TransportInterface ​ FastDDS中整个Transport类的设计遵循的是设计模式中的建造者模式&#xff0c;其中&#xff0c;TransportDescriptor就是建造者&#xff0c;而TransportInterface则是建造出来的产品。 ​ Tra…

zabbix最新版本7.2超级详细安装部署(一)

如果文章对你有用&#xff0c;请留下痕迹在配置过程中有问题请及时留言&#xff0c;本作者可以及时更新文章 目录 1、提前准备环境 2、zabbix7.2安装部署 3、安装并配置数据库 4、为Zabbix server配置数据库 5、为Zabbix前端配置PHP 6、启动Zabbix server和agent进程 7、关闭防…

CodeBlocks调试报错

尝试打断点&#xff0c;并且点击红色箭头启动debugger时&#xff0c;控制台报错 Active debugger config: GDB/CDB debugger:Default Building to ensure sources are up-to-date Selecting target: Debug Adding source dir: C:\Users\Lenovo\Desktop\exercise\ Adding source…

Manus 开放注册:AI 智能体领域的新起点

2025 年 5 月 13 日成为了一个具有特殊意义的日子 —— 备受瞩目的 AI 智能体平台 Manus&#xff08;Manus&#xff09;正式宣布开放注册。这一消息犹如一颗重磅炸弹&#xff0c;瞬间在全球科技圈引起了广泛关注和热烈讨论。在此之前&#xff0c;Manus 一直以其独特的魅力和极高…

车载网关作为车辆网络系统的核心枢纽

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 钝感力的“钝”&#xff0c;不是木讷、迟钝&#xff0c;而是直面困境的韧劲和耐力&#xff0c;是面对外界…

俄罗斯方块算法2025.5.10

问题描述 俄罗斯方块&#xff08;Tetris&#xff09;作为风靡全球38年的现象级益智游戏&#xff0c;其简单易学但难于精通的特性使其成为游戏史上的不朽经典。以下是其核心游戏规则解析及我们的要求&#xff1a; 游戏界面由20行10列的可视区域组成&#xff0c;7种不同形状的四…

Femap许可网络配置

电磁仿真领域&#xff0c;Femap以其卓越的性能和广泛的应用场景&#xff0c;成为众多工程师和科研人员的首选工具。为了满足多用户协作的需求&#xff0c;Femap提供了灵活的网络配置方案。本文将详细介绍Femap许可网络配置的方法和优势&#xff0c;帮助您轻松实现多用户高效协作…

计算机视觉----时域频域在图像中的意义、傅里叶变换在图像中的应用、卷积核的频域解释

1、时域&#xff08;时间域&#xff09;——自变量是时间,即横轴是时间,纵轴是信号的变化。其动态信号x&#xff08;t&#xff09;是描述信号在不同时刻取值的函数。 2、频域&#xff08;频率域&#xff09;——自变量是频率,即横轴是频率,纵轴是该频率信号的幅度,也就是通常说…

主流高防服务器技术对比与AI防御方案实战

1. 高防服务器核心能力对比 当前市场主流高防服务商&#xff08;如阿里云、腾讯云、华为云&#xff09;的核心防御能力集中在流量清洗与静态规则防护&#xff0c;但面临以下挑战&#xff1a; 静态防御瓶颈&#xff1a;传统方案依赖预定义规则&#xff0c;对新型攻击&#xff…

常时间运行的程序 导致系统卡顿 自动监控系统CPU和内存利用率 自动选择 内存回收 软件重启 电脑重启

长时间运行安防系统&#xff0c;导致CPU或内存利用率超80%&#xff0c;使得电脑变的缓慢、卡顿的问题。定时获取CPU和内存利用率的数据&#xff0c;在不同时间段&#xff08;如凌晨与平时&#xff09;&#xff0c;根据利用率的不同的阈值&#xff0c;进行&#xff1a;内存回收(…

OpenCV播放摄像头视频

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 播放摄像头视频和播放视频文件类似&#xff0c;也是通过类VideoCapture来实现&#xff0c;只不过调用open的时候传入的是摄像头的索引号。如果计算机安装了一个摄像头&#xff0c;则open的第一个参数通常是0&…

操作系统:内存管理

目录 1、主要目标 2、核心概念和技术 2.1 物理内存与虚拟内存 2.2 内存分页机制 2.3 页面置换算法 3、监控与性能优化 3.1 查看物理内存 3.2 查看虚拟内存 3.3 性能问题 1> 内存不足&#xff08;OOM&#xff09; 2> 内存泄漏 3> 内存碎片 3.4 性能优化策…

专题四:综合练习( 找出所有子集的异或总和再求和)

以leetcode1863题为例 题目分析&#xff1a; 找到每个子集&#xff0c;然后子集中的元素异或之后全部相加 算法原理分析&#xff1a; 画决策树&#xff1a;第一层为这个子集有一个元素 第二层这个子集有两个元素 从上往下罗列&#xff0c;把所有子集都罗列出来&#xf…

【python】—conda新建python3.11的环境报错

1.报错 conda create -n py3.11 python3.11 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ Collecting package metadata: done Solving environment: failed PackagesNotFoundError: The following packages are not available from current channel…

RabbitMQ事务机制

在RabbitMQ中&#xff0c;生产者为了确保消息发送成功&#xff0c;一种是使用 confirm 确认机制&#xff0c;另一种就是使用事务机制&#xff0c;事务机制就是允许生产者在发送消息时&#xff0c;将多个消息操作作为一个原子单元进行处理&#xff0c;要么所有操作都成功执行&am…

两台笔记本电脑直接通过HDMI线连接?

两台笔记本电脑直接通过HDMI线连接通常无法实现屏幕共享或数据传输&#xff0c;因为HDMI接口设计主要用于单向音视频输出(如连接显示器或电视)。以下是详细分析和替代方案&#xff1a; 为什么HDMI直连两台电脑不适用&#xff1f; 接口功能限制&#xff1a;• 大多数笔记本电脑的…