DS:时间复杂度和空间复杂度

欢迎各位来到 Harper.Lee 的学习世界!

博主主页传送门:Harper.Lee的博客主页

想要一起进步的uu欢迎来后台找我哦!


        本片博客主要介绍的是数据结构中关于算法的时间复杂度和空间复杂度的概念。

一、算法

1.1 什么是算法?

         算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。

1.2 算法的复杂度

        算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。
        时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度,计算机的配置变得越来越高,对内存(空间复杂度)的关注也就没那么高了。所以我们如今已经不需要再特别关注一个算法的空间复杂度。目前计算机行业的硬件方面已经遇到瓶颈期了。

摩尔定律:其核心内容是当价格不变时,集成电路上可容纳的晶体管数目约每隔18个月至24个月便会增加一倍,同时性能也将提升一倍。换言之,每一美元所能买到的电脑性能,将每隔18个月翻两倍以上。这一定律揭示了信息技术进步的速度,为半导体行业的发展提供了长期的发展目标和预测。

二、时间复杂度

2.1 时间复杂度的概念

        在计算机科学中,算法的时间复杂度是一个函数(这里的函数不是之前写的函数调用的那个函数,而是数学中的函数式),它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。即:找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。(时间复杂度越大,运行水时间越长)。

        但是我们为什么不直接讨论快速排序执行多少时间、冒泡排序执行多少时间呢?原因在于具体怎么执行与自己的机器(硬件)有关,硬件配置不一样,就不能比较具体执行的时间。因此,我么需要一套与环境因素(如硬件因素)无关的理论,也就是这里的时间复杂度。

请观察下面的代码,然后进行分析:

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

Func1 执行的基本操作次数 :F(N)=N^2+2*N+10
N = 10              F(N) = 130,            N^2 = 100
N = 100            F(N) = 10210,           N^2 = 10000
N = 1000          F(N) = 1002010,       N^2 = 1000000

        从这个例子我们发现,当N越大(当N趋于无穷大时),N^2对时间复杂度的结果影响最大。因此,我们选择大概估算(大O的渐进表示法)的方法,忽略掉2*N+10这一项,时间复杂度就可以表示为:F(N)=O(N^2)。当N很小的时候,认为时间复杂度一样,没有比较的意义,CPU主频很大。(CPU主频在 2.3 有详细介绍)

2.2 大O的渐进表示法

        大概估算是计算算法属于哪个量级(level)。

        大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,Func1的时间复杂度为:F(N)=O(N^2)
        N = 10 F(N) = 100
        N = 100 F(N) = 10000
        N = 1000 F(N) = 1000000

        通过上面的分析,我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
        另外有些算法的时间复杂度存在最好、平均和最坏情况:
 最坏情况:任意输入规模的最大运行次数(上界)
 平均情况:任意输入规模的期望运行次数
 最好情况:任意输入规模的最小运行次数(下界)
例如:在一个长度为N数组中搜索一个数据x
 最好情况:1次找到
 最坏情况:N次找到
 平均情况:N/2次找到
        在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)。

2.3 为什么O(n)使用最坏情况下的估算结果呢?

         在这种情况下,实际的结果要么就是估算的结果的惊喜,要么就刚好是最低预期结果,这是一种以防万一的心态,在预估了所有坏的可能后得到的方案。

2.4 CPU主频(拓展)

CPU主频,也称为时钟频率或时钟速度,是指中央处理单元(CPU)内部时钟的频率或速度。

        它表示了处理器每秒钟执行指令的次数,通常以赫兹(Hz)为单位表示,例如兆赫兹(MHz)或千兆赫兹(GHz)。主频是评估其性能和速度的一个重要指标之一。一般来说,较高的主频意味着处理器能够更快地执行指令,因此在一定程度上具有更高的性能。然而,主频并不是评估处理器性能的唯一因素,其他因素如微架构、核心数量、缓存大小、指令集等也会影响性能。需要注意的是,主频并不是唯一影响处理器性能的因素。不同型号的处理器可能在相同主频下表现出不同的性能,因为它们的架构和其他规格可能不同。因此,在选择计算机或处理器时,不仅要考虑主频,还要综合考虑其他因素,以确保满足你的性能需求。

(资料来自百度)

CPU主频也叫时钟频率,单位是MHz,用来表示CPU的运算速度。

        CPU的工作频率(主频)包括两部分:外频与倍频,两者的乘积就是主频。

        倍频的全称为倍频系数。CPU的主频与外频之间存在着一个比值关系,这个比值就是倍频系数,简称倍频。倍频可以从1.5一直到23以至更高,以0.5为一个间隔单位。外频与倍频相乘就是主频,所以其中任何一项提高都可以使CPU的主频上升。由于主频并不直接代表运算速度,所以在一定情况下,很可能会出现主频较高的CPU实际运算速度较低的现象。因此主频仅仅是CPU性能表现的一个方面,而不代表CPU的整体性能 。

        处理器主频以每秒处理器周期可运行的百万次计算。通常,具有较高MHz或GHz的处理器能够提高电脑运行创新、娱乐、通信和生产力应用的性能。但主频只是影响系统整体性能的一个方面,主频高的机器整体性能并非就一定高。
                        
(声明:此段文本复制自博客:http://t.csdnimg.cn/FGGi7)

        简而言之,CPU主频反映了在一个周期内大概能执行多少指令主频越高,CPU的处理速度越快。CPU性能再怎么差,它每秒的运算速度也能运行上亿次。可以利用clock函数验证:

#include <time.h>int main()
{int begin1 = clock();int n = 100000000;int x = 10;for (int i = 0; i < n; i++){++x;}int end1 = clock();printf("%d\n", x); printf("程序运行时间%d ms\n", end1 - begin1);return 0;
}

如果结果为0ms说明中间的时间消耗小于1ms,而不是没有时间消耗。

        C语言中的函数clock(),它可以捕捉从程序开始运行到clock()被调用时所耗费的时间。两个clock()函数的返回值相减,就可以计算两个函数之间的程序运行所消耗的大概时间(ms)了。我么可以利用它来大致测试一下电脑的性能。而且,release版本做了优化,因此时间比Debug版本稍短。

2.5 常见的时间复杂度量级

2.6 重要时间复杂度计算

2.6.1 冒泡排序的时间复杂度 O(n^2)

        F(n)=(n-1)+ (n-2) + (n-3)+……+3+2+1=n*(n-1)/2 (可以根据两个数比较的次数来写), 时间复杂度为:O(n^2)。注意不能直接数循环的个数。

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

2.6.2 qsort函数的时间复杂度O(n*logn)

qsort函数的时间复杂度为: O(n*logn)

2.6.3 二分查找的时间复杂度

        折半查找:n,n/2,n/2/2,……,n/2/2/……/2(查找了x次就除以x个2),2^x=N,所以x=logN(省略底数2)。最坏情况:查找区间只剩一个数或者找不到。O(logN)

// 计算BinarySearch的时间复杂度
int BinarySearch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n - 1;// [begin, end]:begin和end是左闭右闭区间,因此有=号 //保持左闭右闭区间(保持不变)while (begin <= end)//begin=end,还有一个数{int mid = begin + ((end - begin) >> 1);//此写法可以防止溢出if (a[mid] < x)begin = mid + 1;//因为签】前一次比较中,mid已经比较过了else if (a[mid] > x)end = mid - 1;//end是mid-1elsereturn mid;}return -1;
}//写法二:
int BinarySearch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n - 1;// [begin, end)  ->保持左闭右开区间while(begin<end){//int mid = begin + ((end - begin) >> 1);//防止溢出(begin+end值可能很大)//也可以写成int mid = (begin + end)/2;(不能防止溢出)if (a[mid] < x)begin = mid + 1;else if (a[mid] > x)end = mid;//这里变成end=mid,而不是 mid-1elsereturn mid;}return -1;
}

        二分查找:O(logN),随着N的增长,O(logN)变化不大;暴力查找:O(N),随着N的增长,O(N)变化很大。

        缺点:二分查找外强中干,在实际中不太实用,需要排序、而且数组结构不方便插入删除数据(会造成数据整体的挪动)。

2.6.4  strchr函数的时间复杂度

// 计算strchr的时间复杂度?
const char * strchr ( const char * str, int character );

        在一个字符串中查找一个字符,它的实现过程就相当于如下的代码:

while (*str)
{if (*str == character)return str;else++str;
}

        最好情况:O(1),最坏情况:O(n),平均情况:O((1+2+3+……+n)/n))。所以时间复杂度为O(n)。

        时间复杂度的意义:帮助我们对比几种解决方法孰优孰劣。 

三、 常见时间复杂度的举例

1、O(n)只看循环次数,且系数对结果影响不大

        F(n)=2*n+10 , O(n)而不是O(2*n)。F(n)相当于只看循环次数,要去掉系数2(即使这个系数是200也要去掉),系数对结果影响不大,n无穷大时,n和2*n没有区别。

// 计算Func2的时间复杂度?
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);
}

2、O(n)可以用多个未知数表示

        F(n)=M+N,  O(M+N)或O(max(M,N)。在时间复杂度,经常使用N作为未知数,也可以使用其它符号来表示未知数。如果M远大于N,O(M);如果如果N远大于M,O(N)。不一定只有一个未知数。

// 计算Func3的时间复杂度?
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);
}

3、F(n)= 常数,  O(1)

        时间复杂度是O(1),而不是O(100)。没有未知数而只有常数次,则时间复杂度为  O(1)。

// 计算Func4的时间复杂度?
void Func4(int N)
{int count = 0;for (int k = 0; k < 100; ++ k){++count;}printf("%d\n", count);
}

4、单身狗题目回顾(为下一道题做铺垫)

5、力扣--17.04. 消失的数字

        题目描述:数组nums包含从0n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

思路1:先排序(冒泡排序、qsort快速排序)再查找,如果前一个值(b)不等于后一个值(a) +1,那么前一个值(b)就是消失的数字。(由于时间复杂度,现可以直接抛弃该思路)(排序:a,b; a+1==b),但时间复杂度不符合要求。

思路2:先将0~N进行求和,然后再依次减去数组中值,剩下的值就是消失的数字。时间复杂度为O(N)。(缺陷:N太大,存在溢出风险)

int missingNumber(int* nums, int numsSize){int N = numsSize;//0~n一共n+1个数,但缺了1个数,一共n个数int ret = (0 + N) * (N + 1) / 2;//计算出0~n的总和for(int i = 0; i < numsSize; ++i)//{ret -= nums[i];//总和减去数组中值}return ret;
}

思路3:按位异或(相同为0,相异为1)(有点类似于单身狗的那道题)。O(n)

int missingNumber(int* nums, int numsSize){int N = numsSize;int x = 0;for(int i = 0; i < numsSize; ++i)//numsSize是少了1的,9个数{x ^= nums[i];//0和任何数异或均是任何数}  for(int j = 0; j <= N; ++j)//这里有n个数,10个数{x ^= j;}return x;
}

6、力扣--189. 轮转数组

        题目描述:给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 

分析:需要一个循环两个嵌套,时间复杂度应该是:O(k*N)。

思路1:暴力求解(用只管的方式直接解 决问题,不用太多技巧)

        表达式为:F(N)= (N-1)*(N-1);O(k * N)

        如果k为7或者7的倍数次,旋转7次或者7的倍数次,其实就是旋转到原来的样子(相当于不旋转);如果旋转10次,就相当于旋转了3次。所以真实的旋转次数为 k % = N ;在最好情况下,即没有旋转,k % N = 0 , O(1);在最坏情况下K(N)=N*(N-1), k % N = N-1,O(N^2),旋转N-1次,。

        值得注意的是:时间复杂度必须要计算调用的其它方法所花的时间消耗。

void rotate(int* nums, int numsSize, int k) 
{k%=numsSize;while(k--)//k最大为n-1,k--走了k次,所以这里走了n-1次{//旋转一次      画图是最好的分析方法int tmp = nums[numsSize-1];//最后一个数保存起来for(int i =numsSize-2;i >= 0;i--)//起始位置在n-2(numsSize-2),结束情况:i >= 0{nums[i+1] = nums[i];//中间过程}nums[0] = tmp;}//但是用这种方法不能通过,超出时间限制(不能O(N^2))
}//前n-1个数往后挪
//循环分析:循环就三个过程,起始情况、中间过程、结束情况

        思路2:三段逆置  O(N)

代码如下: 

void reverse(int*  a,int left,int right)
{//三段逆置一定要画图,下标标明while(left<right)//一段区间,左右往中间走,未相遇,交换值{int tmp =a[left];a[left] = a[right];a[right] = tmp;++left;--right;}
}void rotate(int* nums, int numsSize, int k) {k%= numsSize;reverse(nums,0,numsSize-k-1);//前n-k个数,最后一个下标n-k-reverse(nums,numsSize-k,numsSize-1);reverse(nums,0,numsSize-1);
}

strncpy是针对字符串的,在这里不合适。
 

7、对数时间复杂度常见出现形式

        时间复杂度O(logN)

void func(int n)
{int x = 0;for (int i = 1; i < n; i *= 2){++x;}printf("%d\n", x);
}
int main()
{func(8);func(1024);func(1024*1024);return 0;
}

        分析:1*2*2*……*2 = N;假设循环走x次,就是x个2相乘,2^x=N,两边同时取对数,得到\log _2{N} 。时间复杂度就是O(\log N)。因为写的时候需要支持专业公式,否则不好写底数。为了方便 \log _2{N}省略了底数2,直接写成了\log N,但是其他的就不能省略且其他底数的很少出现。

8、阶乘递归的时间复杂度

// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{if(0 == N)return 1;return Fac(N-1)*N;
}

        每次调用函数都是O(1)的复杂度,调用N次就是O(N)的复杂度,而不是O(N!)。如果变式:时间复杂度为O(N^2)。 


//变式:
// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{if(0 == N)return 1;for(int i = 0; i <N;++i){//……}return Fac(N-1)*N;
}

        总结:递归时间复杂度为所有递归调用消耗次数(相当于运算次数)的累加。

9、斐波那契递归和非递归的时间复杂度

        斐波那契递归非递归的时间复杂度O(N^2)

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

        最左侧会逐步减少到Fib(1),有N层,但是右侧未必能走到N层,所以呈现的三角形并不是等腰三角形,但是不影响最终的量级,大O阶表示时间复杂度O(N^2) 。分析过程如下图:

         斐波那契非递归(斐波那契数列的优化)的时间复杂度 :

// 1  1  2  3  5  8....
// 时间复杂度:O(N)(很大的优化)
long long Fib(size_t N)
{long long f1 = 1;long long f2 = 1;long long f3 = 0;for (size_t i = 3; i <= N; i++){f3 = f1 + f2;f1 = f2;f2 = f3;}return f3;
}

        其实斐波那契数列没什么特别的实用意义,因为数据稍稍大点就计算不出结果了。(50都不得行了)。此外,还可以使用字符串进行存储(大树运算)。

四、空间复杂度

4.1 空间复杂度定义 

        空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 
        空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法
        注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

4.2 空间复杂度例题

        1、冒泡排序的空间复杂度

        变量个数:3(常数个),所以空间复杂度为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;}
}

         2、  轮转数组另一个解法(空间复杂度)

        不用三段逆置的方法,重新创建一个数组,后k个旋转在前面,再把前n-k个拷贝到后面去 ,最后再将最终结果拷贝到原来的位置。此时,新创建的N个数组就是为了解决此问题而创建的,它就需要计算空间,空间复杂度就是O(N)。

最后的代码如下,代码中使用了变长数组:

void _rotate(int* nums, int numsSize, int k, int* tmp)
{k %= numsSize;int n = numsSize;memcpy(tmp, nums + n - k, sizeof(int) * k);memcpy(tmp+k, nums, sizeof(int) * (n-k));memcpy(nums,tmp, sizeof(int) * (n));
}void rotate(int* nums, int numsSize, int k)
{int tmp[numsSize];_rotate(nums, numsSize, k, tmp);
}

        3、阶乘递归的空间复杂度

// 计算阶乘递归Fac的空间复杂度?
long long Fac(size_t N)
{if (N == 0)return 1;return Fac(N - 1) * N;
}

4、斐波那契数列的空间复杂度为:

         常见的空间复杂度中只有三种:O(1)、O(N)、O(N^2)(比如二维数组)。


        创作不易,喜欢的uu三连支持一下叭! 

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

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

相关文章

QT--2

Qt界面设计 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//窗口相关设置this->resize(680,520);this->setFixedSize(680,520);this->setWindowTitle("Tim");this->setWindowFla…

Linux进程控制——Linux进程终止

前言&#xff1a;前面了解完前面的Linux进程基础概念后&#xff0c;我们算是解决了Linux进程中的一大麻烦&#xff0c;现在我们准备更深入的了解Linux进程——Linux进程控制&#xff01; 我们主要介绍的Linux进程控制内容包括&#xff1a;进程终止&#xff0c;进程等待与替换&a…

【机器学习数据可视化-04】Pyecharts数据可视化宝典

一、引言 在大数据和信息爆炸的时代&#xff0c;数据可视化成为了信息传递和展示的关键手段。通过直观的图表和图形&#xff0c;我们能够更好地理解数据&#xff0c;挖掘其背后的信息。Pyecharts&#xff0c;作为一款基于Python的数据可视化库&#xff0c;凭借其丰富的图表类型…

数据结构-二叉树-红黑树

一、红黑树的概念 红黑树是一种二叉搜索树&#xff0c;但在每个节点上增加一个存储位表示节点的颜色&#xff0c;可以是Red或者BLACK&#xff0c;通过对任何一条从根到叶子的路径上各个节点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出两倍&#xff0c;…

Crossplane 实战:构建统一的云原生控制平面

1 什么是 Crossplane Crossplane 是一个开源的 Kubernetes 扩展&#xff0c;其核心目标是将 Kubernetes 转化为一个通用的控制平面&#xff0c;使其能够管理和编排分布于 Kubernetes 集群内外的各种资源。通过扩展 Kubernetes 的功能&#xff0c;Crossplane 对 Kubernetes 集群…

Go实现树莓派读取at24c02 eeprom读写数据

步骤 启用i2c 参考 Go实现树莓派读取bh1750光照强度 代码 package mainimport ("fmt""periph.io/x/conn/v3/i2c" )type AT24C02Device struct {dev *i2c.Dev }func NewAT24C02Device(addr uint16, bus i2c.BusCloser) (*AT24C02Device, error) {var (d…

利用github pages建立Serverless个人博客

利用github pages建立Serverless个人博客 概述 使用github pages&#xff0c;可以在github上部署静态网站。利用这个功能&#xff0c;可以很方便地实现个人博客的发布托管。 比如我的个人博客&#xff1a;Buttering’s Blog 对应代码仓库&#xff1a;buttering/EasyBlog: 自…

Ubuntu20.4部署Cuda12.4

准备Ubuntu20.4 VM 安装Cuda12.4 1.进入如下界面安装安装Cuda12.4版本&#xff1a; CUDA Toolkit 12.4 Update 1 Downloads | NVIDIA Developerhttps://developer.nvidia.com/cuda-downloads?target_osLinux&target_archx86_64&DistributionUbuntu&target_vers…

图像分割各种算子算法-可直接使用(Canny、Roberts、Sobel)

Canny算子&#xff1a; import numpy as np import cv2 as cv from matplotlib import pyplot as pltimg cv.imread("../test_1_1.png") edges cv.Canny(img, 100, 200)plt.subplot(121),plt.imshow(img,cmap gray) plt.title(Original Image), plt.xticks([]), …

TC3xx MTU概述(1)

目录 1.MTU基本功能 2.MBIST 3.小结 1.MTU基本功能 在TC3xx中&#xff0c;MTU(Memory Unit Test)被用来管理控制芯片内部各种RAM的测试、初始化和数据完整性检查。 既然MTU主要是管理和控制&#xff0c;那干活的想必另有他人。所以在该平台中&#xff0c;我们可以看到SRAM…

(Java)心得:LeetCode——19.删除链表的倒数第 N 个节点

一、原题 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&…

C++ 指针 参数 静态 常 友元与组合概念

一 类类型作为函数参数 1 类类型作参数类型的三种方式 1&#xff09; 对象本身作为参数 由于C采用传值的方式传递参数&#xff0c;因此使用对象本身参数时&#xff0c;形参是实参的一个拷贝。在这种情况下&#xff0c;最好显式地为类定义一个拷贝构造函数&#xff0c;以免出…

图论专题训练

leecode 547 并查集 class Solution { public:int findCircleNum(vector<vector<int>>& isConnected) {ini();int len isConnected.size();for(int i0;i<len;i){for(int j0;j<len;j)if(isConnected[i][j]){unio(i,j);}}int ans 0;for(int i0;i<len;…

面试集中营—Redis面试题

一、Redis的线程模型 Redis是基于非阻塞的IO复用模型&#xff0c;内部使用文件事件处理器&#xff08;file event handler&#xff09;&#xff0c;这个文件事件处理器是单线程的&#xff0c;所以Redis才叫做单线程的模型&#xff0c;它采用IO多路复用机制同时监听多个socket&a…

Obsidian/Typora设置图床

在obsidian中默认图片是保存在本地的&#xff0c;但是在要导出文档上传到网上时&#xff0c;由于图片保存在本地&#xff0c;会出现无法加载图片的问题。 这里引用的一段话&#xff1a; 这里使用picgo-core和gitee实现图床功能&#xff0c; 参考1&#xff1a; Ubuntu下PicGO配…

【半个月我拿下了软考证】软件设计师高频考点--系统化教学-关系模式

&#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件设计师考点暴击 ⭐&#x1f170;️进入狂砍分⭐ ⭐软件设计师高频考点文档&#xff0c; ⭐软件设计师高频考点专栏 ⭐软件设计师高频考点⭐ &#x1f3b6;&#xff08;A) 考点1,关系模式 考点&#xff1a; 三个模式相…

AI算法-高数5-线性代数1-基本概念、向量

线性代数&#xff1a;主要研究1、张量>CV计算机视觉 2、研究张量的线性关系。 深度学习的表现之所以能够超过传统的机器学习算法离不开神经网络&#xff0c;然而神经网络最基本的数据结构就是向量和矩阵&#xff0c;神经网络的输入是向量&#xff0c;然后通过每个矩阵对向量…

Calendar 366 II for Mac v2.15.5激活版:智能日历管理软件

在繁忙的工作和生活中&#xff0c;如何高效管理日程成为了许多人的难题。Calendar 366 II for Mac&#xff0c;作为一款全方位的日历管理软件&#xff0c;以其独特的功能和优秀的用户体验&#xff0c;成为您的日程好帮手。 Calendar 366 II for Mac支持多种视图模式&#xff0c…

【Android学习】简单的登录页面和业务逻辑实现

实现功能 1 登录页&#xff1a;密码登录和验证码登录 2 忘记密码页&#xff1a;修改密码 3 页面基础逻辑 java代码 基础页面 XML login_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.and…

2-6 任务 猜数小游戏(单次版)

本任务要求编写一个猜数小游戏&#xff08;单次版&#xff09;&#xff0c;游戏规则是计算机产生一个0到100之间的随机整数&#xff0c;用户通过输入猜测的数字进行猜测&#xff0c;根据猜测情况给出提示&#xff0c;直到猜对为止。编程思路是利用while循环和多分支结构实现永真…