时间复杂度详解2——时间复杂度的计算

时间复杂度基本计算规则:

  • 基本操作即只有常数项,认为其时间复杂度为O(1)
  • 顺序结构,时间复杂度按加法进行计算
  • 循环结构,时间复杂度按乘法进行计算
  • 分支结构,时间复杂度取最大值
  • 判断一个算法效率时,往往只需要关注操作数量的最高次项,其他次要项和常数项可以忽略
  • 在没有特殊说明时,我们所分析的时间复杂度都是指最坏时间复杂度

单层循环时间复杂度计算

例题分析

 例一:

i = n*n;
whlie(i != 1)i = i/2;

我们发现,循环执行的条件是i!=1,然后循环体中i=i/2;改变了i的值。

我们列出循环体执行次数t  和i的最终值(即执行完t次循环后的值)的关系

循环体执行次数t0123
i的改变量in^{2}\frac{n^{2}}{2}\frac{n^{2}}{4}\frac{n^{2}}{8}

           
第二步:找到t的最终值与i的关系:

i=\frac{n^{2}}{2^{t}}

第三步:确定循环停止条件:

i=1

第四步:联立第二步第三步两式解方程:

\frac{n^{2}}{2^{t}}=1     n^{2}=2^{t} 

两边对2取对数得    t=log_{2}n^{2}=2log_{2}n

所以得到时间复杂度为:T=O(log_{2}n)

例二:

x = 0;
while (n>=(x+1)*(x+1))x = x+1;

第一步:列出循环趟数t及x的最终值(即执行完t次循环后的值)

循环体执行次数t0123
x的最终值x0123


第二步:找到t与x的最终值关系:

t=x

第三步:确定循环停止条件:

n=(x+1)^{2}

第四步:联立第二步第三步两式解方程:

n=(t+1)^{2}

t=\sqrt{n}-1

所以得到时间复杂度为:

T=O(\sqrt{n})

 例三:

int i = 1;
while (i<=n)i = i *2

第一步:列出循环趟数t及i的最终值(即执行完t次循环后的值)

循环趟数t0123
i的最终值1248


第二步:找到t与i的关系:

i=2^{t}

第三步:确定循环停止条件:

i=n

第四步:联立第二步第三步两式解方程:

n=2^{t}

t=log_{2}n

所以得到时间复杂度为:

T=O(log_{2}n)

 例四:

int i = 0;
while (i*i*i<=n)i ++;


第一步:列出循环趟数t及i的最终值:

循环趟数t0123
i的最终值i0123


第二步:找到t与i的关系:

t=i

第三步:确定循环停止条件:

i^{3}=n

第四步:联立第二步第三步两式解方程:

t^{3}=n

t=\sqrt[3]{n}

所以得到时间复杂度为:

T=O(\sqrt[3]{n})

 例五:

y = 0;
while (y+1)*(y+1) <= n)y = y+1;


第一步:列出循环趟数t及y的最终值:

循环趟数t0123
y的最终值0123


第二步:找到t与y的关系:

t=y

第三步:确定循环停止条件:

(y+1)^{2}=n

第四步:联立第二步第三步两式解方程:

(t+1)^{2}=n

t=\sqrt{n}-1

所以得到时间复杂度为:

T=O(\sqrt{n})

两层循环时间复杂度计算

对于两层循环时间复杂度的计算,我们完全可以将这个循环视作一个单层循环,然后它的循环体是另一个循环。这样子计算起时间复杂度就很简单了

例题分析

例一:

int m=0,i,j;
for (i=1;i<=n;i++)for(j=1;j<=2*i;j++)m++;


第一步列出是第n次大循环

第二步列出在第n次大循环中内循环层语句能执行的次数:

第几次大循环123……n
第n次大循环中内循环语句的执行次数246……2n

注意上面这个都是每次大循环对应的内部循环语句执行次数,整个语句的时间复杂度还需要把每次大循环中内循环语句执行的次数相加起来

注意是将内循环语句次数相加

第三步 求和,写结果

2+4+...+2n=n(n+1)

T=O(n^{2})

 例二:

for (i=0;i<n;i++)for(j=0;j<m;j++)a[i][j] = 0;

第一步列出第n次大循环:

第二步列出第n次大循环中内层语句的执行次数:

第n次大循环123...n
第n次大循环中内层循环语句的执行次数mmmmm

注意上面这个都是每次大循环对应的内部循环语句执行次数,整个语句的时间复杂度还需要把每次大循环中内循环语句执行的次数相加起来


第三步 求和,写结果

注意是将内循环语句次数相加

T=O(m*n)

 例三:

count = 0;
for (k=1;k<=n;k*=2)for(j=1;j<=n;j++)count ++;

第一步列出第a次大循环:(注意这里k*=2)

第二步列出第a次大循环中内层语句的执行次数:

由于这里大循环能执行的次数不是一眼就能看出来的,所以还得先计算能执行多少次大循环

假设能执行t次大循环,则

k=2^{t-1}

k=n

n=2^{t-1}

t=log_{2}n+1

第a次大循环123……log_{2}n+1
k的值124……n
第a次大循环中内层语句的执行次数nnnnn

内层每个都是n,求和则可以得到:

注意是将内循环语句次数相加

内循环语句总的执行次数是

(log_{2}n+1)n

T=O(nlog_{2}n)

 例四:

for (i=n-1;i>=1;i--)for(j=1;j<=i;j++)if (A[j] > A [j+1]){//时间复杂度为O(1)的语句
}

第一步列出第t次大循环:

第二步列出第t次大循环中内层语句的执行次数:

第t次大循环123...n-1
第t次大循环中内层循环语句的执行次数n-1n-2n-3...1

第三步 求和,写结果

注意是将内循环语句次数相加

在本例中它就是个等差数列求和

(n-1) + (n-2) + \ldots + 2 + 1 = \frac{(n-1) \times n}{2}

所以时间复杂度就是

T=O(n^{2})

多层循环时间复杂度计算

实际上无论多少层循环,我们只需一层一层分开来计算就行了,最后只需将最内层的语句的执行次数全加起来就好了

例一:

for(i=0;i<=n;i++)for(j=0;j<=i;j++)for(k=0;k<j;k++)

要计算这个嵌套循环的时间复杂度,我们首先要分析每个循环的执行次数。

外层循环 for(i=0;i<=n;i++) 从 0 到 n,因此会执行 n+1 次。

对于每一个 i 的值,内层循环 for(j=0;j<=i;j++) 的执行次数从 0 到 i。具体来说:

  • 当 i = 0 时,内层循环执行 1 次(j 从 0 到 0)。
  • 当 i = 1 时,内层循环执行 2 次(j 从 0 到 1)。
  • 当 i = 2 时,内层循环执行 3 次(j 从 0 到 2)。
  • ...
  • 当 i = n 时,内层循环执行 n+1 次(j 从 0 到 n)。

因此,内层循环的总执行次数是 1 + 2 + 3 + ... + (n+1),这是一个等差数列的和,其和为 (\frac{(n+1)(n+2)}{2})。

对于每一个 j 的值,最内层的循环 for(k=0;k<j;k++) 的执行次数是从 0 到 j-1。这实际上是一个等差数列的前 j 项和,但我们要注意,这个内层循环对于每一个 j 都会执行,所以我们需要将它与 j 的所有可能值相乘。

具体来说,当 j 分别取 0, 1, 2, ..., n 时,最内层循环的执行次数分别是 0, 1, 3, ..., n(n-1)/2。因此,最内层循环的总执行次数是这些值的和。

为了计算这个总和,我们可以观察到一个事实:每一个 k 值在 j 从 k+1 到 n 的过程中都会被计算一次。因此,k=0 会被计算 n 次,k=1 会被计算 n-1 次,以此类推,直到 k=n-1 只被计算 1 次。

这个总和是另一个等差数列的和,其和为 \frac{n(n-1)}{2}

因此,整个嵌套循环的时间复杂度是外层循环次数 n+1 乘以最内层循环的总执行次数 (\frac{n(n-1)}{2}),即(n+1) \times \frac{n(n-1)}{2}

简化后得到时间复杂度为 (O(n^3))。这是因为尽管有系数和较低阶的项,但在大 n 的情况下,(n^3) 项将主导整个表达式,因此时间复杂度是立方级的。

常见时间复杂度计算举例

实例1:

// 计算Func2的时间复杂度?void Func2(int N) 
{ int count = 0; 
for (int k = 0; k < 2 * N ; ++ k){ ++count; } int M = 10; 
while (M--) 
{ ++count; } printf("%d\n", count); 
}

 实例1基本操作执行了2N+10次,通过推导大O阶方法知道,时间复杂度为 O(N) 

实例2

// 计算Func3的时间复杂度?void Func3(int N, int M){ int count = 0; 
for (int k = 0; k < M; ++ k) 
{ ++count; } for (int k = 0; k < N ; ++ k) 
{ ++count; } printf("%d\n", count);}

实例2基本操作执行了M+N次,有两个未知数M和N,时间复杂度为 O(N+M) 

实例3

// 计算Func4的时间复杂度? 
void Func4(int N){ int count = 0; 
for (int k = 0; k < 100; ++ k) 
{ ++count; } 
printf("%d\n", count);}

 实例3基本操作执行了10次,通过推导大O阶方法,时间复杂度为 O(1)

实例4

// 计算strchr的时间复杂度?const char * strchr ( const char * str, int character );

实例4基本操作执行最好1次,最坏N次,时间复杂度一般看最坏,时间复杂度为 O(N)

实例5 

// 计算BubbleSort的时间复杂度? 
void BubbleSort(int* a, int n) 
{ assert(a);for (size_t end = n; end > 0; --end){ int exchange = 0; for (size_t i = 1; i < end; ++i) 
{ 
if (a[i-1] > a[i]) { Swap(&a[i-1], &a[i]); 
exchange = 1; 
} } 
if (exchange == 0)break;
} 
} 

实例5基本操作执行最好N次,最坏执行了(N*(N+1)/2次,通过推导大O阶方法+时间复杂度一般看最坏,时间复杂度为 O(N^2)

实例6 

// 计算BinarySearch的时间复杂度?int BinarySearch(int* a, int n, int x) 
{ 
assert(a);int begin = 0; 
int end = n-1; 
while (begin < end){ int mid = begin + ((end-begin)>>1); if (a[mid] < x) begin = mid+1;else if (a[mid] > x) end = mid; else return mid;}return -1;}

实例6基本操作执行最好1次,最坏O(logN)次,时间复杂度为 O(logN).。ps:logN在算法分析中表示是底数为2,对数为N。有些地方会写成lgN。(建议通过折纸查找的方式讲解logN是怎么计算出来的)

实例7

// 计算阶乘递归Fac的时间复杂度?long long Fac(size_t N) 
{ if(0 == N) return 1;return Fac(N-1)*N; }

实例7通过计算分析发现基本操作递归了N次,时间复杂度为O(N) 

实例8

// 计算斐波那契递归Fib的时间复杂度?long long Fib(size_t N){ 
if(N < 3) 
return 1; return Fib(N-1) + Fib(N-2); }

实例8通过计算分析发现基本操作递归了2^N次,时间复杂度为O(2^N)。(建议画图递归栈帧的二叉树 讲解)

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

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

相关文章

第十二届蓝桥杯大赛软件赛省赛Java 大学 B 组题解

1、ASC public class Main {public static void main(String[] args) {System.out.println(

LeetCode- 合并两个有序数组

题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;合并…

Java | Leetcode Java题解之第17题电话号码的字母组合

题目&#xff1a; 题解&#xff1a; class Solution {public List<String> letterCombinations(String digits) {List<String> combinations new ArrayList<String>();if (digits.length() 0) {return combinations;}Map<Character, String> phoneM…

Linux的学习之路:7、yum与git

摘要 本章主要是说一下yum和git的操作 目录 摘要 一、什么是yum 二、yum三板斧 1、list 2、install 3、remove 三、怎么创建仓库 四、git三板斧 1、add 2、commit 3、push 4、pull 五、思维导图 一、什么是yum YUM是Yellowdog Updater Modified的简称&#xf…

Github 2024-04-12 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-04-12统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6TypeScript项目2Cuda项目1C++项目1C项目1HTML项目1Jupyter Notebook项目1JavaScript项目1Python - 100天从新手到大师 创建周期:22…

unity_Button:单击的三种实现方式

1.针对特定单个按钮 此代码直接绑定到button上面无需其他操作 using UnityEngine; using UnityEngine.UI;public class PrintHelloOnButtonClick : MonoBehaviour {private Button button;void Start(){// 获取当前GameObject上的Button组件button GetComponent<Button&g…

CTF-SHOW SSRF

web351 存在一个flag.php页面&#xff0c;访问会返回不是本地用户的消息&#xff0c;那肯定是要让我们以本地用户去访问127.0.0.1/flag.php web352 代码中先判断是否为HTTP或https协议&#xff0c;之后判断我们传入的url中是否含有localhost和127.0.0&#xff0c;如果没有则…

VulnHub靶机-easy_cloudantivirus 打靶

easy_cloudantivirus 靶机 目录 easy_cloudantivirus 靶机一、导入虚拟机配置二、攻击方式主机发现端口扫描web渗透-SQL注入命令注入反弹shellssh爆破提权 一、导入虚拟机配置 靶机地址&#xff1a; https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453/下载完成&am…

Docker 安装RabbitMQ以及使用客户端图形化界面

目录 一、点击进入docker 镜像仓库 1.1 直接在官网里 搜索 rabbitmq 1.2 在标签里 直接搜索3.10-management 因为这个标签包含用户操作界面 二、启动docker 2.1 首先拉取镜像&#xff1a; 2.2 Docker运行&#xff0c;并设置开机自启动 三、访问用户操作界面 一、点击进入…

PTA(题目集二 题目 代码 C++)

目录 题目一&#xff1a; 代码&#xff1a; 题目二&#xff1a; 代码&#xff1a; 题目三&#xff1a; 代码&#xff1a; 题目四&#xff1a; 代码&#xff1a; 题目五&#xff1a; 代码&#xff1a; 题目六&#xff1a; 代码&#xff1a; 题目七&#xff1a; 代…

python中time库的time.time()函数的作用是什么?

python中time库的time.time()函数的作用是什么&#xff1f; 作用&#xff1a;Python time time() 返回当前时间的时间戳&#xff08;1970纪元后经过的浮点秒数&#xff09;。 time()方法语法&#xff1a;time.time() #!/usr/bin/python # Write Python 3 code in this onlin…

Windows10 19c单例数据库补丁升级方案

一、环境说明&#xff1a; 名称内容系统版本Windows10数据库版本19.3.0.0.0SIDorcl 二、配置OPatch 2.1.解压OPatch --解压至$ORACLE_HOME位置 2.2.查看版本 --命令 OPatch version 三、准备打补丁 3.1.解压补丁文件 --解压 unzip p35962832_190000_MSWIN-x86-64.zip 3.2.…

【DM8】AWR报告

sys.WRM$_WR_CONTROL记录快照的相关控制信息 sys.wrm $_snapshot记录快照的相关信息 1.初始化awr快照包 创建或删除DBMS_WORKLOAD_REPOSTORY系统包为1的时候开启&#xff0c;0的时候关闭 SELECT sf_check_awr_sys; sp_init_awr_sys(1);2.设置时间 –间隔10min一次 CALL dbms_…

未来汽车硬件安全的需求(1)

目录 1.概述 2.EVITA 2.1 EVITA HSM 2.2 EVITA保护范围 3.市场变化对车载网络安全的影响 3.1 非侵入式攻击的风险 3.2 量子计算机的蛮力攻击 3.3 整车E/E架构的变化 3.4 网络安全标准和认证 3.5 汽车工业的网络安全措施 4.汽车安全控制器 4.1 TPM2.0 4.2 安全控…

CLIP模型入门

简介 CLIP&#xff08;Contrastive Language-Image Pre-Training&#xff09;是OpenAI在2021年初发布的多模态预训练神经网络模型&#xff0c;用于匹配图像和文本。该模型的关键创新之一是将图像和文本映射到统一的向量空间&#xff0c;通过对比学习的方式进行预训练&#xff…

运用OSI模型提升排错能力

1. OSI模型有什么实际的应用价值&#xff1f; 2. 二层和三层网络的区别和应用&#xff1b; 3. 如何通过OSI模型提升组网排错能力&#xff1f; -- OSI - 开放式系统互联 - 一个互联标准 - 从软件和硬件 定义标准 - 不同厂商的设备 研发的技术 - 具备兼容性 -- O…

知识图谱入门到实战之1.知识图谱基础

知识图谱基础 1.为什么要用知识图谱2.知识图谱的前世今生&#xff08;1&#xff09;发展脉络&#xff08;2&#xff09;发展阶段&#xff08;3&#xff09;知识图谱定义&#xff08;4&#xff09;知识类型&#xff08;5&#xff09;常见的开源知识图谱 3.知识图谱的相关技术&am…

拥有一台阿里云服务器可以做什么?

阿里云ECS云服务器可以用来做什么&#xff1f;云服务器可以用来搭建网站、爬虫、邮件服务器、接口服务器、个人博客、企业官网、数据库应用、大数据计算、AI人工智能、论坛、电子商务、AI、LLM大语言模型、测试环境等&#xff0c;云服务器吧yunfuwuqiba.com整理阿里云服务器可以…

2024/4/5—力扣—下一个排列

代码实现&#xff1a; 思路&#xff1a;两遍扫描 void swap(int *a, int *b) {int t *a;*a *b;*b t; }void reverse(int *nums, int l, int r) {while (l < r) {swap(nums l, nums r);l;r--;} }void nextPermutation(int *nums, int numsSize) {int i numsSize - 2;wh…

陆面、生态、水文模拟与多源遥感数据同化

原文链接&#xff1a;陆面、生态、水文模拟与多源遥感数据同化https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601198&idx6&sn51b9b26b75c9df1f11dcb9a187878261&chksmfa820dc9cdf584df9ac3b997c767d63fef263d79d30238a6523db94f68aec621e1f91df85f6…