算法的复杂度
1.数据结构前言
下面的概念有的比较难理解,做个了结就行。
1.1数据结构的起源
在现实生活中我们更多地并不是解决数值计算的问题,而是 需要一些更科学的手段如(表,数,图等数据结构),才能更好地处理问题。所以数据结构是一门研究非数值计算的程序设计问题中的操作对象,以及他们之间的关系和操作等相关问题的学科。
1968年,美国高德纳教授在其所写的《计算机程序设计艺术》第一卷《基本算法》中,较系统的阐述了数据的逻辑结构及其操作。
1.2数据结构(Data Structure)的定义
数据结构:相互之间存在一种或者多种关系的数据元素的集合
数据元素:是组成数据的,有一定意义的基本单位,在计算机中被当做成体处理。也叫做记录。比如在人类社会中,它的数据元素就是人。畜类中,牛羊猪等就是它的数据元素。
数据项:一个数据元素可以由多个数据项组成。比如人的数据项可以由眼睛、鼻子、嘴巴等等。
数据对象:具有相同性质的数据元素的集合,是数据的子集。比如人都有生日、姓名、性别,把这些拥有相同数据项的数据元素就称为相同性质的数据元素。

1.3逻辑结构与物理结构
1.3.1逻辑结构
逻辑结构:数据元素之间的相互关系。
常见的逻辑结构:
集合结构:(”平等“)

线性结构:(一对一)

树形结构:(一对多)

图形结构:(多对多)

1.3.2物理结构
物理结构:指的是数据的逻辑结构在计算机中的存储方式
存储结构的分类:顺序存储结构、链式存储结构
顺序存储结构:把数据元素存放在连续的内存空间中,这种的结构的物理结构与逻辑结构是相同的

链式存储结构:把数据元素存放在任意的内存空间中,这个任意可以连续也可以不连续。
这种存储结构的操作是建立在指针域上的,因为你总得通过一个手段去找到这些元素。

1.4抽象数据类型
1.4.1数据类型
数据类型:只一组具有相同性质的值的集合以及定义在此集合上面的一组操作的总称。
高级语言中,类型往往指代的是变量、常量、表达式所能表示的范围,还有所能进行的+ - * /等一系列操作。
在C语言中,数据类型分为:
原子类型:不可再分的基本单位,包括整形、浮点型、字符型
结构类型:由若干个类型组合而成,可以再分。比如:一个整形数组就包含若干个整形数据。
1.4.2抽象数据类型
抽象是指抽出事物具有的本质属性。
抽象数据类型:是指一个数学模型以及定义在该模型上面的一组操作。
对于抽象数据类型,我们并不关注数据本身的物理结构,而是关注它的数学抽象特征。
一个抽象数据类型定义了:一个数据对象、数据元素中各数据元素之间的关系及对数据的操作。
2.算法的复杂度
在次之前我们先看一个例题:189. 轮转数组 - 力扣(LeetCode)

经过考虑我们可以有三种解法:
1.挨个轮转
void rotate(int* nums, int numsSize, int k) {int i=0;while(k--){int tmp=nums[numsSize-1];for(i=numsSize-1;i>0;i--){nums[i]=nums[i-1];}nums[0]=tmp;}
}

2.取余挨个轮转:
void rotate(int* nums, int numsSize, int k) {int i=0;k%=numsSize;while(k--){int tmp=nums[numsSize-1];for(i=numsSize-1;i>0;i--){nums[i]=nums[i-1];}nums[0]=tmp;}
}

3.面向结果编程:
void rotate(int* nums, int numsSize, int k) {int ans[numsSize];int i=0;for(i=0;i<numsSize;i++){ans[(i+k)%numsSize]=nums[i];}for(i=0;i<numsSize;i++){nums[i]=ans[i];}}

4.三次逆序法:
void Reverse(int* nums,int low,int high){while(low<high){int tmp=nums[low];nums[low]=nums[high];nums[high]=tmp;low++;high--;}
}
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);}

2.1时间复杂度
先说明一下:上述方法的1、2的关系为优化。3、4是使用了不同的算法。
2.1.1时间复杂度的定义
时间复杂度:在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)数量级。算法的时间复杂度,也就是算法的时间量度,记作T(n)=O(f(n))。它表示随着问题规模n的增大,算法的执行时间的增长率和符f(n)的增长率相同,称作算法的渐进时间复杂度,简称时间复杂度。其中符f(n)是问题规模n的某个函数。
这里我们从定义中提取几个关键点:
1.算法时间复杂度是算法渐进时间复杂度的简称。
2.它表示的是一种变化趋势(随问题规模)或者增长率。
3.并不是一个确切的语句到底执行多少次的函数表达式。
2.1.2算法时间复杂度的大O渐进表示法
💡 推导⼤O阶规则1. 时间复杂度函数式 T(N) 中,只保留最⾼阶项,去掉那些低阶项,因为当 N 不断变大时,低阶项对结果影响越来越小,当 N 无穷大时,就可以忽略不计了。2. 如果最高阶项存在且不是 1 ,则去除这个项目的常数系数,因为当 N 不断变大,这个系数对结果影响越来越小,当 N 无穷大时,就可以忽略不计了。3. T(N) 中如果没有 N 相关的项目,只有常数项,用常数 1 取代所有加法常数。




2.1.3算法时间复杂度的例题:
2.1.3.1
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);
}
T(n)=2*n+10(只关注循环的额外开销)
时间复杂度:O(n)
2.1.3.2
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);
}
同样的时间复杂度:O(n)
2.1.3.3
void Func4(int N)
{
int count = 0;
for (int k = 0; k < 100; ++ k)
{
++count;
}
printf("%d\n", count);
}
O(1)
2.1.3.4
const char * strchr ( const char
* str, int character)
{
const char* p_begin = s;
while (*p_begin != character)
{
if (*p_begin == '\0')
return NULL;
p_begin++;
}
return p_begin;
}
这是一个查找某个字符的算法,但是不同情况有不同的复杂度有不同划分:
假设要找的就在第一个字符位置(或常数个):T(n)=k(常数) --> O(1)4
假设要找的在最后一个位置:T(n)=n --> O (n)
假设要找的在中间:T(n)=n/2 --> O(n)

2.1.3.5
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;
}
}
T(n)=N*(N+1)/2 -->O(n)=n^2
2.1.3.6
void func5(int n)
{
int cnt = 1;
while (cnt < n)
{
cnt *= 2;
}
}
O(n)=logn 这里写成lnn lgn都行,因为我们说时间复杂度表示的是变化率,所以只需要表示出来对数阶就可以。
2.1.3.7
递归的时间复杂度
// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{
if(0 == N)
return 1;
return Fac(N-1)*N;
}
O(n)=n
递归时间复杂度的求法=单次递归的时间复杂度*递归次数
2.1.4常见的时间复杂度
![]()

2.2.空间复杂度
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;
}
} 由于额外开辟的空间仅是几个常量所以空间复杂度为O(1)
3.轮转数组复杂度分析
法一:O(n^2) O(1)
法二:O(n^2) O(1)
法三:O(n) O(n)
法四:O(n) O(1)
完
相关文章:
算法的复杂度
1.数据结构前言 下面的概念有的比较难理解,做个了结就行。 1.1数据结构的起源 在现实生活中我们更多地并不是解决数值计算的问题,而是 需要一些更科学的手段如(表,数,图等数据结构),才能更好…...
Linux命令进阶·如何切换root以及回退、sudo命令、用户/用户组管理,以及解决创建用户不显示问题和Ubuntu不显示用户名只显示“$“符号问题
目录 1. root用户(超级管理员) 1.1 用于账户切换的系统命令——su 1.2 退回上一个用户命令——exit 1.3 普通命令临时授权root身份执行——sudo 1.3.1 为普通用户配置sudo认证 2. 用户/用户组管理 2.1 用户组管理 2.2 用户管理 2.2.1 …...
若依项目源码阅读
源码阅读 前端代码分析 代码生成器生成的前端代码有两个,分别是course.js用于向后端发送ajax请求的接口代码,另一个是index.vue,用于在浏览器展示课程管理的视图组件。前端的代码是基于vue3elementplus。 template用于展示前端组件别的标签…...
JVM知识点学习-1
学习视频:狂神说Java 类加载器和双亲委派机制 类加载器 作用:加载Class文件 流程:这里的名字car1。。在栈里面,但是数据在堆里面 类加载器的几个类型: 虚拟机自带的类加载器;启动类(根Boot…...
TypeScript和JavaScript区别详解
文章目录 TypeScript和JavaScript区别详解一、引言二、类型系统1、静态类型检查TypeScript 示例JavaScript 示例 2、类型推断TypeScript 示例JavaScript 示例 三、面向对象编程TypeScript 示例JavaScript 示例 四、使用示例1. 环境搭建2. 创建TypeScript项目3. 安装TypeScript插…...
RVO动态避障技术方案介绍
原文:RVO动态避障技术方案介绍 - 哔哩哔哩 我们在开发游戏的时候经常会遇到这样的问题,当我们寻路的时候,其它人也在寻路,如何避免不从其它人的位置穿过。这个叫做动态避障,目前主流的解决方案就是RVO。本节我们来介绍…...
Vue进阶之单组件开发与组件通信
书接上篇,我们了解了如何快速创建一个脚手架,现在我们来学习如何基于vite创建属于自己的脚手架。在创建一个新的组件时,要在新建文件夹中打开终端创建一个基本的脚手架,可在脚手架中原有的文件中修改或在相应路径重新创建…...
OGRE 3D----5. OGRE和QML事件交互
在现代图形应用程序开发中,OGRE(Object-Oriented Graphics Rendering Engine)作为一个高性能的3D渲染引擎,广泛应用于游戏开发、虚拟现实和仿真等领域。而QML(Qt Modeling Language)则是Qt框架中的一种声明式语言,专注于设计用户界面。将OGRE与QML结合,可以充分利用OGR…...
ARIMA-神经网络混合模型在时间序列预测中的应用
ARIMA-神经网络混合模型在时间序列预测中的应用 1. 引言 1.1 研究背景与意义 时间序列预测在现代数据科学中扮演着越来越重要的角色。从金融市场的价格走势到工业生产的需求预测,从气象数据的天气预报到用电量的负荷预测,时间序列分析无处不在。传统的统计方法和现代深度学习…...
常见靶场的搭建
漏洞靶场 渗透测试(漏洞挖掘)切忌纸上谈兵,学习渗透测试(漏洞挖掘)知识的过程中,我们通常需要一个包含漏洞的测试环境来进行训练。而在非授权情况下,对于网站进行渗透测试攻击,是触及…...
[MacOS] [kubernetes] MacOS玩转虚拟化最佳实践
❓ 为什么不在MacOS本机安装呢?因为M系列芯片是Arm架构,与生产环境或者在本地调试时候,安装虚拟镜像和X86不同,造成不必要的切换环境的额外成本,所以在虚拟化的x86调试 步骤 & 详情 一: 安装OrbStack & 并配置…...
HarmonyOS:@Provide装饰器和@Consume装饰器:与后代组件双向同步
一、前言 Provide和Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,Provide和Consume摆脱参数传递机制的束缚,实现跨层级传递。 其中Provi…...
git 上传代码时报错
在上传代码时,显示无法上传 PS E:\JavaWeb\vue3-project> git push To https://gitee.com/evening-breeze-2003/vue3.git! [rejected] master -> master (non-fast-forward) error: failed to push some refs to https://gitee.com/evening-breeze-20…...
判断1456789876541是否为素数,是输出“是素数“,不是则输出“不是素数“
题目描述 判断1456789876541是否为素数,是输出"是素数",不是则输出"不是素数" 代码实现 int main() { long long n 1456789876541; //for (long long i 2; i < n; i)//数据量太大 for(long long i2;i<sqrt(n);i)//素数的优化 { if (n % i 0) …...
Flutter:封装发送验证码组件,注册页使用获取验证码并传递控制器和验证码类型
验证码:view import package:flutter/material.dart; import package:get/get.dart; import index.dart;class SendcodePage extends GetView<SendcodeController> {// 接收注册页面,传进来的手机号控制器,和发送验证码的类型final Tex…...
亚马逊IP关联是什么?
亚马逊不仅提供了广泛的商品和服务,也是许多企业和个人选择的电子商务平台。然而,与亚马逊相关的IP关联问题,特别是在网络安全和运营管理方面,经常成为使用亚马逊服务的用户和商家关注的焦点。通过了解亚马逊IP关联的含义、可能的…...
Electron + vue3 打包之后不能跳转路由
路由不跳转问题原因: 是因为electron需要将vue-router的mode调整为hash模式(两种写法) export default new Router({mode: hash, //这里history修改为hashscrollBehavior: () > ({y: 0}),routes: constantRouterMap, }) export default new createRouter({his…...
docker安装clickhouse副本集群
docker安装clickhouse副本集群 1、clickhouse副本集群搭建1.1、docker安装zookeeper集群1.1.1、zookeeper第一个节点安装1.1.2、zookeeper第二个节点安装1.1.3、zookeeper第三个节点安装1.1.4、zookeeper客户端命令 2、Clickhouse副本集群搭建2.1、clickhouse搭建2.2、验证集群…...
vue超过三行显示省略号和查看更多按钮
1、超过3行显示省略号和更多按钮,不超过3行正常显示; html: <div class"container"><div style"display: flex;"><div class"content"><div class"text-content" ref"textContentR…...
【软考速通笔记】系统架构设计师⑤——软件工程基础知识
文章目录 一、前言二、基础知识点2.1 软件危机2.2 软件生命周期 三、软件过程模型(论文)3.1 瀑布模型3.2 原型模型3.3 螺旋模型3.4 敏捷模型3.5 软件统一过程模型3.6 软件成熟度模型3.7 软件成熟度模型集成 四、需求工程五、软件测试5.1 根据程序执行状态…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
