《数据结构》详解精炼:时间复杂度(3)

第 2 章 算法分析

2.8 时间复杂度(4)

1. 一个较复杂的问题

例题 2.8.1 估算以下算法的时间复杂度:

c 复制代码
void fun(int n){
    int x = 0;
    for(int i = 0, j = 0; i < n; i += j, j++)
        x++;
}

在循环语句中,i, j 都是从 0 开始,j 的步长是 1,但 i 的步长是 j 。通过下表,观察在迭代过程中两个变量的变化(注意,先执行 i += j )。

循环次序 i(i+=j) j(j++)
1 0+0 1
2 0+0+1 2
3 0+0+1+2 3
4 0+0+1+2+3 4
<math xmlns="http://www.w3.org/1998/Math/MathML"> ⋮ \vdots </math>⋮ <math xmlns="http://www.w3.org/1998/Math/MathML"> ⋮ \vdots </math>⋮ <math xmlns="http://www.w3.org/1998/Math/MathML"> ⋮ \vdots </math>⋮
r <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 + 0 + 1 + 2 + 3 + ⋯ + ( r − 1 ) 0+0+1+2+3+\cdots+(r-1) </math>0+0+1+2+3+⋯+(r−1) r

因为 i < n ,所以: <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 + 0 + 1 + 2 + 3 + ⋯ + ( r − 1 ) < n 0+0+1+2+3+\cdots+(r-1)\lt n </math>0+0+1+2+3+⋯+(r−1)<n ,即:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> r ( r − 1 ) 2 < n r 2 − r − 2 n < 0 1 − 1 + 8 n 2 < r < 1 + 1 + 8 n 2 ∵ r > 0 ∴ 0 < r < 1 + 1 + 8 n 2 \begin{split} &\frac{r(r-1)}{2}\lt n \\&r^2-r-2n\lt0 \\&\frac{1-\sqrt{1+8n}}{2}\lt r\lt\frac{1+\sqrt{1+8n}}{2} \\&\because~r\gt0 \\&\therefore~0\lt r\lt\frac{1+\sqrt{1+8n}}{2} \end{split} </math>2r(r−1)<nr2−r−2n<021−1+8n <r<21+1+8n ∵ r>0∴ 0<r<21+1+8n

所以,时间复杂度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(\sqrt{n}) </math>O(n ) 。

2. 多项式时间复杂度

至此,已经学习过的时间复杂度包括: <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( 1 ) , O ( log ⁡ n ) , O ( n ) , O ( n ) , O ( n log ⁡ n ) , O ( n 2 ) , O ( n 3 ) O(1),O(\log{n}),O(\sqrt{n}),O(n),O(n\log{n}),O(n^2),O(n^3) </math>O(1),O(logn),O(n ),O(n),O(nlogn),O(n2),O(n3) ,在 013 节的练习题中还有 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( log ⁡ log ⁡ n ) O(\log\log{n}) </math>O(loglogn) 。这些时间复杂度之间,存在如下定性的大小关系:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> O ( 1 ) < O ( log ⁡ log ⁡ n ) < O ( log ⁡ n ) < O ( n ) < O ( n ) < O ( n log ⁡ n ) < O ( n 2 ) < O ( n 3 ) O(1)\lt O(\log\log{n})\lt O(\log{n})\lt O(\sqrt{n})\lt O(n)\lt O(n\log{n})\lt O(n^2)\lt O(n^3) </math>O(1)<O(loglogn)<O(logn)<O(n )<O(n)<O(nlogn)<O(n2)<O(n3)

其中, <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( log ⁡ log ⁡ n ) , O ( log ⁡ n ) , O ( n ) , O ( n ) , O ( n log ⁡ n ) , O ( n 2 ) , O ( n 3 ) O(\log\log{n}), O(\log{n}), O(\sqrt{n}), O(n), O(n\log{n}), O(n^2), O(n^3) </math>O(loglogn),O(logn),O(n ),O(n),O(nlogn),O(n2),O(n3) 等称为多项式时间复杂度 (polynomial time complexity),可以统一表示为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( f ( n ) ) O(f(n)) </math>O(f(n)) ,且 <math xmlns="http://www.w3.org/1998/Math/MathML"> f ( n ) f(n) </math>f(n) 为多项式。

在算法复杂度理论中,多项式级的运行时间成本,往往被认为是可接受的,或者是可忍受的。某问题若可以用多项式复杂度的算法求解,则称该问题是可有效求解的,或者易解的。这样的问题也称为 P 问题。

除了 P 问题之外,也就是解决问题的算法的复杂度是多项式复杂度,除此之外,还有另外一类问题,只能用指数时间复杂度的算法求解,称为 NP 问题,或者称为难解问题。

3. 指数时间复杂度 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( 2 n ) O(2^n) </math>O(2n)

指数时间复杂度不是本课程重点,但是,考虑到学习本课的同学,将来的学习、工作或者研究过程中,一定不会仅仅局限于教材或者所谓考研大纲的知识范围,那么,也对此做个简单介绍。

例题 2.8.3 <math xmlns="http://www.w3.org/1998/Math/MathML"> n n </math>n 是非负整数,计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> 2 n 2^n </math>2n ,其算法如下(注意,这里的算法是此计算的一种,蛮力迭代,并不是最好的算法,此处仅仅是以此为例说明指数时间复杂度)。

c 复制代码
int power(int n){
    int pow = 1;
    while(0 < n--){
        pow <<= 1;  // pow = pow * 2
    }
    return  pow;
}

很显然,第 4 行是基本语句,语句频度是 <math xmlns="http://www.w3.org/1998/Math/MathML"> n n </math>n ,所以此算法的时间复杂度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(n) </math>O(n) 。

如果将输入指数 <math xmlns="http://www.w3.org/1998/Math/MathML"> n n </math>n 用二进制位数 <math xmlns="http://www.w3.org/1998/Math/MathML"> r = 1 + ⌊ log ⁡ n ⌋ r = 1+\lfloor\log{n}\rfloor </math>r=1+⌊logn⌋ 作为输入规模,则时间复杂度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( 2 r ) O(2^r) </math>O(2r) 。

把时间复杂度可以表示为 <math xmlns="http://www.w3.org/1998/Math/MathML"> T ( n ) = O ( a n ) , ( a > 1 ) T(n)=O(a^n),(a\gt1) </math>T(n)=O(an),(a>1) 的,均是指数时间复杂度(exponential time complexity)。

一般认为,指数时间复杂度的算法无法真正应用于实际问题中,这类算法不是有效的算法。

本文由mdnice多平台发布

相关推荐
程序员鱼皮6 分钟前
Cursor 1.2重磅更新,这个痛点终于被解决了!
ai·程序员·编程·agent·软件开发
狂师1 小时前
啥是AI Agent!2025年值得推荐入坑AI Agent的五大工具框架!(新手科普篇)
人工智能·后端·程序员
坤坤爱学习2.03 小时前
求医十年,病因不明,ChatGPT:你看起来有基因突变
人工智能·ai·chatgpt·程序员·大模型·ai编程·大模型学
摆烂工程师3 小时前
Claude Code 为什么突然火了?聊一下Claude Code 跟 Cursor 之间的区别
程序员·claude·cursor
redreamSo1 天前
AI Daily | AI日报:马斯克Grok 4跑分泄露,有望改写LLM格局; 猫猫话术让大模型数学答错率翻3倍; 安克创新All in AI,代码采纳率破50%
程序员·aigc·资讯
盖世英雄酱581362 天前
容易被程序员忽略的硬件设备
程序员
DeepSeek-大模型系统教程2 天前
深入金融与多模态场景实战:金融文档分块技术与案例汇总
人工智能·ai·语言模型·程序员·大模型·大模型学习·大模型教程
程序员鱼皮2 天前
Cursor 网页版来了,这下拉屎时也能工作了
计算机·ai·程序员·开发·项目·编程经验
redreamSo2 天前
AI Daily | AI日报:Nature:超14%生物医学论文或由AI代写; Grok 4测试成绩优异,数据真实性引争议; 李飞飞:攻克空间智能,为AGI补拼图
程序员·aigc·资讯