(数据结构)复杂度

基本概念说明

数据结构

定义:数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在⼀种或多种特定关系的数据元素的集合。没有⼀种单⼀的数据结构对所有用途都有用(要考虑适配、效率问题,在不同情况下使用合适的数据结构提高效率)
如:线性表、树、图、哈希等
功能

  1. 存储数据
  2. 组织数据:增删改查数据

算法

定义:算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。
算法都有好坏之分——就由复杂度来衡量
而数据结构和算法是不分家的

复杂度引入

我们来做一道算法题
https://leetcode.cn/problems/rotate-array/description/
在这里插入图片描述
在这里插入图片描述
自测运行通过,但是提交后的样例测试没有全部通过——代码所使用的算法不够好?
我们是否可以通过一些清晰的表达方法明确地表示算法的好坏呢?

复杂度的概念

算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量⼀个算法的好坏,⼀般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。
时间复杂度主要衡量⼀个算法的运行快慢,而空间复杂度主要衡量⼀个算法运⾏所需要的额外空间
在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很⾼的程度。所以我们如今已经不需要再特别关注⼀个算法的空间复杂度。
(但是我们也不能随意浪费空间!)
时间复杂度和空间复杂度都使用大O的渐进表示法来表示,复杂度是一个函数式。

大O的渐进表示法

大O符号(Big O notation):是用于描述函数渐进行为的数学符号

推导大O阶规则

  1. 复杂度函数式T(N)中,只保留最高阶项,去掉那些低阶项,因为当N不断变大时,低阶项对结果影响越来越⼩,当N无穷时,就可以忽略不计了。
  2. 如果最高阶项存在且不是1,则去除这个项目的常数系数,因为当N不断变大,这个系数对结果影响越来越小,当N无穷大时,就可以忽略不计了。
  3. T(N)中如果没有N相关的项目,只有常数项,用常数1取代所有加法常数。

有些算法的时间复杂度存在最好、平均和最坏情况。
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
大O的渐进表示法在实际中⼀般情况关注的是算法的上界,也就是最坏运行情况。

时间复杂度运算

在计算机科学中,算法的时间复杂度是⼀个函数式T(N),它定量描述了该算法的运⾏时间。
实际中我们计算时间复杂度时,计算的也不是程序的精确的执⾏次数,精确执⾏次数计算起来还是很⿇烦的(不同的⼀句程序代码,编译出的指令条数都是不⼀样的),计算出精确的执⾏次数意义也不⼤,因为我们计算时间复杂度只是想⽐较算法程序的增⻓量级,也就是当N不断变⼤时T(N)的差别,当N不断变⼤时,常数和低阶项对结果的影响很⼩,所以我们只需要计算程序能代表增⻓量
级的⼤概执⾏次数,复杂度的表⽰通常使⽤⼤O的渐进表⽰法。
1.
在这里插入图片描述
在这里插入图片描述
2.
在这里插入图片描述
在这里插入图片描述
3.

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
5.

在这里插入图片描述
在这里插入图片描述

空间复杂度运算

空间复杂度也是⼀个数学表达式,是对⼀个算法在运⾏过程中因为算法的需要额外临时开辟的空间。空间复杂度不是程序占⽤了多少bytes的空间,因为常规情况每个对象⼤⼩差异不会很⼤,所以空间复杂度算的是变量的个数
空间复杂度计算规则基本跟实践复杂度类似,也使⽤⼤O渐进表⽰法。
注意:函数运⾏时所需要的栈空间(存储参数、局部变量、⼀些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运⾏时候显式申请的额外空间来确定
1.

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

常见复杂度对比

在这里插入图片描述

复杂度算法题

在这里插入图片描述
最后我们再回到一开始的算法题

法一

审视一下最开始的算法的时间复杂度——O(n^2)。

void rotate(int* nums, int numsSize, int k) {while(k--){int i=1;int tmp=nums[numsSize-1];for(int i=numsSize-1;i>0;i--)//注意替换元素的方向!nums[i]=nums[i-1];nums[0]=tmp;}
}

这种算法由于超出时间限制导致测试不通过,就是因为时间复杂度太高,所以现在我们需要进行优化、或者想出其他时间复杂度更低算法来解决问题。

法二:重新创建一个新数组,把nums中的元素按规律重新安置——只需要遍历一次nums数组就可完成——时间复杂度O(n)

(只要有思路,写具体代码之前就可以把时间复杂度写出来了)在这里插入图片描述

void rotate(int* nums, int numsSize, int k) {int newArray[numsSize];for(int i=0;i<numsSize;i++){newArray[(i+k)%numsSize]=nums[i];//巧用取模解决越界问题,不需要if语句分类讨论了}//将新数组导入到原数组中for(int j=0;j<numsSize;j++){nums[j]=newArray[j];}
}

在这里插入图片描述
空间复杂度是O(n),因为运行时开辟临时变量数组另外申请了numsSize个int的空间,而反观最开始的方法一,空间复杂度为O(1)
所以我们称法二是一种“用时间换空间”的方法。

法三:三次逆置

在这里插入图片描述

void reverse(int* nums,int left,int right){while(left<right){int tmp=nums[left];nums[left]=nums[right];nums[right]=tmp;left++;right--;}
}
void rotate(int* nums, int numsSize, int k) {reverse(nums,0,numsSize-k-1);reverse(nums,numsSize-k,numsSize-1);reverse(nums,0,numsSize-1);
}

但是这样写的代码运行是正确的,但是不是所有样例都通过
在这里插入图片描述
看上图分析可以得出,这是因为当k>numsSize时,这种方法会导致反转时出现数组编号为负数的越界问题。
只需要多写一句k%=numsSize即可避免越界情况。

void reverse(int* nums,int left,int right){while(left<right){int tmp=nums[left];nums[left]=nums[right];nums[right]=tmp;left++;right--;}
}
void rotate(int* nums, int numsSize, int k) {k%=numsSize;reverse(nums,0,numsSize-k-1);reverse(nums,numsSize-k,numsSize-1);reverse(nums,0,numsSize-1);
}

此算法
时间复杂度:O(n)
空间复杂度:O(1)

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

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

相关文章

玩转Docker | 使用Docker部署bender个人导航页工具

玩转Docker | 使用Docker部署bender个人导航页工具 前言 一、bender介绍 Bender 简介 Bender 的主要特点 二、系统要求 环境要求 环境检查 Docker版本检查 检查操作系统版本 三、部署bender服务 下载bender镜像 编辑部署文件 创建容器 检查容器状态 检查服务端口 安全设置 四、…

解决了困扰我的upload靶场无法解析phtml等后缀的问题

本文章为解决困扰我的 upload 靶场无法解析 phtml 问题 ​ 这个问题直接让我过不了Upload-Pass-03这一关&#xff0c;一直卡着。 ​ 痛太痛了 &#xff0c;为什么无法解析上传之后的 phtml 后缀文件&#xff01;这块儿折磨了博主一天多&#xff0c;太不容易了&#xff0c;查找…

Leetcode百题斩-二分搜索

二分搜索也是一个很有趣的专题&#xff0c;被做过的题中&#xff0c;刚好一个Easy&#xff0c;一个Medium和一个Hard&#xff0c;刚好可以看看&#xff0c;二分搜索的三个难度等级都是啥样的。 124. Binary Tree Maximum Path Sum[Hard]&#xff08;详见二叉树专题&#xff09;…

【IDEA】格式化代码工具配置

格式化代码快捷键&#xff1a; CtrlAltL格式代码的时候不会再方法名与参数中间添加空格默认不勾选的情况下&#xff1a;代码样例&#xff1a;勾选之后的样例&#xff1a;选择不勾选&#xff0c;IDEA默认情况下就是不勾选的状态忽略加载文件有些非必要加载到开发工具中的文件我们…

驱动开发(3)|rk356x驱动GPIO基础应用之点亮led灯

点亮LED灯看似是一个基础的操作&#xff0c;但实际上&#xff0c;许多高级应用也依赖于高低电平的切换。例如&#xff0c;脉冲宽度调制&#xff08;PWM&#xff09;信号可以用来精确控制电机的转速&#xff0c;通过改变脉冲的频率和占空比&#xff0c;实现对电机的精确调节&…

手动搭建PHP环境:步步为营,解锁Web开发

目录一、引言二、准备工作2.1 明确所需软件2.2 下载软件三、Windows 系统搭建步骤3.1 安装 Apache 服务器3.2 安装 PHP3.3 集成 Apache 与 PHP3.4 安装 MySQL3.5 配置 PHP 连接 MySQL四、Linux 系统搭建步骤&#xff08;以 Ubuntu 为例&#xff09;4.1 更新系统4.2 安装 Apache…

DrissionPage:一款让网页自动化更简单的 Python 库

在网页自动化领域&#xff0c;Selenium 和 Playwright 早已是开发者耳熟能详的工具。但今天要给大家介绍一款更轻量、更易用的 Python 库 ——DrissionPage。它以 "融合 selenium 和 requests 优势" 为核心设计理念&#xff0c;既能像 requests 一样高效处理静态网页…

理解Grafana中`X-Scope-OrgID`的作用与配置

X-Scope-OrgID的作用 该HTTP Header用于标识Loki日志数据的所属租户&#xff08;组织&#xff09;。在多租户模式下&#xff0c;Loki通过此Header隔离不同团队或用户的数据&#xff0c;确保查询和存储的独立性。数据隔离&#xff1a; 租户A的日志标记为X-Scope-OrgID: team-a&a…

【PycharmPyqt designer桌面程序设计】

在 main.py 中调用 Qt Designer 生成的 windows.py&#xff08;假设它是 PySide2 版&#xff09;。 只要把两个文件放在同一目录即可直接运行。 ──────────────────── 1️⃣ windows.py&#xff08;Qt Designer 生成&#xff0c;已转码&#xff09; # -*-…

Unity Android Logcat插件 输出日志中文乱码解决

背景之前安卓真机调试看日志&#xff0c;一直用的是Android Studio自带的adb命令进行看日志&#xff0c;不太方便&#xff0c;改用Unity自带的安卓日志插件时&#xff0c;存在中文日志乱码问题。插件安装基于Unity6000.1.11版本&#xff1a;Window -> Package Management -&…

Halcon双相机单标定板标定实现拼图

1.Halcon图像拼接算法在之前的文章里也写过&#xff0c;主要是硬拼接和特征点拼接两种方式&#xff0c;今天增加另一种拼接图像的方式。应用场景是多个相机联合一起拍大尺寸的物体&#xff0c;并且相机视野之间存在重叠区域。通过在同一个标定板上面标定&#xff0c;计算两个相…

动物世界一语乾坤韵芳华 人工智能应用大学毕业论文 -仙界AI——仙盟创梦IDE

提示词在一个奇幻的童话森林里&#xff0c;所有的动物都像人类一样直立行走&#xff0c;穿着各种搞怪的衣服。 一只戴着超大眼镜、穿着背带裤的乌龟&#xff0c;正一本正经地站在一个蘑菇舞台上&#xff0c;拿着一根树枝当作麦克风&#xff0c;准备唱歌。它的眼镜总是往下滑&am…

SpringBoot(原理篇)

大家好&#xff0c;这里是 盛码笔记。 本篇我们来聊一聊 Spring Boot 的“魔法”是如何实现的。你可能已经用过 Spring Boot 快速搭建项目&#xff0c;但有没有想过&#xff1a;为什么只需要引入几个 starter&#xff0c;Spring Boot 就能自动配置好整个应用环境&#xff1f; …

数据结构:栈(区间问题)

码蹄集OJ-小码哥的栈 #include<bits/stdc.h> using namespace std; #define int long long const int N1e67; struct MOOE {int ll,rr; }; stack<MOOE>st; signed main( ) {ios::sync_with_stdio(false);cin.tie(nullptr);int n;cin>>n;while(n--){int opt…

Vue 中 data、watch、created 和 methods

以下是 Vue 中 data、watch、created 和 methods 的详细解释&#xff0c;结合常见使用场景和示例&#xff1a;1. data&#xff1a;响应式数据容器 作用&#xff1a;定义组件的响应式数据&#xff08;状态&#xff09;&#xff0c;当数据变化时&#xff0c;视图自动更新。特点&a…

精密模具冷却孔内轮廓检测方法探究 —— 激光频率梳 3D 轮廓检测

引言精密模具冷却孔的内轮廓精度直接影响注塑成型效率与制品质量。冷却孔具有深径比大&#xff08;可达 25:1&#xff09;、结构复杂&#xff08;多为螺旋形或异形&#xff09;、表面质量要求高&#xff08;Ra≤0.2μm&#xff09;等特点&#xff0c;传统检测方法难以满足其高精…

Vue单文件组件与脚手架工程化开发

一、Vue与VueComponent原型关系解析1. 原型链关系图解在Vue中&#xff0c;组件实例(VueComponent)与Vue实例之间存在特殊的原型链关系&#xff1a;VueComponent.prototype.__proto__ Vue.prototype这种设计使得所有组件都能访问Vue原型上定义的方法和属性。2. 原理验证示例// …

架构设计之计算高性能——单体服务器高性能

架构设计之计算高性能——单体服务器高性能 高性能是每个程序员共同的追求&#xff0c;无论是开发系统&#xff0c;还是仅仅只是写一段脚本&#xff0c;都希望能够达到高性能的效果&#xff0c;而高性能又是软件系统设计中最复杂的一步。无论是开发千万级并发的电商系统&#…

Unity灯光面板环境设置

在Unity中&#xff0c;环境设置&#xff08;Environment Lighting&#xff09; 是灯光面板&#xff08;Lighting Window&#xff09;的核心功能之一&#xff0c;用于控制场景的全局光照效果&#xff0c;包括天空盒、环境光、反射和雾效等。这些设置直接影响场景的整体氛围和真实…

MySQL语句优化案例

1.案例in查询条件很慢其中in中共115个select id,detail_id,request,response,utime,ctime from response_detaill where detaill_id in (26371986, 26372242, 26371984, 26371990, 26400150, 26371988, 26371994, 26371992,26371998, 26371996, 26371970, 26371968, 2637197…