数据结构初阶:算法复杂度_复杂度的阶,1-3年的网络安全开发工程师看过来

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注网络安全)
img

正文

N

N

N 都是已知常数,则复杂度是

O

(

1

)

O(1)

O(1)。

一般通常用

N

N

N 表示未知数,但

M

M

M ,

K

K

K 等等也行。

Example 2
void Func2(int N) {
	int count = 0;
	for (int k = 0; k < 100; ++ k) {
		++count;
	}
	printf("%d\n", count);
}

本题的运行次数是常数次,不管该常数多大,时间复杂度都是

O

(

1

)

O(1)

O(1) 。

Example 3
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;
	}
}

有的算法会有最好情况,最坏情况。对于复杂度的计算我们通常采用最坏的情况作悲观预期。很少有算法会看平均情况。

冒泡排序就是其中之一,我们对其最差的情况分析。相邻两数相比,第一趟交换

N

1

N-1

N−1 次,第二趟交换

N

2

N-2

N−2 次,……,第

i

i

i 趟交换

N

i

N-i

N−i 次。故精确的算法次数应为

F

(

N

)

=

N

1

N

2

.

.

.

N

i

.

.

.

1

0

=

N

×

(

N

1

)

/

2

F(N)=N-1+N-2+…+N-i+…+1+0=N×(N-1)/2

F(N)=N−1+N−2+…+N−i+…+1+0=N×(N−1)/2 。故复杂度为

O

(

N

2

)

O(N^2)

O(N2) 。

在这里插入图片描述

也可以看比较的次数,由于每趟最后一次只比较不交换,所以每趟比较的次数都比交换的次数多一次。但是并不影响其的复杂度。

Example 4
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;
		else
			return mid;
	}
	return -1;
}

计算算法的复杂度不可仅看循环的层数,还要看算法的思想。 二分查找同样具有最好情况和最坏情况,仍然要对其最坏情况(找不到)进行分析。

对于这样的每次折半的情况,可以形象的用“折纸法”理解,一张纸对折一次去掉一半再对折再舍弃,假设一共折了

x

x

x 次,就找到了该数字。也就是

2

x

=

N

2^x=N

2x=N,所以次数

x

=

l

o

g

2

N

x=log_2N

x=log2​N 。

对数阶

O

(

l

o

g

2

N

)

O(log_2N)

O(log2​N),也可以省略底数写成

O

(

l

o

g

N

)

O(logN)

O(logN)。二分查找这个对数阶是非常优秀的算法,

20

=

l

o

g

2

(

1000000

)

20=log_2(1000000)

20=log2​(1000000),一百万个数仅需查找20次。

Example 5
long Factorial(size\_t N)
{
	if (0 == N)
		return 1;
	return Fac(N - 1) \* N;
}

递归算法的复杂度取决于两个因素:递归深度和每次递归调用次数。

递归深度即是一共递归的层数,也就是创建栈帧的次数。每次递归调用次数是递归函数内调用自身的次数。

显然本题的深度是

O

(

N

)

O(N)

O(N),调用次数是

1

1

1,故复杂度是

O

(

N

)

O(N)

O(N) 。

Example 6
long Fibonacci(size\_t N)
{
    if(N < 3)
        return 1;
    return Fib(N-1) + Fib(N-2);
}

斐波那契递归的思想是类似于二叉树的,但是后面缺少了一部分,如图所示:

如果没有缺失的话就是完整二叉树,将缺少的部分设为

X

X

X,精确次数就是

F

(

N

)

=

2

0

2

1

2

2

.

.

.

2

N

1

X

=

2

N

1

X

F(N)=20+21+22+…+2{N-1}-X=2^N-1-X

F(N)=20+21+22+…+2N−1−X=2N−1−X,由于

X

X

X远小于

2

N

1

2^N-1

2N−1,故算法复杂度为

O

(

N

)

=

2

N

O(N)=2^N

O(N)=2N。

空间复杂度
空间复杂度定义

空间复杂度也是数学表达式,度量算法运行时临时额外占存空间的大小。同样空间复杂度不是无意义的实际占用的字节数,空间复杂度计算临时开辟变量的个数。基本规则规则和时间复杂度类似,也采用大O渐进表示法。

Example 1
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)。

虽然变量end,i每次循环都创建一次,但其实从内存角度看,每次所占空间并不会发生变化,一般都开辟在同一块空间。

Example 2
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;
}

包括循环变量和该斐波那契数组,开辟量级为

N

N

N个的变量。故空间复杂度为

O

(

N

)

O(N)

O(N) 。

Example 3
long long Factorial(size\_t N)
{
    if(N == 0)
        return 1;
    return Fac(N - 1) \* N;
}

每次递归创建一个栈帧,每个栈帧中都是常数个变量,

N

N

N次递归的空间复杂度为

O

(

N

)

O(N)

O(N) 。

递归的空间复杂度与递归深度有关。

Example 4
long Fibonacci(size\_t N)
{
    if(N < 3)
        return 1;
    return Fib(N-1) + Fib(N-2);
}

斐波那契每次递归同样创建常数个变量,从斐波那契栈帧创建图中可以看出,递归中会有重复的项,这些重复的栈帧创建又销毁。空间不同于时间是可以重复利用的,所以这些重复的栈帧仅占用一次的空间。所以

F

i

b

(

N

)

Fib(N)

Fib(N),

F

i

b

(

N

1

)

Fib(N-1)

Fib(N−1),…,

F

i

b

(

1

)

Fib(1)

Fib(1)这些栈帧都分配一次的空间足矣。故时间复杂度为

O

(

N

)

O(N)

O(N) 。

常见复杂度

常见的算法复杂度如下表,复杂度由上到下依次递增:

简称大O表示示例
常数阶

O

(

1

)

O(1)

O(1) |

k

k

k |
| 对数阶 |

O

(

l

o

g

n

)

O(logn)

O(logn) |

k

l

o

g

2

n

klog_2n

klog2​n |
| 线性阶 |

O

(

n

)

O(n)

O(n) |

k

n

kn

kn |
| 对数阶 |

O

(

n

l

o

g

n

)

O(nlogn)

O(nlogn) |

k

l

o

g

2

n

klog_2n

klog2​n |
| 平方阶 |

O

(

n

2

)

O(n^2)

O(n2) |

k

n

2

kn^2

kn2 |
| 立方阶 |

O

(

n

3

)

O(n^3)

O(n3) |

k

n

3

kn^3

kn3 |
| 指数阶 |

O

(

2

n

)

O(2^n)

O(2n) |

k

2

n

k2^n

k2n |
| 阶乘阶 |

O

(

n

!

)

O(n!)

O(n!) |

k

n

!

kn!

kn! |

最低的是常数次

O

(

1

)

O(1)

O(1),其次是对数阶

O

(

l

o

g

n

)

O(logn)

O(logn),然后是线性阶

O

(

n

)

O(n)

O(n),再高就是平方阶

O

(

n

2

写在最后

在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。

需要完整版PDF学习资源私我

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

kn^3

kn3 |
| 指数阶 |

O

(

2

n

)

O(2^n)

O(2n) |

k

2

n

k2^n

k2n |
| 阶乘阶 |

O

(

n

!

)

O(n!)

O(n!) |

k

n

!

kn!

kn! |

最低的是常数次

O

(

1

)

O(1)

O(1),其次是对数阶

O

(

l

o

g

n

)

O(logn)

O(logn),然后是线性阶

O

(

n

)

O(n)

O(n),再高就是平方阶

O

(

n

2

写在最后

在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。

需要完整版PDF学习资源私我

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
[外链图片转存中…(img-CRcFjvPq-1713610525225)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值