【CS.AL】算法复杂度分析 —— 时间复杂度详解

在这里插入图片描述

文章目录

    • 1 概述
    • 2 时间复杂度的详细分析
      • 2.1 常数时间复杂度(O(1))
      • 2.2 对数时间复杂度(O(log n))
      • 2.3 线性时间复杂度(O(n))
      • 2.4 线性对数时间复杂度(O(n log n))
      • 2.5 平方时间复杂度(O(n²))
      • 2.6 指数时间复杂度(O(2^n))
      • 2.7 阶乘时间复杂度(O(n!))
    • 3 用户体验中的时间复杂度 🔥
    • 4 计算时间复杂度的方法
    • 5 实际例子算法题
      • 5.1 二分查找算法
        • 步骤 1:分析代码
        • 步骤 2:分析循环
        • 步骤 3:处理递归
        • 步骤 4:计算总时间
        • 步骤 5:简化结果
      • 5.2 另一个例子:冒泡排序
        • 步骤 1:分析代码
        • 步骤 2:分析循环
        • 步骤 3:处理递归
        • 步骤 4:计算总时间
        • 步骤 5:简化结果
    • References

1 概述

时间复杂度是衡量一个算法执行效率的重要指标,它描述了算法在输入规模增长时,所需执行时间的增长趋势。时间复杂度通常用大O记号表示,比如O(1)、O(n)、O(n²)、O(log n)等。以下是一些常见的时间复杂度及其含义:

  1. O(1) - 常数时间复杂度

    • 这种算法在输入规模增大时,执行时间保持不变,不受输入规模影响。
    • 例如:数组访问、哈希表查找。
  2. O(log n) - 对数时间复杂度

    • 这种算法的执行时间随着输入规模的增大而对数级增长,常见于二分查找等。
    • 例如:二分查找、平衡二叉树查找。
  3. O(n) - 线性时间复杂度

    • 这种算法的执行时间与输入规模成正比,即输入规模翻倍,执行时间也翻倍。
    • 例如:线性查找、遍历数组。
  4. O(n log n) - 线性对数时间复杂度

    • 这种算法的执行时间是输入规模的线性乘以对数级增长,常见于高效排序算法如快速排序、归并排序等。
    • 例如:快速排序、归并排序。
  5. O(n²) - 平方时间复杂度

    • 这种算法的执行时间随着输入规模的平方级增长,常见于简单的排序算法如冒泡排序、选择排序等。
    • 例如:冒泡排序、选择排序。
  6. O(2^n) - 指数时间复杂度

    • 这种算法的执行时间随着输入规模的指数级增长,通常出现在解决复杂的递归问题中。
    • 例如:斐波那契数列递归解法、汉诺塔问题。
  7. O(n!) - 阶乘时间复杂度

    • 这种算法的执行时间随着输入规模的阶乘级增长,通常用于解决排列和组合问题。
    • 例如:旅行商问题的暴力解法。

2 时间复杂度的详细分析

2.1 常数时间复杂度(O(1))

在这种情况下,算法的执行时间不会随着输入规模的变化而变化。无论输入的规模多大,算法都只执行一个固定数量的操作。例如,访问数组中的某个元素,或者执行一个固定的算术运算。

2.2 对数时间复杂度(O(log n))

这种复杂度通常出现在需要“二分”处理问题的算法中。常见的例子是二分查找。在每一步中,算法将输入数据分成两半,只处理其中的一半,因此执行时间随着输入规模的对数级增长。

2.3 线性时间复杂度(O(n))

在这种情况下,算法的执行时间与输入规模成正比。每一个输入元素都会被处理一次。常见的例子包括简单的循环遍历数组、线性查找等。

2.4 线性对数时间复杂度(O(n log n))

这种复杂度通常出现在一些高效的排序算法中,如快速排序和归并排序。算法将输入数据分成较小的部分(通常是对数级),然后分别处理这些部分。

2.5 平方时间复杂度(O(n²))

这种复杂度通常出现在需要嵌套循环处理问题的算法中。每一个输入元素都会与每一个其他元素进行比较和处理。常见的例子包括冒泡排序、选择排序和插入排序。

2.6 指数时间复杂度(O(2^n))

这种复杂度通常出现在一些递归算法中,每一步递归都会生成多个子问题。常见的例子包括计算斐波那契数列的递归方法、汉诺塔问题等。

2.7 阶乘时间复杂度(O(n!))

这种复杂度通常出现在需要处理所有排列和组合问题的算法中。例如,旅行商问题的暴力解法就是一个阶乘时间复杂度的例子。

3 用户体验中的时间复杂度 🔥

#用户体验 #响应时间 #刹那 #须臾

根据《摩诃僧祗律》记载:一刹那为一念,二十念为一瞬,二十瞬为一弹指,二十弹指为一罗预,二十罗预为一须臾,一日一夜有三十须臾。可知:
1 须臾 = 24 小时 / 30 = 0.8 小时 = 48 分钟
1 罗预 = 1 须臾 / 20 = 48 分钟 / 20 = 2.4 分钟 = 2 分 24 秒
1 弹指 = 1 罗预 / 20 = 2.4 分钟 / 20 = 0.12 分钟 = 7.2 秒
1 瞬 = 1 弹指 / 20 = 7.2 秒 / 20 = 0.36 秒 = 360 毫秒
1 刹那 = 1 念 = 1 瞬 / 20 = 360 毫秒 / 20 = 18 毫秒

在实际的应用开发和用户体验中,响应时间对用户体验至关重要。以下是一些常见的响应时间要求和对应的描述:

  • 刹那(Moment):刹那可以认为是几十毫秒的响应时间。在理想状态下,页内操作应在刹那间解决,例如点击按钮、切换标签等,确保用户感受到即时的响应。

  • 瞬间(Instantaneous):瞬间的响应时间在几百毫秒以内。页面跳转应在瞬间解决,用户感觉不到延迟。

  • 弹指(Blink of an Eye):弹指级别的响应时间在几秒到十秒之间。对于复杂的操作,如上传大文件或处理复杂计算,响应时间较长时需要提供进度提示,告知用户操作正在进行中,并允许用户随时中止或取消。

4 计算时间复杂度的方法

为了理解和计算算法的时间复杂度,可以将其类比为一次探险,寻找算法的时间复杂度这个“宝藏”。以下是具体步骤:

  1. 分析代码:观察代码中的每一步操作,找到它们之间的关系,以及它们执行的频率。

  2. 分析循环:使用指南针(分析循环)判断方向,计算每一步操作的次数。

  3. 处理递归:注意递归调用的频率,计算递归的深度和每次递归的操作次数。

  4. 计算总时间:将所有操作次数加总,得到整个算法的时间复杂度。

  5. 简化结果:将复杂度表达式简化,保留最高次项,忽略常数项和低次项,得到最终的时间复杂度。

通过这些步骤,我们可以准确地计算出算法的时间复杂度,从而更好地评估和优化算法的性能。

5 实际例子算法题

让我们通过一个实际例子来演示如何计算算法的时间复杂度。

5.1 二分查找算法

int binarySearch(int arr[], int left, int right, int x) {while (left <= right) {int mid = left + (right - left) / 2;// 检查x是否在中间位置if (arr[mid] == x) return mid;// 如果x更大,忽略左半部分if (arr[mid] < x) left = mid + 1;// 如果x更小,忽略右半部分elseright = mid - 1;}// 元素不存在于数组中return -1;
}
步骤 1:分析代码
  • 初始化中间位置 mid = left + (right - left) / 2
  • 比较 arr[mid]x
  • 更新 leftright 以缩小搜索范围
步骤 2:分析循环
  • while循环条件为 left <= right,在每次迭代中,搜索范围减半。
步骤 3:处理递归

二分查找算法是一个迭代过程,没有递归调用。

步骤 4:计算总时间

在每次迭代中,搜索范围减半,这意味着我们最多会执行 log₂n 次迭代,其中 n 是数组的长度。

步骤 5:简化结果

忽略常数项和低次项,我们得到时间复杂度为 O(log n)

5.2 另一个例子:冒泡排序

void bubbleSort(int arr[], int n) {for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - i - 1; j++) {if (arr[j] > arr[j + 1]) {// 交换 arr[j] 和 arr[j+1]int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}
步骤 1:分析代码
  • 两个嵌套的for循环
  • 内循环中,每次迭代比较并交换相邻的元素
步骤 2:分析循环
  • 外循环执行 n-1
  • 内循环执行 n-i-1 次,其中 i 是外循环的当前迭代次数
步骤 3:处理递归

冒泡排序是一个迭代过程,没有递归调用。

步骤 4:计算总时间

总的执行次数为:∑i=0n-1​(n−i−1)=n(n−1)/2

步骤 5:简化结果

忽略常数项和低次项,我们得到时间复杂度为 O(n²)

References

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

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

相关文章

程序的基本结构、cout语句(c++语言)

一、如何下载Dev C 登录网站&#xff1a;ht.51goc.com 二、安装Dev C 一、启动Dev C 双击桌面的图标 二、新建一个程序 三、复制一个程序 请你复制以下代码到“程序编辑区” #include<bits/stdc.h> using namespace std; int main() { cout<<"Hell…

详解MySQL完整性约束

完整性约束条件是对字段进行限制&#xff0c;要求用户对该属性进行的操作符合特定的要求。如果不满足完整性约束条件&#xff0c;数据库系统将不再执行用户的操作。MySQL 完整性约束常用的操作有六大操作&#xff1a; 主键约束唯一约束 unique非空 not null默认值约束(default…

计网仿真综合实验 实验十二

实验十二 综合网络实验 实验过程 IP配置说明参考连线配置OSPF使公司内部联通 路由器R1的OSPF配置路由器R2的OSPF配置路由器R3的OSPF配置R1、R2、R3的相关解释路由器R4的OSPF配置路由器R5的OSPF配置路由器R6的OSPF配置R4、R5、R6解释: 路由器R2的RIP配置路由器R7的RIP配置 总结 …

MicroPython esp32 连接wifi 配网

整体流程&#xff1a; 1&#xff09;开启STA 和 AP 模式 2&#xff09;扫描周围wifi 保存在 变量 wifi_list&#xff08;后面要用到&#xff09; 3) 尝试STA模式连接Wifi&#xff0c;并查寻状态。 4) 如果STA 无法连网&#xff0c;就用AP模式&#xff0c;创建热点。 5&a…

Radash 轻量级的函数工具集

Radash 是一个现代的 JavaScript 实用程序库&#xff0c;旨在提供高效、轻量级的函数工具集&#xff0c;类似于 Lodash&#xff0c;但更加现代化和模块化。Radash 通过提供一系列常用的工具函数&#xff0c;帮助开发者更轻松地处理数组、对象、函数等操作。 以下是一些 Radash…

Python中的列表(List)和元组(Tuple)的区别

在Python中&#xff0c;列表&#xff08;List&#xff09;和元组&#xff08;Tuple&#xff09;都是常用的数据结构&#xff0c;用于存储一系列的元素。然而&#xff0c;它们在多个方面存在着显著的区别。下面将从技术难点、面试官关注点、回答吸引力和代码举例四个方面来详细解…

【lesson1】第三方库(jsoncpp,bundle, httplib)的介绍和使用

文章目录 jsoncpp库json 认识jsoncpp 认识jsoncpp 实现序列化jsoncpp 实现反序列化 bundle库bundle库实现文件压缩bundle库实现文件解压缩 httplib 库httplib 库搭建简单服务器httplib库搭建简单客户端 jsoncpp库 json 认识 json 是一种数据交换格式&#xff0c;采用完全独立…

【Vscode配置java环境并配置stringboot】

1.VSCODE配置JAVA环境 参考这篇文章配置JAVA环境&#xff1a;连接 java版本&#xff0c;我是win11系统,我下载的JAVA安装版本是下面&#xff0c;是最新版的&#xff1a; 配置环境&#xff1a;步骤很简单&#xff0c;就是向系统环境变量中添加路径&#xff0c;参考上面文章中的…

(20)DAC接口--->(005)FPGA实现AD5601接口(五)

(005)FPGA实现AD5601接口(五) 1 目录 (a)FPGA简介 (b)IC简介 (c)Verilog简介 (d)FPGA实现AD5601接口(五) (e)结束 1 FPGA简介 (a)FPGA(Field Programmable Gate Array)是在PAL (可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展…

基于学习模型的可学习小波变换方法(Pytorch)

首先以图像编码为例进行说明。 图像编码是一个复杂的系统&#xff0c;通常包含多个模块&#xff0c;其中变换模块具有重要作用。小波变换在图像编码领域得到了广泛的应用&#xff0c;例如著名的JPEG 2000就是一种小波图像编码方法。然而&#xff0c;现阶段的小波图像编码方法与…

htb-window-1-legacy-smb

nmap smb-vuln-ms08-067 py文件测试失败 msf 漏洞定位 反弹 获取flag

【Oracle篇】rman全库异机恢复:从单机环境到RAC测试环境的转移(第五篇,总共八篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

一文学会Spring 实现事务,事务的隔离级别以及事务的传播机制

目录 一.Spring (Spring Boot) 实现事务 1.通过代码的方式手动实现事务 (手动档的车) 2.通过注解的方式实现声明式事务 (自动挡的车) 二.事务的4大特性(ACID) 三.事务的隔离级别 ①Mysql的事务隔离级别: ②Spring的事务隔离级别: 四.事务的传播机制 ①事务传播机制的概…

验证码案例

目录 前言 一、Hutool工具介绍 1.1 Maven 1.2 介绍 1.3 实现类 二、验证码案例 2.1 需求 2.2 约定前后端交互接口 2.2.1 需求分析 2.2.2 接口定义 2.3 后端生成验证码 2.4 前端接收验证码图片 2.5 后端校验验证码 2.6 前端校验验证码 2.7 后端完整代码 前言…

基于可解释性深度学习的马铃薯叶病害检测

数据集来自kaggle文章&#xff0c;代码较为简单。 import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)# Input data files are available in the read-only "../input/" directory # For example, runni…

快团团供货大团长如何查看帮卖团长的订单?

一、功能说明 可以看到团购中每个帮卖团长帮卖产生的订单 二、具体设置方法 1、小程序端如何操作&#xff1f; 在团购页面中&#xff0c;点击订单管理&#xff0c;在这里可以选择全部团长订单&#xff0c;我的团订单&#xff0c;和帮卖团长的帮卖订单。 2、PC端如何操作&am…

ssm616基于vue.js的购物商场的设计与实现+vue【已测试】

前言&#xff1a;&#x1f469;‍&#x1f4bb; 计算机行业的同仁们&#xff0c;大家好&#xff01;作为专注于Java领域多年的开发者&#xff0c;我非常理解实践案例的重要性。以下是一些我认为有助于提升你们技能的资源&#xff1a; &#x1f469;‍&#x1f4bb; SpringBoot…

几句话搞懂什么是docker image?它主要解决什么问题?他用什么技术实现的?

一、什么是docker image? 1、除去LinuxOS内核资源的用户空间的一组资源集合的快照。 2、使用laber区分版本。 3、使用仓库进行分发。 4、符合OCI标准的Runtime都可以运行docker image. 二、他主要解决什么问题&#xff1f; 1、最最重要的就是解决可移植性&#xff01;当你本地…

【基于C++与OpenCV实现魔方图像识别和还原算法】施工总览图

文章目录 主要效果展示思维导图魔方还原算法 本系列博客长期更新&#xff0c;分为两大部分 OpenCV实现魔方六面识别 C编写科先巴二阶段还原算法实现三阶魔方的还原 主要效果展示 摄像头识别六面 3D图像构建&#xff0c;提供还原公式 动画演示还原过程 思维导图 魔方还原算法 参…

达梦8 开启物理逻辑日志对系统的影响

物理逻辑日志&#xff0c;是按照特定的格式存储的服务器的逻辑操作&#xff0c;专门用于 DBMS_LOGMNR 包挖掘获取数据库系统的历史执行语句。当开启记录物理逻辑日志的功能时&#xff0c;这部分日志内 容会被存储在重做日志文件中。 要开启物理逻辑日志的功能&#xff0c;需要…