当前位置: 首页 > news >正文

《数据结构初阶》【时间复杂度 + 空间复杂度】

《数据结构初阶》【时间复杂度 + 空间复杂度】

  • 前言:
  • -----------------------------------------
    • 1. 什么是数据结构?
    • 2. 什么是算法?
  • -----------------------------------------
  • 算法的时间复杂度和空间复杂度
    • 1. 为什么要引入时间复杂度和空间复杂度?
    • 2. 什么是时间复杂度和空间复杂度?
    • 3. 常见的时间复杂度类型有哪些?
    • 4. 常见的空间复杂度类型有哪些?
    • 5. 为什么选择使用时间复杂度和空间复杂度?
    • 6. 我们要怎么表示时间复杂度和空间复杂度?
    • 7. 时间复杂度分为哪些?
  • -----------------------------------------
  • 常见时间复杂度计算举例
    • 常数阶O(1)
    • 对数阶O(nlogn)
    • 线性阶O(n)
    • 平方阶O(n^2)
    • 指数阶O(2^n)
  • -----------------------------------------
  • 常见空间复杂度计算举例
    • 常数阶O(1)
    • 线性阶O(n)
  • -----------------------------------------
  • 复杂度的oj练习
    • [面试题 17.04. 消失的数字](https://leetcode.cn/problems/missing-number-lcci/)
      • 题目介绍
      • 方法一:
      • 方法二:
    • [189. 轮转数组](https://leetcode.cn/problems/rotate-array/)
      • 题目介绍
      • 方法一:
        • 算法思想演示

前言:

hi~,正在看这篇博客的小伙伴,如果你之前看过博主的博客的话,此时内心应该不禁感叹:这博主是不是又打算挖个坑就跑?,(因为这个博主之前挖过:《C语言系列》、《算法基础》、《算法精讲》这些坑,其中《C语言系列》的坑都长草了吧?🤔,今天又打算再一个新坑吗?)


博主先在这里声明一下:博主是一个有头有尾有始有终的人,
"你们要相信我!每一个坑都是真爱!只是它们……在等一个合适的时机成熟!🫠
例如:《C语言系列》还剩下:“复合结构体 + 文件操作” 这两部分的内容的没有更新,博主预估想完结《C语言系列》至少还需要4篇博客,由于博主现在的重心不是学习C语言,所以可能会鸽很久 (在这个以视频学习为主的时代,也不知道有没有人看),不过博主的博客当笔记来看是最好的,因为内容较全,拿来复习是很不错的😍
而《算法基础》、《算法精讲》接下来可能就是偶尔更一下了,
《数据结构初阶》将是博主接下来持续更新的内容了,博客内容主要划分为:数据结构的介绍 + 数据结构的实现 + 数据结构的OJ练习


祝愿:希望《数据结构初阶》系列的内容可以帮助到大家~
(如果没帮到也不要紧,至少你收获了 “原来还有人比我更菜” 的心理安慰😂)

-----------------------------------------

1. 什么是数据结构?

既然是学习 《数据结构》 这门课程,那么我们要思考的第一个问题无疑就是: 什么是数据结构?

数据结构:是计算机科学中用于组织存储管理数据的一种 方式

  • 用于实现高效的数据访问修改操作

  • 它定义了数据元素之间的 逻辑关系存储方式 以及 相关的操作(如:增删查改),是算法设计和程序优化的基础

2. 什么是算法?

俗话说的好:数据结构与算法不分家(其实是我说的)

那么接下来也一并见见的他的妻子(😂)

算法 :是解决特定问题的一系列明确有限步骤

  • 用于对数据进行计算、处理或自动化决策。
  • 它是计算机程序的逻辑核心,决定了程序的效率和正确性。

-----------------------------------------

算法的时间复杂度和空间复杂度

1. 为什么要引入时间复杂度和空间复杂度?

疑问:算法种类繁多,千奇百怪,面对具体的问题我们要选择什么样的算法才是最好的选择呢?或者也可以理解为:看到一种算法我们怎么知道它是好还是坏呢?

示例:比如对于下面这个求斐波那契数列的算法:

long long Fib(int N) 
{if(N < 3)return 1;return Fib(N-1) + Fib(N-2);
}

思考:这种递归实现的算法非常的简洁,但是简洁就一定好吗?换句话说:难道简洁是衡量一个算法的好坏的标准吗?如果不是那我们要使用什么来衡量一个算法的好与坏呢?


回答:我们可以使用下面的两把 “尺子” 来衡量解决这个问题的算法中的那个是最好的。

而这两把尺子分别是:时间复杂度空间复杂度

思考与探究:我们怎么想到了用这两个维度的信息进行衡量一个算法的好坏呢?


回答:算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。

因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即:时间复杂度和空间复杂度。

2. 什么是时间复杂度和空间复杂度?

时间复杂度:是衡量算法 运行时间随输入规模 n 增长的变化趋势的指标。

  • 它不计算具体的执行时间,而是分析算法执行的基本操作次数的增长规律,并用数学符号(如:大O表示法)描述其渐进上界

空间复杂度:是衡量算法 运行所使用的内存空间随输入规模 n 增长的变化趋势的指标。

  • 它不计算具体的内存占用大小,而是分析算法运行过程中所需的额外存储空间的增长规律,空间复杂度也用大O表示法(Big-O Notation)其渐进上界

注意:函数运行时所需要的栈空间(存储参数局部变量、一些寄存器信息等……)在编译期间已经确定好了。

因此:空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。


所以:这里说的直白一点就是时间复杂度和空间复杂度其实你也可以理解为:他们俩其实就是一个函数,具体一点就是一个

  • 时间复杂度:运行时间(y)输入规模 (n) 的函数
  • 空间复杂度:运行所使用的内存空间 (y)输入规模 (n) 的函数

只不过函数是什么类型的函数我们并不清楚?

3. 常见的时间复杂度类型有哪些?

也可以理解为函数的类型:

在这里插入图片描述

时间复杂度名称示例算法时间增长趋势
O ( 1 ) O(1) O(1)常数时间数组随机访问(arr[i]不随 n n n 增长
O ( log ⁡ n ) O(\log n) O(logn)对数时间二分查找、平衡树(AVL树)增长极慢
O ( n ) O(n) O(n)线性时间遍历数组、链表 n n n 成正比
O ( n l o g n ) O(nlog n) O(nlogn)线性对数时间快速排序、归并排序 O ( n ) O(n) O(n) 稍慢
O ( n 2 ) O(n^2) O(n2)平方时间冒泡排序、选择排序数据量大时性能差
O ( 2 n ) O(2^n) O(2n)指数时间穷举法(如:斐波那契递归)计算量爆炸式增长
O ( n ! ) O(n!) O(n!)阶乘时间旅行商问题(暴力解法)几乎不可计算

4. 常见的空间复杂度类型有哪些?

在这里插入图片描述

空间复杂度名称示例场景内存增长趋势
O ( 1 ) O(1) O(1)常数空间变量交换、原地排序(如:冒泡排序)不随 n n n 变化
O ( n ) O(n) O(n)线性空间数组拷贝、哈希表存储 n n n 成正比
O ( n 2 ) O(n^2) O(n2)平方空间二维矩阵、邻接矩阵存储图 n 2 n^2 n2 增长
O ( log ⁡ n ) O(\log n) O(logn)对数空间递归调用栈(如:二分查找的递归实现) O ( n ) O(n) O(n) 增长更慢

5. 为什么选择使用时间复杂度和空间复杂度?

疑问:如果想要计算时间复杂度和空间复杂度的话,我们直接找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况,这样不就比较出这两种算法谁好谁差了吗?有必要使用一个函数进行表示吗?


直接原因:直接运行测试的局限性

(1) 硬件依赖性

  • 不同设备性能差异:同一算法在低配手机和高性能服务器上运行时间可能差几十倍,无法客观比较算法优劣。
  • 后台进程干扰:计算机同时运行的其他程序(如杀毒软件、浏览器)会占用资源,影响测试结果。

(2) 数据规模的影响

  • 小规模数据无法反映趋势
    • 当输入规模 n n n 很小时, O ( n 2 ) O(n^2) O(n2) 的算法可能比 O ( n log ⁡ n ) O(n \log n) O(nlogn) 更快(因为常数项或低阶项主导)
    • 但当 n n n 增长到百万级时, O ( n 2 ) O(n^2) O(n2) 的算法会变得极慢,而实际测试可能无法覆盖所有规模

(3) 编程语言和实现的差异

  • 语言特性影响:Python 的列表操作比 C++ 的向量慢,但这不代表算法本身效率低。
  • 代码优化干扰:编译器优化(如:循环展开、内联函数)可能让同一算法的不同实现表现迥异。

(4) 测试成本高

  • 穷举所有输入不现实:算法可能在某些特殊输入下表现极差(如:快速排序的最坏情况 O ( n 2 ) O(n^2) O(n2) ,但测试时未必能覆盖到。

实际测试 vs 复杂度分析的关系:

对比维度实际运行测试复杂度分析
结果性质具体数值(如 3ms、5MB)抽象趋势(如 O ( n log ⁡ n ) O(n \log n) O(nlogn) )
适用范围特定设备、特定输入通用理论模型
成本需实现代码并多次运行纸笔推导即可
核心作用验证实际性能、调优参数算法设计阶段的比较与选择

6. 我们要怎么表示时间复杂度和空间复杂度?

疑问:时间复杂度分析算法执行的基本操作次数,这这……好分析吗?这应该会很麻烦吧?真的可以用笔和纸就算出来了吗?


回答:实际中我们计算时间复杂度时,我们其实并不需要要计算精确的执行次数,而只需要计算大概执行次数,因为这里我们使用的是:大O的渐进表示法

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


你现在心里一定在想:说的好像很有道理,但是事实真的如你所说的只用计算一个渐进的值就可以吗?

示例

// 请计算一下Func1中count++语句总共执行了多少次?
void Func1(int N)
{int count = 0;for (int i = 0; i < N; ++i){for (int j = 0; j < N; ++j){count++;}}//执行了N^2次的count++语句for (int k = 0; k < 2 * N; ++k){count++;}//执行了2N次的count++语句int M = 10;while (M--){count++;}//执行了10次的count++语句printf("%d\n", count);
}

第一种方案:使用大O的渐进表示法:时间复杂度为 O ( N 2 ) O(N^2) O(N2)

假如:我们的N取下面的不同的值,我们观察一下count++语句都具体执行了多少次?

N = 10 -------- F(N) = 100

N = 100 ------- F(N) = 10000

N = 1000 ----- F(N) = 1000000


第二种方案:使用精确计算程序的执行的次数

Func1 执行的基本操作次数 :(主要分为三部分)

将三部分的 count++ 执行次数相加:
t e x t 总次数 = N 2 + 2 N + 10 text{总次数} = N^2 + 2N + 10 text总次数=N2+2N+10


假如:我们的N取下面的不同的值,我们观察一下count++语句都具体执行了多少次?

N = 10 -------- F(N) = 130 (第一部分:100;第二部分:20;第三部分:10)

N = 100 ------- F(N) = 10210 (第一部分:10000;第二部分:200;第三部分:10)

N = 1000 ----- F(N) = 1002010 (第一部分:1000000;第二部分:2000;第三部分:10)


通过上面两种分析时间复杂度的方法的比较我们发现:

使用大O的渐进表示法不仅可以快速的计算出一个算法大致的执行的次数,并且计算结果与精确值的量级是一致的(误差不大)

我想大家的心里一定在想

  1. 使用大O的渐进表示法我们只保留了计算出来了最高阶项的值,而直接忽略了低阶项的值,如果哪一天所有的低阶项的值的和已经几乎和高阶项相等了,我看你还怎么忽视?(例如:程序总共执行了1999次:一个高阶项贡献1000次,所有的低阶项贡献999次)(哼🫠)
  2. 好就算你有理由说是:“最高阶项的贡献还是比所有的低阶项多”,但是当我的N取得很小呢?(例如:上面的N取1,程序总共执行了13次,一个高阶项贡献1次,所有的低阶项贡献12次)(哈哈😄,看你怎么办)

大家的问题真是:夺命两连问啊?,幸好博主早有准备(🐕没有狗头就拿狗来代替吧

其实大O的渐进表示法可以有以下两种方式得来:

  • 直接看程序中执行次数最多的那一部分其他的细枝末节的直接忽略,即:直接锚定高阶项,得到的就是大O的渐进表示法的形式
  • 间接通过程序精确的执行次数,来进一步得到大O的渐进表示法的形式
    • 第一步:忽略所有 低次幂项
    • 第二步:忽略 最高次幂的系数

所以的小可爱你的第一问已经被我迎刃而解了,由于还要要忽略 最高次幂的系数,所以对于时间复杂度来说:执行1000次和执行9999次是同一个复杂度的啦~


至于第二问的疑问源于:你忽略了一个时间复杂的定义中的一点“是衡量算法 运行时间随输入规模 n 增长的变化趋势的指标

也就是说:其实任何算法在输入规模比较小的时候,程序执行的时间是没什么差异的,你也可以理解为在输入规模很小的时候,它们是一样好的。

因为:CPU的执行速度非常的快,快到即使你的CPU性能再差再差,它每秒也可执行上亿次。

(CPU中有一个概念CPU主频:主频越高,通常意味着CPU的处理速度更快)


算法在时间上的差异主要体现在当输入规模不断变大的时候它们的执行时间开始有了不同程度的变慢,即:有的是一下就变慢了,有的则是缓慢变慢了,有的则是没什么明显差别。

7. 时间复杂度分为哪些?

最坏时间复杂度(Worst-Case Time Complexity):算法在最不利输入情况下的时间增长趋势(上界)

  • 作用:保证算法性能的下限,确保任何情况下都不会比这更差

最好时间复杂度(Best-Case Time Complexity):算法在最理想输入情况下的时间增长趋势(下界)

  • 作用:反映算法在最优场景下的潜力,但实际意义有限。

平均时间复杂度(Average-Case Time Complexity):算法在所有可能输入*的期望时间成本(需假设输入的概率分布)

  • 作用:更贴近实际应用场景的综合性能评估。

示例:例如,在一个长度为N数组中搜索一个数据x

最好情况:1次找到

最坏情况:N次找到

平均情况:N/2次找到

三者的对比与意义

类型关注点数学表示实际应用价值
最坏性能保障上界(Big-O)关键系统(如:医疗、航天)必须考虑
最好理想场景下界(Big-Omega)理论分析,实际参考价值较低
平均综合表现期望值(Big-Theta)通用算法评估(如:数据库索引设计)

经典算法示例分析:

1. 快速排序

  • 最坏 O ( n 2 ) O(n^2) O(n2)(输入已有序,分区极度不平衡)
  • 最好 O ( n log ⁡ n ) O(n \log n) O(nlogn)(每次分区均匀)
  • 平均 O ( n log ⁡ n ) O(n \log n) O(nlogn)(随机化输入或随机化分区策略)

2. 二分查找

  • 最坏 O ( l o g n ) O(log n) O(logn)(元素不存在或位于两端)
  • 最好 O ( 1 ) O(1) O(1)(目标元素正好是中间元素)
  • 平均 O ( l o g n ) O(log n) O(logn)(假设目标元素等概率分布)

3. 冒泡排序

  • 最坏 O ( n 2 ) O(n^2) O(n2) (输入逆序,需完全比较)
  • 最好 O ( n ) O(n) O(n)(输入已有序,一次遍历即结束)
  • 平均 O ( n 2 ) O(n^2) O(n2)(随机排列时仍需多次交换)

-----------------------------------------

常见时间复杂度计算举例

常数阶O(1)

//Func2的时间复杂度
void Func2(int N) 
{int count = 0;for (int k = 0; k < 100; ++k) // 固定循环100次{  count++;}printf("%d\n", count);
}

答案

  • 时间复杂度 O ( 1 ) O(1) O(1)
  • 原因:循环次数固定为100次,与输入规模 N N N 无关。

对数阶O(nlogn)

//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 - 1;elsereturn mid;}return -1;
}

答案

  • 时间复杂度 O ( l o g n ) O(log n) O(logn)
  • 原因:每次迭代将搜索范围缩小一半,最坏情况下需执行 l o g 2 n log_2 n log2n 次。

在这里插入图片描述

线性阶O(n)

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

答案

  • 时间复杂度 O ( n ) O(n) O(n)
  • 原因:主导项是 (2N)。常数项(10次)和系数(2)在渐进分析中忽略。
//strchr 的时间复杂度
const char* strchr(const char* str, int character);

答案

  • 时间复杂度 O ( n ) O(n) O(n)
  • 原因:最坏情况下需遍历整个字符串(长度为 n )才能找到目标字符或到达结尾。
//Func4的时间复杂度
void Func3(int N, int M) 
{int count = 0;for (int k = 0; k < M; ++k) // 循环M次{  ++count;}for (int k = 0; k < N; ++k) // 循环N次{  ++count;}printf("%d\n", count);
}

答案

  • 时间复杂度 O ( M + N ) O(M + N) O(M+N)
  • 原因:两段循环分别依赖 M M M N N N,无法进一步简化。
//阶乘递归 Fac 的时间复杂度
long long Fac(size_t N) 
{if (N == 0)  return 1;return Fac(N - 1) * N;  // 递归调用N次
}

答案

  • 时间复杂度 O ( n ) O(n) O(n)
  • 原因:递归深度为 N N N,每次递归执行常数时间操作。

平方阶O(n^2)

//BubbleSort(冒泡排序)的时间复杂度
void BubbleSort(int* a, int n) 
{assert(a);for (size_t end = n; end > 0; --end) // 外层循环n次{      int exchange = 0;for (size_t i = 1; i < end; ++i) // 内层循环最多n-1次{      if (a[i - 1] > a[i]) {Swap(&a[i - 1], &a[i]);exchange = 1;}}if (exchange == 0) break;  // 优化:提前终止}
}

答案

  • 最坏时间复杂度 O ( n 2 ) O(n^2) O(n2)(输入完全逆序时,需完整比较)。
  • 最好时间复杂度 O ( n ) O(n) O(n)(输入已有序时,仅需一次遍历)。
  • 平均时间复杂度 O ( n 2 ) O(n^2) O(n2)

指数阶O(2^n)

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

答案

  • 时间复杂度 O ( 2 N ) O(2^N) O(2N)
  • 原因:递归树呈指数增长,每层调用次数约为 2 N 2^N 2N

在这里插入图片描述

总结

函数时间复杂度关键原因
Func2 O ( 1 ) O(1) O(1)固定循环次数
BinarySearch O ( log ⁡ n ) O(\log n) O(logn)每次范围减半
Func3 O ( N ) O(N) O(N)主导项为 2 N 2N 2N
strchr O ( n ) O(n) O(n)线性遍历字符串
Func4 O ( M + N ) O(M + N) O(M+N)两段独立循环
Fac(阶乘) O ( N ) O(N) O(N)递归深度为 N N N
BubbleSort O ( n 2 ) O(n^2) O(n2)(最坏)双重循环
Fib(斐波那契) O ( 2 N ) O(2^N) O(2N)递归树指数增长

-----------------------------------------

常见空间复杂度计算举例

常数阶O(1)

//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;}
}

答案

  • 空间复杂度 O ( 1 ) O(1) O(1)
  • 原因:仅使用了常数个额外变量(endexchangei),与输入规模 n n n 无关。
  • 关键点:冒泡排序是原地排序算法,不依赖额外存储空间。

线性阶O(n)

//Fibonacci的空间复杂度
long long* Fibonacci(size_t n) 
{if (n == 0) return NULL;long long* fibArray = (long long*)malloc((n + 1) * sizeof(long long));fibArray[0] = 0;fibArray[1] = 1;for (int i = 2; i <= n; ++i) {fibArray[i] = fibArray[i - 1] + fibArray[i - 2];}return fibArray;
}

答案

  • 空间复杂度 O ( n ) O(n) O(n)
  • 原因:动态分配了大小为 n + 1 n+1 n+1 的数组 fibArray,空间占用与输入规模 n n n 成正比。
// 阶乘递归Fac的空间复杂度
long long Fac(size_t N) 
{if (N == 0)  return 1;return Fac(N - 1) * N;
}

答案

  • 空间复杂度 O ( n ) O(n) O(n)
  • 原因:递归深度为 N N N,每次递归调用会在调用栈中保存一帧(包括:返回地址、局部变量等),共占用 O ( n ) O(n) O(n) 的栈空间。

总结

函数/算法空间复杂度关键原因
BubbleSort O ( 1 ) O(1) O(1)仅使用常数个额外变量
Fibonacci O ( n ) O(n) O(n)动态分配了大小为 n + 1 n+1 n+1 的数组
Fac(阶乘递归) O ( n ) O(n) O(n)递归深度为 N N N,栈空间线性增长

-----------------------------------------

复杂度的oj练习

面试题 17.04. 消失的数字

题目介绍

在这里插入图片描述

方法一:

class Solution 
{
public:int missingNumber(vector<int>& nums) {//第一种思路://1.先将数字0~n的和求出来//2.接着将这个和减去数组nums中的每一个元素//这样最终得到的结果就是消失的数字//1.int n=nums.size();int sum=(0+n)*(n+1)/2;//2.for(auto it:nums){sum-=it;}return sum;}
};

方法二:

class Solution 
{
public:int missingNumber(vector<int>& nums) {// 第二种思路:// 1.将数组中的所有的元素都于值为0的x进行异或// 2.再将这个值和0~n的每个值进行异或//最终x的值就是消失的数字//1.int x = 0;for (auto it : nums) {x ^= it;}// 2.for (int i = 0; i <= nums.size(); i++) {x ^= i;}return x;}
};

异或运算(XOR)有几个重要特性

  1. 任何数和自身异或结果为0a ^ a = 0
  2. 任何数和0异或结果为它本身a ^ 0 = a
  3. 异或运算满足交换律和结合律

算法思路

  1. 假设完整的数字序列是 0, 1, 2, ..., n,共 n+1 个数字
  2. 给定的数组 nums 包含这 n+1 个数字中的 n 个(缺少一个)
  3. 如果我们把所有数字(包括缺失的)都异或在一起,再异或上数组中的所有数字,结果就是缺失的数字

疑问:这个算法为什么是有效的?

假设数组是 [3,0,1],缺失的数字是2:

  1. 第一步异或数组元素:x = 3 ^ 0 ^ 1
  2. 第二步异或完整序列:x = (3 ^ 0 ^ 1) ^ 0 ^ 1 ^ 2 ^ 3
  3. 根据交换律重新排列:(0 ^ 0) ^ (1 ^ 1) ^ (3 ^ 3) ^ 2
  4. 简化后:0 ^ 0 ^ 0 ^ 2 = 2

189. 轮转数组

题目介绍

在这里插入图片描述

方法一:

class Solution 
{
public://实现:逆置数组元素的函数void reverse(vector<int>& nums,int l,int r){//使用:遍历同一个数组中元素的对撞指针:for(int left=l,right=r;left<=right;left++){int tmp=0;tmp=nums[left];nums[left]=nums[right];nums[right]=tmp;//更新right指针right--;}}void rotate(vector<int>& nums, int k) {//思路:使用3段逆置://1.前n-k个元素的逆置//2.后k个元素的逆置//3.整体的逆置int n=nums.size();k%=n;//1.reverse(nums,0,n-k-1);//2.reverse(nums,n-k,n-1);//3.reverse(nums,0,n-1);}
};
算法思想演示

在这里插入图片描述

相关文章:

《数据结构初阶》【时间复杂度 + 空间复杂度】

《数据结构初阶》【时间复杂度 空间复杂度】 前言&#xff1a;-----------------------------------------1. 什么是数据结构&#xff1f;2. 什么是算法&#xff1f; -----------------------------------------算法的时间复杂度和空间复杂度1. 为什么要引入时间复杂度和空间复…...

【深度学习—李宏毅教程笔记】Self-attention

目录 一、Self-attention 的引入 1、多样化的输入形式 2、典型的下游任务下游任务 3、传统“全连接 窗口”方法的局限 4、Self‑Attention 的引入 二、Self-attention 的架构 1、Self-attention层的框图表示 2、Self-attention 层的矩阵运算过程 三、Multi-head Self…...

PHP腾讯云人脸核身获取Access Token

参考腾讯云官方文档&#xff1a; 人脸核身 获取 Access Token_腾讯云 public function getAccessToken(){$data [appId > , //WBappid,https://cloud.tencent.com/document/product/1007/49634secret > ,grant_type > client_credential, //授权类型version > 1…...

pytorch基本操作2

torch.clamp 主要用于对张量中的元素进行截断&#xff08;clamping&#xff09;&#xff0c;将其限制在一个指定的区间范围内。 函数定义 torch.clamp(input, minNone, maxNone) → Tensor 参数说明 input 类型&#xff1a;Tensor 需要进行截断操作的输入张…...

Linux服务器配置Anaconda环境、Pytorch库(图文并茂的教程)

引言&#xff1a;为了方便后续新进组的 师弟/师妹 使用课题组的服务器&#xff0c;特此编文&#xff08;ps&#xff1a;我导从教至今四年&#xff0c;还未招师妹&#xff09; ✅ NLP 研 2 选手的学习笔记 笔者简介&#xff1a;Wang Linyong&#xff0c;NPU&#xff0c;2023级&a…...

idea 许可证过期

今天打开IDEA写代码突然提示&#xff1a;Your idea evaluation has expired. Your session will be limited to 30 minutes 评估已过期&#xff0c;您的会话将限制为 30 分钟。也就是说可以使用&#xff0c;但30min就会自动关闭 1 下载 ide-eval-resetter-2.1.6.zip https…...

Git常用命令分类汇总

Git常用命令分类汇总 一、基础操作 初始化仓库git init添加文件到暂存区git add file_name # 添加单个文件 git add . # 添加所有修改提交更改git commit -m "提交描述"查看仓库状态git status二、分支管理 创建/切换分支git branch branch_name …...

归并排序:数据排序的高效之道

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

分布式训练(记录)

为什么要分布式训练&#xff1f; 单机训练有物理上限&#xff1a; 显存不够&#xff08;大模型根本放不下&#xff09; 单机计算慢&#xff08;数据量一多就耗时太长&#xff09; 多卡并行性不高 分布式训练的常见方式 Data Parallel&#xff08;数据并行&#xff09; 每个G…...

vue3中使用拖拽组件vuedragable@next

vue3中使用拖拽组件vuedragablenext 官网传送门 下载 npm install vuedraggablenext基本使用 <script setup> import draggable from vuedraggable import { ref } from vue const list ref([{ id:1,name:第一个 },{ id:2,name:第二个 },{ id:3,name:第三个 }, ]) <…...

Oracle、MySQL、PostgreSQL三大数据库对比分析

Oracle、MySQL、PostgreSQL 三大数据库的对比分析&#xff0c;结合 Java SpringBoot 项目开发 的实际场景&#xff0c;重点说明分库分表、主从复制的实现难度及案例。 一、数据库核心对比 1. 核心区别与适用场景 维度OracleMySQLPostgreSQL定位企业级商业数据库轻量级开源数据…...

java八股之并发编程

1.java线程和操作系统线程之间的区别&#xff1f; 现在java线程本质上是操作系统线程&#xff0c;java中采用的是一对一的线程模型&#xff08;一个用户线程对应一个内核进程&#xff09; 2.什么是进程和线程&#xff1f; 1.进程是操作系统一次执行&#xff0c;资源分配和调度的…...

Qt 入门 5 之其他窗口部件

Qt 入门 5 之其他窗口部件 本文介绍的窗口部件直接或间接继承自 QWidget 类详细介绍其他部件的功能与使用方法 1. QFrame 类 QFrame类是带有边框的部件的基类。它的子类包括最常用的标签部件QLabel另外还有 QLCDNumber、QSplitter,QStackedWidget,QToolBox 和 QAbstractScrol…...

Linux系统之----冯诺依曼结构

1.简要描述 冯诺依曼体系结构是现代计算机的基本设计思想&#xff0c;其核心理念是将计算机的硬件和软件统一为一个整体&#xff0c;通过存储程序的方式实现计算。冯诺依曼体系结构的核心思想是通过存储程序实现自动计算&#xff0c;其五大部件协同工作&#xff0c;奠定了现代…...

C++11新特性

目录 引入 C11新特性 统一的初始化列表 一切皆可{}初始化 std::initializer_list 统一的声明 auto decltype nullptr 范围for STL新增容器 STL新增容器接口 左值引用和右值引用 左值和右值 左值引用和右值引用 右值引用的优势(移动语义) 右值引用的使用场景 …...

492Q 型气缸盖双端面铣削组合铣床总体设计

一、引言 492Q 型气缸盖是发动机的重要组成部分&#xff0c;其双端面的加工精度对发动机的性能和可靠性有着重要影响。设计一款适用于 492Q 型气缸盖双端面铣削的组合铣床&#xff0c;能够提高加工效率和质量&#xff0c;满足发动机生产的需求。 二、总体设计要求 加工精度&…...

《软件设计师》复习笔记(4.2)——关系代数、函数依赖、范式

目录 一、关系代数 基本运算 笛卡尔积&#xff08;&#xff09; 投影&#xff08;π&#xff09; 选择&#xff08;σ&#xff09; 自然连接&#xff08;⋈&#xff09; 真题示例&#xff1a; 二、函数依赖 基本概念 Armstrong公理系统 键与约束 三、范式&#xff…...

IO流(二)

一、字符流 使用字节流可以读取文件中的字节数据。但是如果文件中有中文使用字节流来读取&#xff0c;就有可能读到半个汉字的情况&#xff0c;这样会导致乱码。虽然使用读取全部字节的方法不会出现乱码&#xff0c;但是如果文件过大又不太合适。 所以Java专门为我们提供了另…...

#Linux动态大小裁剪以及包大小变大排查思路

1 动态库裁剪 库分为动态库和静态库&#xff0c;动态库是在程序运行时才加载&#xff0c;静态库是在编译时就加载到程序中。动态库的大小通常比静态库小&#xff0c;因为动态库只包含了程序需要的函数和数据&#xff0c;而静态库则包含了所有的函数和数据。静态库可以理解为引入…...

天梯赛数据结构合集

1.集合操作&#xff1a;PTA | 程序设计类实验辅助教学平台 主要是注意set的取交集操作&#xff0c;AC代码&#xff1a; #include<bits/stdc.h> using namespace std; int n,m,k; set<int> a[60]; int main(){cin>>n;for(int i1;i<n;i){cin>>m;for…...

pdfjs库使用记录1

import React, { useEffect, useState, useRef } from react; import * as pdfjsLib from pdfjs-dist; // 设置 worker 路径 pdfjsLib.GlobalWorkerOptions.workerSrc /pdf.worker.min.js; const PDFViewer ({ url }) > { const [pdf, setPdf] useState(null); const […...

LIMS引领综合质检中心数字化变革,赋能质量强国战略

在质量强国战略的深入推进下&#xff0c;我国综合质检机构迎来了前所未有的发展机遇&#xff0c;同时也面临着诸多严峻挑战。随着检测领域从传统的食品药品监督向环境监测、新材料检测等新兴领域不断拓展&#xff0c;跨领域协同管理的复杂度呈指数级增长。作为提升产品质量的关…...

MySQL+Redis实战教程:从Docker安装部署到自动化备份与数据恢复20250418

MySQLRedis实战教程&#xff1a;从Docker安装部署到自动化备份与数据恢复 一、前言 在企业应用中&#xff0c;对MySQL和Redis运维的要求越来越高&#xff1a; 不能仅是启动就算部署运行稳定、隔离、访问控制、备份恢复、安全可靠&#xff0c;才是 企业级的基本功能 本文将手…...

嵌入式音视频开发指南:从MPP框架到QT实战全解析

嵌入式音视频开发指南:从MPP框架到QT实战全解析 一、音视频技术全景概述 1.1 技术演进里程碑 2003-2010年:标清时代(H.264/AVC + RTMP)2011-2018年:高清时代(H.265/HEVC + WebRTC)2019-至今:智能时代(AV1 + AI编解码 + 低延迟传输)1.2 现代音视频技术栈 #mermaid-s…...

如何使用Python进行自动化的系统管理?

Python已经成为系统管理员最流行的编程语言之一&#xff0c;因为它简单、灵活&#xff0c;并且广泛支持各种系统管理任务。无论您是自动执行重复性任务&#xff0c;管理文件和目录&#xff0c;还是处理用户权限&#xff0c;Python都提供了一组强大的工具来简化您的工作流程。 …...

拆机装机,通电主板亮灯风扇不转无法开机解决办法

电源开机线 重启线 usb耳机模块 灯线 看来电源没问题 参考https://zhidao.baidu.com/question/83939532/answer/2321171868.html 买了个新主板过几天到看看会不会好...

IntelliSense 已完成初始化,但在尝试加载文档时出错

系列文章目录 文章目录 系列文章目录前言一、原因二、使用步骤 前言 IntelliSense 已完成初始化&#xff0c;但在尝试加载文档时出错 File path: E:\QtExercise\DigitalPlatform\DigitalPlatform\main\propertyWin.ui Frame GUID:96fe523d-6182-49f5-8992-3bea5f7e6ff6 Frame …...

SuperMap iClient3D for WebGL 如何加载WMTS服务

在 SuperMap iClient3D for WebGL 中加载WMTS服务时&#xff0c;参数配置很关键&#xff01;下面我们详细介绍如何正确填写参数&#xff0c;确保影像服务完美加载。 一、数据制作 对于上述视频中的地图制作&#xff0c;此处不做讲述&#xff0c;如有需要可访问&#xff1a;Onl…...

[密码学实战]基于Python的国密算法与通用密码学工具箱

引言 在当今数字化浪潮中&#xff0c;信息安全已成为个人隐私保护与商业机密守护的核心议题。作为一位在密码学领域深耕多年的技术实践者&#xff0c;我深谙密码学工具在构建数字安全防线中的关键作用。正是基于这份认知与责任&#xff0c;我倾力打造了一款全方位、高性能的密…...

[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案

[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案 引言 国密算法&#xff08;SM2/SM3/SM4&#xff09;在金融、政务等领域广泛应用&#xff0c;但开发者在集成gmssl库实现SM2签名时&#xff0c;常遇到与第三方工具&#xff08;如OpenSSL、国密网关&#xff09;验证不…...

LIB-ZC, 一个跨平台(Linux)平台通用C/C++扩展库, stream 流操作

LIB-ZC, 一个跨平台(Linux)平台通用C/C扩展库, stream 流操作 lib-zc 封装了流操作命名空间 zcc基础类 stream(基类), iostream(io流封装) class stream 介绍 连接相关 // 都是虚函数, 为 iostream 等做准备virtual inline bool connect(const char *destination) { return …...

从零开始解剖Spring Boot启动流程:一个Java小白的奇幻冒险之旅

大家好呀&#xff01;今天我们要一起探索一个神奇的话题——Spring Boot的启动流程。我知道很多小伙伴一听到"启动流程"四个字就开始头疼&#xff0c;别担心&#xff01;我会用最通俗易懂的方式&#xff0c;带你从main()方法开始&#xff0c;一步步揭开Spring Boot的…...

概率多假设跟踪(PMHT):多目标跟踪中的概率软关联与高效跟踪算法解析

一、PMHT 的起源与核心定位 &#xff08;一&#xff09;背景 在多目标跟踪中&#xff0c;传统算法面临以下瓶颈&#xff1a; JPDA&#xff1a;单帧局部最优关联&#xff0c;无法处理跨帧长时间断联&#xff0c;且假设目标数固定&#xff08;如雷达跟踪中预设目标数范围&…...

4.信号和槽|存在意义|信号和槽的连接方式|信号和槽断开|lambda表达式|信号和槽优缺点(C++)

信号和槽存在意义 所谓的信号槽&#xff0c;终究要解决的问题&#xff0c;就是响应用户的操作 信号槽&#xff0c;其实在GUI开发的各种框架中&#xff0c;是一个比较有特色的存在 其他的GUI开发框架&#xff0c;搞的方式都要更简洁一些&#xff5e;~ 网页开发 (js dom api) 网…...

电脑 BIOS 操作指南(Computer BIOS Operation Guide)

电脑 BIOS 操作指南 电脑的BIOS界面&#xff08;应为“BIOS”&#xff09;是一个固件界面&#xff0c;允许用户配置电脑的硬件设置。 进入BIOS后&#xff0c;你可以进行多种设置&#xff0c;具体包括&#xff1a; 1.启动配置 启动顺序&#xff1a;设置从哪个设备启动&#x…...

Scrapeless Scraping Browser: A high-concurrency automation solution for AI

介绍&#xff1a;升级无缝抓取浏览器的并发能力 作为 Scrapeless 的开发者和创始团队&#xff0c;我们对人工智能自动化的未来充满真诚的热情。我们的使命是创建一个真正为 AI 设计的自动化浏览器。在过去的几年中&#xff0c;从 Browserless.io 到众多云服务供应商推出的“浏…...

Java项目—— 拼图小游戏(进阶版)

项目需求 在拼图小游戏基础版的基础上&#xff0c;完成下列要求&#xff1a; 一、实现更换拼图图片功能 1&#xff0c;给美女&#xff0c;动物&#xff0c;运动菜单按钮添加单击事件&#xff08;动作监听&#xff09; 2&#xff0c;当我们点击了美女之后&#xff0c;就会从13…...

解析:深度优先搜索、广度优先搜索和回溯搜索

一、深度优先搜索&#xff08;DFS&#xff09; 1. 原理 思想&#xff1a;从起始节点出发&#xff0c;顺着一条路径不断深入&#xff0c;直到到达目标或无路可走&#xff0c;然后回溯到最近的分支点&#xff0c;继续探索其他分支。 应用场景&#xff1a;路径查找、连通性检测、…...

探索大语言模型(LLM):循环神经网络的深度解析与实战(RNN、LSTM 与 GRU)

一、循环神经网络&#xff08;RNN&#xff09; 1.1 基本原理 循环神经网络之所以得名&#xff0c;是因为它在处理序列数据时&#xff0c;隐藏层的节点之间存在循环连接。这意味着网络能够记住之前时间步的信息&#xff0c;并利用这些信息来处理当前的输入。 想象一下&#xf…...

从零开始开发 MCP Server

作者&#xff1a;张星宇 在大型语言模型&#xff08;LLM&#xff09;生态快速演进的今天&#xff0c;Model Context Protocol&#xff08;MCP&#xff09;作为连接 AI 能力与真实世界的标准化协议&#xff0c;正逐步成为智能体开发的事实标准。该协议通过定义 Resources&#…...

Oracle日志系统之重做日志和归档日志

Oracle日志系统之重做日志和归档日志 重做日志归档日志 本文讨论Oracle日志系统中对数据恢复非常重要的两个日志&#xff1a;重做日志和归档日志。 重做日志 重做日志&#xff0c;英文名Redo Log&#xff0c;顾名思义&#xff0c;是用来数据重做的&#xff0c;主要使用场景是事…...

嵌入式开发--STM32G4系列硬件CRC支持MODBUS和CRC32

需求 在项目中&#xff0c;需要用到MODBUS CRC16校验&#xff0c;也要用到CRC32的校验&#xff0c;出于效率的考虑&#xff0c;准备用硬件CRC。 CRC 16的参数模型有很多种&#xff0c;我这里用的是MODBUS&#xff0c;对于不同的参数模型&#xff0c;会有不同的参数设置和初值&a…...

基于尚硅谷FreeRTOS视频笔记——4—多任务处理

目录 多任务处理 任务调度 任务的调度策略 优先级不同 优先级相同 多任务处理 通俗来讲就是 能够在同一时间 同时 进行多个任务的处理&#xff0c;这就时多任务处理。 但是&#xff0c;单核处理器一次只能处理一个任务&#xff0c;就是说在while中&#xff0c;任务们只能…...

中小型及初创企业如何实现数字化转型?

在当今动态的商业环境中&#xff0c;财务团队开始肩负起推动企业数字化转型的重任&#xff0c;即从传统的财务规划系统稳步迈向基于商业智能平台和以创新技术为驱动的解决方案领域。这些举措有望提高运营和分析效率&#xff0c;同时依托数据驱动的决策机制&#xff0c;帮助企业…...

java输出、输入语句

先创建一个用于测试的java 编写程序 #java.util使java标准库的一个包&#xff0c;这里拉取Scanner类 import java.util.Scanner;public class VariableTest {public static void main(String[] args) {#创建一个 Scanner 对象Scanner scanner new Scanner(System.in);System.…...

Python基础知识语法归纳总结(数据类型-1)

Python基础知识&语法归纳总结&#xff08;数据类型&#xff09; 一、Python基本数据类型 尤其注意&#xff0c;Python中的变量不需要特定的去声明&#xff0c;每个变量在使用前都必须对其进行赋值&#xff0c;它没有类型&#xff0c;我们所说的“类型”是变量所指的内存中对…...

Spring数据访问全解析:ORM整合与JDBC高效实践

目录 一、Spring ORM集成深度剖析 &#x1f31f; ORM模块架构设计 核心集成特性&#xff1a; 整合MyBatis示例配置&#xff1a; 二、Spring JDBC高效实践指南 &#x1f31f; 传统JDBC vs Spring JDBC对比 &#x1f31f; JdbcTemplate核心操作示例 批量操作优化&#xf…...

哪种电脑更稳定?Mac?Windows?还是云电脑? 实测解密

随着科技的发展进步&#xff0c;电脑已成为当下各类群体的必备产品之一&#xff0c;它的妙用有很多&#xff0c;无论是学生党、打工人还是已经退休的人群或都离不开它的存在。然而&#xff0c;电脑虽好却也差异很大、不同品牌、不同系统、不同配置、不同价位的统统都会有区别。…...

【AI模型学习】关于写论文——论文的审美

文章目录 一、“补丁法”&#xff08;Patching&#xff09;1.1 介绍1.2 方法论1.3 实例 二、判断工作的价值2.1 介绍2.2 详细思路2.3 科研性vs工程性 三、novelty以及误区3.1 介绍3.2 举例 看了李沐老师的读论文系列后&#xff0c;总结三个老师提到的有关课题研究和论文写作的三…...

【面经】杭州产链数字科技一面

1.介绍一下自己 面试官您好&#xff01;我叫***&#xff0c;目前是就读于****计算机科学与技术专业的一名学生。我平时在学校也自学了编程相关的知识&#xff0c;比如Java基础、Springboot、SpringCloud&#xff0c;关系型数据库Mysql&#xff0c;非关系型数据库Redis&#xff…...