时间复杂度的计算技巧-算法模型中的时间复杂度如何计算,有哪些技巧呢

大家好,我是微学AI,今天给大家介绍一下时间复杂度的计算技巧-算法模型中的时间复杂度如何计算,有哪些技巧呢,算法的时间复杂度是评估算法性能和效率的一种方式,它表示算法需要执行多少次基本操作才能完成其任务,这个数量随着输入规模的增加而增加。
时间复杂度通常用大O符号表示,例如O(n)、O(n²)等。其中,n表示输入规模,也就是算法需要处理的数据的大小。
在这里插入图片描述

一、常见的时间复杂度有:

O(1):常数时间复杂度,表示算法的执行时间不随输入规模的增加而增加,例如数组的索引访问。
O(log n):对数时间复杂度,表示算法的执行时间随着输入规模的增加而增加,但增加速度很慢,例如二分查找。
O(n):线性时间复杂度,表示算法的执行时间随着输入规模的增加而线性增加,例如遍历数组。
O(n log n):线性对数时间复杂度,表示算法的执行时间随着输入规模的增加而略微超线性增加,例如快速排序。
O(n²):平方时间复杂度,表示算法的执行时间随着输入规模的增加而平方级别增加,例如冒泡排序。

对于同一问题,不同的算法可能具有不同的时间复杂度,因此在选择算法时需要综合考虑时间复杂度、空间复杂度以及算法的实现难度等因素。

二、在C语言中的算法时间复杂度

我们可以通过对程序执行的次数的统计来计算其时间复杂度。一般情况下,我们关注的是最坏情况下程序的执行次数,因为最坏情况下的时间复杂度往往是算法的瓶颈。

对于一个基本操作(如赋值、比较、运算等),我们假设其执行时间为常量单位时间(即 O(1) 时间复杂度)。那么我们可以根据程序的代码结构和控制流程,计算出程序在最坏情况下的执行次数,从而确定其时间复杂度。下面是一些常见的时间复杂度及其示例:

  1. O(1) 常数级别
int a = 1;
int b = 2;
int c = a + b;

上述代码中,三个赋值语句和一个加法运算都是 O(1) 操作,总的时间复杂度也是 O(1)。

  1. O(n) 线性级别
for (int i = 0; i < n; i++) {printf("%d ", i);
}

上述代码中,for 循环中的 printf 语句会被执行 n 次,因此总的时间复杂度是 O(n)。

  1. O(n^2) 平方级别
for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {printf("%d ", i + j);}
}

上述代码中,内层循环中的 printf 语句会被执行 n^2 次,因此总的时间复杂度是 O(n^2)。

  1. O(log n) 对数级别
int i = n;
while (i > 0) {printf("%d ", i);i /= 2;
}

上述代码中,while 循环的条件是 i > 0,每次循环 i 会被除以 2,因此循环执行的次数为 log2(n)+1(以 2 为底的对数),因此总的时间复杂度是 O(log n)。

  1. O(n log n) 线性对数级别
for (int i = 0; i < n; i++) {int j = n;while (j > 0) {printf("%d ", i + j);j /= 2;}
}

上面代码中,外层循环会被执行 n 次,内层循环会被执行 log2(n)+1 次,因此总的时间复杂度是 O(n log n)。

计算时间复杂度时,一般采用大 O 记法,去掉常数项和低次项,只保留最高次项。另外,在计算时间复杂度时,需要注意以下几点:

  1. 循环嵌套时,内层循环次数的上界应该是外层循环的变量。
  2. 递归算法的时间复杂度需要进行递推处理,通常会使用主定理或递归树等方法。
  3. 位运算、矩阵乘法等特殊运算的时间复杂度需要特别处理。

三、递归算法的时间复杂度(python)

当涉及递归算法的时间复杂度时,有几种常见的复杂度级别。下面我将为你提供每种级别的例子代码:

  1. O(1) 常数级别的递归算法
def recursive_constant(n):if n <= 0:returnprint("Hello!")recursive_constant(n - 1)

上述代码中,无论输入是多少,函数都只会递归调用自身一次,因此时间复杂度为 O(1)。

  1. O(n) 线性级别的递归算法
def recursive_linear(n):if n <= 0:returnprint(n)recursive_linear(n - 1)

上述代码中,递归调用的次数与输入规模 n 成线性关系,因此时间复杂度为 O(n)。

  1. O(n^2) 平方级别的递归算法
def recursive_quadratic(n):if n <= 0:returnfor i in range(n):print(n)recursive_quadratic(n - 1)

上述代码中,递归调用的次数与输入规模 n 成平方关系,这个函数的时间复杂度是O(n^2),其中n表示输入的参数值。

我们来分析一下:

该函数是一个递归函数,每次递归调用都会执行一个for循环,循环次数为n。然后,递归调用将参数n减1,并再次执行相同的操作。

因此,在第一次递归调用中,for循环会执行n次。在第二次递归调用中,for循环会执行n-1次,以此类推,直到n减少到1为止。

总的执行次数可以近似为n + (n-1) + (n-2) + … + 1。根据等差数列求和公式,可以得到:

n + (n-1) + (n-2) + … + 1 = (n+1) * n / 2

因此,总的执行次数约为(n+1) * n / 2,也就是O(n^2)。

  1. O(2^n) 指数级别的递归算法
def recursive_exponential(n):if n <= 0:returnprint(n)recursive_exponential(n - 1)recursive_exponential(n - 1)

这个函数的时间复杂度是O(2^n),其中n表示输入的参数值。让我们来分析一下:

该函数是一个递归函数,每次递归调用都会执行两个递归调用。在每个递归调用中,参数n都会减1,并再次执行相同的操作。

因此,在第一次递归调用中,函数会执行一次print语句和两次递归调用。在第二次递归调用中,每次递归调用又会执行一次print语句和两次递归调用。以此类推,直到n减少到0为止。

总的执行次数可以近似为2^0 + 2^1 + 2^2 + … + 2^n。根据等比数列求和公式,可以得到:

2^0 + 2^1 + 2^2 + … + 2^n = 2^(n+1) - 1

因此,总的执行次数约为2^(n+1) - 1,也就是O(2^n)。

需要注意的是,递归函数的空间复杂度是O(n),因为每次递归调用都会在内存中创建新的函数调用栈。

四、 O(nlogn)与O(n^2logn)的时间复杂度:

1.O(nlogn)的例子

def merge_sort(arr):if len(arr) <= 1:return arr# 分割数组mid = len(arr) // 2left = merge_sort(arr[:mid])right = merge_sort(arr[mid:])# 合并并排序子数组return merge(left, right)def merge(left, right):merged = []i, j = 0, 0# 依次比较两个子数组的元素,并按顺序合并while i < len(left) and j < len(right):if left[i] < right[j]:merged.append(left[i])i += 1else:merged.append(right[j])j += 1# 将剩余的元素添加到合并后的数组中merged.extend(left[i:])merged.extend(right[j:])return mergedarr = [4, 2, 7, 1, 5, 3]
sorted_arr = merge_sort(arr)
print(sorted_arr)

以上示例使用归并排序算法对一个数组进行排序,归并排序的时间复杂度为O(nlogn)。在每次递归中,数组会被分割成两半,每一层递归需要O(n)的时间复杂度来合并两个已排序的子数组。

  1. O(n^2logn)的例子:
def insertion_sort(arr):for i in range(1, len(arr)):key = arr[i]j = i - 1# 在已排序的子数组中找到合适的位置插入元素while j >= 0 and arr[j] > key:arr[j+1] = arr[j]j -= 1arr[j+1] = keydef nested_insertion_sort(arr):for i in range(len(arr)):insertion_sort(arr)return arrarr = [4, 2, 7, 1, 5, 3]
sorted_arr = nested_insertion_sort(arr)
print(sorted_arr)

以上使用嵌套的插入排序算法对一个数组进行排序,其中外层循环对数组进行n次插入排序,而插入排序的时间复杂度为O(n^2)。 因此,整个算法的时间复杂度为 O(n^2 logn)。每次插入排序都需要O(n^2)的时间复杂度,而总共需要进行logn次插入排序。

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

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

相关文章

Linux文本编辑器vim使用和配置详解

vim介绍 ​ vim是Linux的一款文本编辑器&#xff0c;可以用来编辑代码&#xff0c;而且支持语法高亮&#xff0c;还可以进行一系列配置使vim更多样化。也可以运行于windows&#xff0c;mac os上。 ​ vim有多种模式&#xff0c;但目前我们只介绍绝大多数场景用的到的模式&…

树结构及其算法-二叉树节点的插入

目录 树结构及其算法-二叉树节点的插入 C代码 树结构及其算法-二叉树节点的插入 二叉树节点插入的情况和查找相似&#xff0c;重点是插入后仍要保持二叉查找树的特性。如果插入的节点已经在二叉树中&#xff0c;就没有插入的必要了&#xff0c;如果插入的值不在二叉树中&…

集线器、交换机、网桥、路由器、网关

目录 集线器(HUB)交换机(SWITCH)网桥(BRIDGE)路由器(ROUTER)网关(GATEWAY)交换机和路由器的区别参考 集线器(HUB) 功能 集线器对数据的传输起到同步、放大和整形的作用 属于物理层设备 工作机制 使用集线器互连而成的以太网被称为共享式以太网。当某个主机要给另一个主机发送单…

轻量封装WebGPU渲染系统示例<13>- 屏幕空间后处理效果(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/ScreenPostEffect.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 细节请见&#xff1a;引擎系统设计思路 - 用户态与系统态隔离-CSDN博客 2. 高频调用与低频调用隔离。…

【Unity实战】最全面的库存系统(五)

文章目录 先来看看最终效果前言配置商店系统数据创建另一个NPC绘制商店UI控制商店开关列出商品添加和删除物品功能添加商品到购物车购买商品购物车删除物品商店预览效果购买和出售切换出售功能保存商店数据快捷栏物品切换和使用完结 先来看看最终效果 前言 本期也是最好一期&a…

数字孪生技术与VR:创造数字未来

在当今数字化浪潮中&#xff0c;数字孪生和虚拟现实&#xff08;VR&#xff09;技术是两大亮点&#xff0c;它们以独特的方式相互结合&#xff0c;为各个领域带来了创新和无限可能。本篇文章将探讨数字孪生与VR之间的关系&#xff0c;以及它们如何共同开辟未来的新前景。 数字…

FreeRTOS_事件标志组

目录 1. 事件标志组简介 2. 创建事件标志组 2.1 函数 xEventGroupCreate() 2.2 函数 xEventGroupCreateStatic() 3. 设置事件位 3.1 函数 xEventGroupClearBits() 3.2 函数 xEventGroupClearBitsFromISR() 3.3 函数 xEventGroupSetBits() 3.4 函数 xEventGroupSetB…

项目实战:分页功能实战

1、在index.html添加点击事件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href"style/index.css"><script src"scr…

点大商城V2版 2.5.2.1 全开源独立版 多小程序端+unipp安装教程

点大商城V2是一款采用全新界面设计支持多端覆盖的小程序应用&#xff0c;支持H5、微信公众号、微信小程序、头条小程序、支付宝小程序、百度小程序&#xff0c;本程序是点大商城V2独立版&#xff0c;包含全部插件&#xff0c;代码全开源&#xff0c;并且有VUE全端代码。分销&am…

万岳讲堂:抖音小程序开发入门指南

抖音小程序可以将开发者的创意带入这个热门的应用中。本文将带您深入了解抖音小程序的开发入门指南&#xff0c;帮助您开始在这一平台上构建自己的应用。 一、什么是抖音小程序&#xff1f; 抖音小程序是一种轻量级的应用程序&#xff0c;它可以在抖音中直接运行&#xff0c;无…

Java8 Stream API全面解析——高效流式编程的秘诀

文章目录 什么是 Stream Api?快速入门流的操作创建流中间操作filter 过滤map 数据转换flatMap 合并流distinct 去重sorted 排序limit 限流skip 跳过peek 操作 终结操作forEach 遍历forEachOrdered 有序遍历count 统计数量min 最小值max 最大值reduce 聚合collect 收集anyMatch…

python 成绩统计,输出及格率和优

题目描述&#xff1a; 小蓝给学生们组织了一场考试&#xff0c;卷面总分为100分&#xff0c;每个学生的得分都是一个0到100的整数。 如果得分至少是60分&#xff0c;则称为及格。如果得分至少为85分&#xff0c;则称为优秀。 请计算及格率和优秀率&#xff0c;用百分数表示&am…

虚拟机保护工具:Zerto Virtual Replication 10.0 U1 Crack

Zerto虚拟复制是为需要保护虚拟机和应用程序的企业设计的产品。通过通过连接到广域网或云到远程站点的复制来保护虚拟机。Zerto VR 2.0还可以与vCloud Director一起将虚拟机或虚拟机组复制到云端&#xff08;或从云端&#xff09;。 事实上&#xff0c;Zerto与33家云提供商合作…

Unity在Project右键点击物体之后获取到点击物体的名称

Unity在Project右键点击物体之后获取到点击物体的名称 描述&#xff1a; 在Unity的Project右键点击物体之后选择对应的菜单选项点击之后打印出物体的名称 注意事项 如果获取到文件或者预制体需要传递objcet类型&#xff0c;然后使用 GameObject.Instantiate((GameObject)se…

WiFi模块在智能家居中的应用与优化

智能家居技术的迅速发展已经改变了我们对家庭的定义。WiFi模块作为智能设备连接的核心&#xff0c;扮演着连接和控制智能家居生态系统的关键角色。本文将深入研究WiFi模块在智能家居中的应用&#xff0c;同时探讨如何通过优化来提升其性能和用户体验。 1. 智能家居中WiFi模块的…

第二十六章 BEV感知系列三(车道线感知)

前言 近期参与到了手写AI的车道线检测的学习中去&#xff0c;以此系列笔记记录学习与思考的全过程。车道线检测系列会持续更新&#xff0c;力求完整精炼&#xff0c;引人启示。所需前期知识&#xff0c;可以结合手写AI进行系统的学习。 BEV感知系列是对论文Delving into the De…

Jenkins项目部署

使用jenkins部署项目 简易版使用jenkins部署项目 将war包部署到tomcat中 将已有的war包部署到tomcat中(jenkins与tomcat在同一台主机) 点击Jenkins主页的新建任务 输入任务名称 选择构建一个自由风格的软件项目后点击确定 在构建内添加构建步骤&#xff0c;选择执行shell 输入…

回归预测 | Matlab实现MPA-BP海洋捕食者算法优化BP神经网络多变量回归预测(多指标、多图)

回归预测 | Matlab实现MPA-BP海洋捕食者算法优化BP神经网络多变量回归预测&#xff08;多指标、多图&#xff09; 目录 回归预测 | Matlab实现MPA-BP海洋捕食者算法优化BP神经网络多变量回归预测&#xff08;多指标、多图&#xff09;效果一览基本介绍程序设计参考资料 效果一览…

数字IC后端实现 |TSMC 12nm 与TSMC 28nm Metal Stack的区别

下图为咱们社区IC后端训练营项目用到的Metal Stack。 芯片Tapeout Review CheckList 数字IC后端零基础入门Innovus学习教程 1P代表一层poly&#xff0c;10M代表有10层metal&#xff0c;M5x表示M2-M6为一倍最小线宽宽度的金属层&#xff0c;2y表示M7-M8为二倍最小线宽宽度的金…

npm的使用

package.json 快速生成package.json npm init -y “version”: “~1.1.0” 格式为&#xff1a;「主版本号. 次版本号. 修订号」。 修改主版本号是做了大的功能性的改动 修改次版本号是新增了新功能 修改修订号就是修复了一些bug dependencies "dependencies": {&…