当前位置: 首页 > news >正文

【算法竞赛学习笔记】基础概念篇:算法复杂度

前言

本文为个人学习的算法学习笔记,学习笔记,学习笔记不是经验分享与教学,不是经验分享与教学,不是经验分享与教学,若有错误各位大佬轻喷(T^T)。主要使用编程语言为Python3,各类资料题目源于网络,主要自学途径为蓝桥云课,侵权即删。

一、算法复杂度概述

算法复杂度是衡量算法效率的核心指标,主要分为两类:

  • 时间复杂度:衡量算法执行时间随数据规模增长的变化趋势(关注 “快不快”)
  • 空间复杂度:衡量算法占用的额外存储空间随数据规模增长的变化趋势(关注 “省不省空间”)

复杂度分析不依赖具体硬件 / 语言,仅关注 “数据规模” 与 “资源消耗” 的关系,是评估算法优劣的通用标准。

二、时间复杂度

2.1 定义

时间复杂度(渐进时间复杂度)表示算法执行次数(或时间)随数据规模 n 增长的趋势,而非实际执行时间。核心思想:当 n 足够大时,公式中的低阶项、常量、系数对增长趋势影响极小,可忽略,仅保留 “最大量级”。

示例:从代码到时间复杂度

文档中两个经典代码案例的 Python 实现与分析:

  1. 单循环(线性级)
def sum_arr(arr):sum_val = 0  # 1次(常量)for i in range(len(arr)):  # 初始化1次,循环n次 → 共n+1次sum_val = sum_val + arr[i]  # n次return sum_val  # 1次(常量)
  • 总执行次数:1 + (n+1) + n + 1 = 2n + 3
  • 忽略低阶项(3)和系数(2),时间复杂度为 O(n)(线性级)
  1. 双循环(平方级)
def sum_double_loop(arr):sum_val = 0  # 1次(常量)for i in range(len(arr)):  # 外层循环:n+1次for j in range(len(arr)):  # 内层循环:n*(n+1)次sum_val = sum_val + arr[i] + arr[j]  # n²次return sum_val  # 1次(常量)
  • 总执行次数:1 + (n+1) + n*(n+1) + n² + 1 = 2n² + 2n + 3
  • 忽略低阶项(2n+3)和系数(2),时间复杂度为 O(n²)(平方级)

2.2 常见时间复杂度及示例

不同复杂度的增长速度差异极大,下表整理了核心类型及 Python 典型场景:

复杂度描述增长速度典型示例
O(1)常数级最快(无增长)基本运算(加减乘除)、固定次数循环(如循环 1000 次,与 n 无关)
O(log n)对数级很慢二分查找、while 循环中变量 “倍增 / 倍减”(如 i=i*2,直到 i>n)
O(n)线性级较慢单循环(遍历列表、顺序查找)
O(n log n)线性对数级中等高效排序算法(Python 内置 sorted ()、归并排序)
O(n²)平方级较快双重循环(如冒泡排序、求 “和谐对” 问题的暴力解法)
O(n³)立方级很快三重循环(如三维列表遍历、矩阵多重乘法)
O(2ⁿ)指数级极快暴力递归解决子集问题(如 n 个元素的所有子集,共 2ⁿ个)
O(n!)阶乘级最快(不可接受)暴力解决全排列问题(如 n 个元素的所有排列,共 n! 种)
关键示例详解
  1. O (1):常数级无论数据规模 n 多大,执行次数固定:
def constant_sum(n):sum_val = 0for i in range(10000):  # 固定10000次,与n无关sum_val += ireturn sum_val
  • 额外执行次数不随 n 变化,时间复杂度为 O(1)
  1. O (log n):对数级核心特征:循环次数随 n 增长,但增长速度是 “对数级”(底数可忽略,因 log₂n 与 log₃n 仅差系数):
def log_n_example(n):i = 1count = 0while i <= n:  # 循环次数k满足2ᵏ > n → k≈log₂ni *= 2count += 1return count
  • 当 n=8 时,循环 4 次(1→2→4→8→16),log₂8=3,量级为 log n;
  • 当 n=10²⁴时,循环仅约 80 次,远快于 O (n)

2.3 复杂度增长速度对比

不同复杂度的差距随 n 增大呈指数级扩大,以 n=20 为例:

复杂度n=20 时的执行次数量级能否接受
O(1)1完全接受
O(log n)~5完全接受
O(n)20完全接受
O(n log n)~100完全接受
O(n²)400接受
O(2ⁿ)~100 万勉强接受
O(n!)~2.4×10¹⁸完全不可接受

结论:O (2ⁿ) 和 O (n!) 仅适用于 n≤20 的极小数据,工程中优先选择 O (n log n) 及更优复杂度的算法

2.4 最好、最坏、平均时间复杂度

当算法执行次数受 “输入数据分布” 影响时,需区分三种复杂度(大多数情况无需区分,仅当复杂度有量级差距时需关注)。

示例:列表查找元素
# 在列表arr中查找x,返回索引(未找到返回-1)
def find_element(arr, n, x):pos = -1for i in range(n):if arr[i] == x:pos = ibreak  # 找到后立即退出return pos
  1. 最好时间复杂度:最理想情况的执行次数若 x 是列表第一个元素(arr [0]=x),循环仅执行 1 次 → O(1)

  2. 最坏时间复杂度:最糟糕情况的执行次数若 x 是列表最后一个元素,或 x 不存在,循环执行 n 次 → O(n)

  3. 平均时间复杂度:所有可能输入的执行次数的平均值假设 x 在列表中每个位置的概率为 1/n,且 x 不存在的概率为 1/2:

    • 存在时:平均执行次数 = (1+2+...+n)/n = (n+1)/2
    • 不存在时:执行次数 = n
    • 总平均:(1/2)×(n+1)/2 + (1/2)×n = (3n+1)/4 → 忽略系数和低阶项,O(n)

2.5 时间复杂度分析原则

1. 最大循环原则(主导项原则)

算法的整体复杂度由 “执行次数最多的部分” 决定,忽略次要部分。示例:

def dominant_loop(n):# 1. 循环100次(O(1),次要)sum1 = 0for p in range(1, 101):sum1 += p# 2. 循环n次(O(n),次要)sum2 = 0for q in range(1, n):sum2 += q# 3. 双重循环n²次(O(n²),主导)sum3 = 0for i in range(1, n+1):for j in range(1, n+1):sum3 += i * jreturn sum1 + sum2 + sum3
  • 主导项是 O (n²),整体复杂度为 O(n²)
2. 加法原则(独立操作叠加)

若算法由多个 “独立” 部分组成(无嵌套),总复杂度为各部分复杂度的最大值(而非求和)。公式:若 T1 (n)=O (f (n)),T2 (n)=O (g (n)),则 T (n)=T1 (n)+T2 (n)=O (max (f (n),g (n)))。

示例:

def add_principle(n_arr, m_arr):# 部分1:遍历n_arr(O(n))sum_val = 0for num in n_arr:sum_val += num# 部分2:遍历m_arr(O(m))for num in m_arr:sum_val += numreturn sum_val
  • 总复杂度为 O(max(len(n_arr), len(m_arr)))(若两列表长度相近,可简化为 O (n))
3. 乘法原则(嵌套操作叠加)

若算法存在 “嵌套” 操作(如循环内调用另一个算法),总复杂度为各部分复杂度的乘积。公式:若 T1 (n)=O (f (n)),T2 (n)=O (g (n)),则 T (n)=T1 (n)×T2 (n)=O (f (n)×g (n))。

示例:

# 内层函数:O(k)(k为输入参数,此处k≤n)
def inner_func(k):sum_val = 0for i in range(1, k):sum_val += ireturn sum_val# 外层循环:O(n),嵌套调用inner_func(O(n))
def multiply_principle(n):ret = 0for i in range(1, n):ret += inner_func(i)return ret
  • 总复杂度为 O(n × n) = O(n²)

三、空间复杂度

3.1 定义

空间复杂度(渐进空间复杂度)表示算法占用的额外存储空间随数据规模 n 增长的趋势,仅关注 “额外空间”(即算法执行过程中主动申请的空间,不包含输入数据本身的空间)。

与时间复杂度类似,空间复杂度也忽略低阶项和系数,仅保留最大量级。

3.2 常见空间复杂度及示例

1. O (1):常数级空间

算法仅使用 “固定数量” 的额外变量,与 n 无关。示例:

def constant_space(n):sum_val = 0  # 固定1个变量for i in range(n):  # 固定1个变量isum_val += ireturn sum_val
  • 额外空间仅 2 个变量(sum_val、i),与 n 无关 → O(1)
2. O (n):线性级空间

算法申请的额外空间随 n 线性增长(如列表、字典等)。示例:

def linear_space(n):i = 0arr = [0] * n  # 申请大小为n的列表(额外空间随n增长)for i in range(n):arr[i] = i * isum_val = 0for i in range(n-1, -1, -1):sum_val += arr[i]return sum_val
  • 额外空间主要是大小为 n 的列表 arr → O(n)

3.3 注意事项

  • 空间复杂度不包含 “输入数据” 的空间(如函数参数中的列表),仅计算 “算法执行中主动创建” 的空间;
  • 递归算法的空间复杂度需考虑 “调用栈深度”:若递归深度为 n(如斐波那契递归),则空间复杂度为 O (n)(因调用栈需保存 n 个栈帧)。

四、复杂度核心小结

时间复杂度

  1. 核心:执行时间随 n 的增长趋势,关注 “最大量级”;
  2. 常见类型(按优劣排序):O (1) < O (log n) < O (n) < O (n log n) < O (n²) < O (2ⁿ) < O (n!);
  3. 分析原则:最大循环原则、加法原则、乘法原则;
  4. 特殊情况:仅当复杂度有量级差距时,才区分最好 / 最坏 / 平均复杂度。

空间复杂度

  1. 核心:额外存储空间随 n 的增长趋势,关注 “额外空间”;
  2. 常见类型:O (1)(常数空间)、O (n)(线性空间);
  3. 递归算法需关注 “调用栈深度” 对空间的影响。
http://www.dtcms.com/a/427132.html

相关文章:

  • SLA操作系统双因素认证实现Windows远程桌面OTP双因子安全登录—从零搭建企业级RDP安全加固体系
  • 现在主流的网站开发语言360房产网郑州官网
  • 石家庄哪个公司做网站好做外贸c2c网站有哪些
  • 伪路径约束
  • 新天力:以全链协同能力构筑食品容器行业领军优势
  • Markdown转换为Word:Pandoc模板使用指南
  • Cloudflare 开源 VibeSDK:开启“氛围编程”新时代的全栈 AI 应用生成平台
  • 汕头网站建设sagevis企业网站建设有什么好处
  • C语言趣味小游戏----猜数字小游戏
  • 多表关联对集中式数据库和分布式数据库系统冲击
  • Suifest 2025 活动速递
  • 交叉熵损失函数和负对数似然损失函数 KL散度
  • 坪地网站建设教程网站seo优化方法
  • 网站数据库多大合适成都小型软件开发公司
  • Gibbs采样:全面解析马尔可夫链蒙特卡洛的核心算法
  • 【开题答辩全过程】以 python的音乐网站为例,包含答辩的问题和答案
  • 二项式定理——力扣2221.数组的三角和
  • 【数据结构】快速排序与归并排序的实现
  • LeetCode算法日记 - Day 57: 括号生成、组合
  • FinalShell 服务器远程连接工具
  • 分享:一键自动化巡检服务器
  • 广州建站快车加盟网网站建设策划书
  • 12306网站架构站长之家seo综合
  • 学习:uniapp全栈微信小程序vue3后台-额外/精彩报错篇
  • 【云服务器相关】云服务器与P2P
  • vscode终端输出中文乱码一种解决方法
  • 脑机接口(BCI):从信号到交互的工程实践
  • 更改mysql密码
  • 同步与互斥
  • Java Web搭建商城首页