#itup01引子
这个专栏我齐是参考竹素《算法竞赛初学到进阶》,罗勇军、郭卫斌至意著进行编写的。
通过竹素上的材料以及我方的暴露来撰写博客。
有不适合的场地,接待诸君一又友指正!
也非常接待诸君hxd沿途学习探讨。
一、缠绵资源
秩序运转时需要两种资源,即缠绵工夫和存储空间。资源是有限的,一个算法对这两个资源的使用进程不错用来辩论该算法的优劣。
工夫复杂度:秩序运转需要的工夫
空间复杂度:秩序运转需要的存储空间
往往用O来示意复杂度
通过底下这个例子来推崇复杂度的主意和影响
源码:
#include<iostream>
using namespace std;
int main() {
int i, k=0, n = 1e8;
clock_t start, end;
start = clock();
for (int i = 0; i < n; i++) {
k++;
}
end = clock();
cout << (double)(end - start) / CLOCKS_PER_SEC << endl;
}
1
2
3
4
5
6
7
8
9
10
11
12
分析:
运转效果:
是以不错看出,在n=1e8的时候,输出工夫为0.135.
当n=1e9的时候
输出工夫为:1.313
那么咱们怎么来评定他的工夫复杂度呢?
由于不同的缠绵机性能不同,是以不行平直把上头的工夫手脚工夫复杂度。应该把柄秩序扩充的次数来辩论才合理。
是以上头的秩序扩充了n次,那么工夫复杂度即是O(n)。
例题分析
给出n个整数,按照从大到小的规章输出其中前m大的数
输入样例:
5 3
3 -35 92 213 -644
输出样例:
213 92 3
1
2
3
4
5
6
7
底下用冒泡排序,快速排序,哈希3种算法进行编程
冒泡排序
#include<iostream>
using namespace std;
int a[10000001];//记载数字
int m, n;
void bubble_sort() {//冒泡排序,效果仍然放到数组a中
int temp;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i ; j++) {
if (a[j] < a[j+1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
int main() {
while (scanf_s("%d %d", &n, &m)!=EOF) {
for (int i = 0; i <= n-2; i++) {
scanf_s("%d ", &a[i]);
}
printf_s("OK\n");
bubble_sort();
for (int i = 0; i < m; i++) {
printf_s("%d ", a[i]);
}
printf("\n");
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
运转效果
工夫复杂度为O(n^2)
快速排序
快速排序是基于分治法的优秀排序算法。这里不错先平直用STL的sort()函数。它是矫正的快速排序,称为“自省式排序”将上头的冒泡算法改为
sort(a,a+n);即可
哈希算法
哈希算法是一种以空间换工夫的算法。本题的哈希念念路是:在输入数字t的时候,在a[5000000+t]这个位置记载a[50000000+t]=1,在输出的时候一一查验a[i],要是a[i]等于1,就示意这个数存在,打印前m个数
#include<iostream>
using namespace std;
const int MAX = 1000001;
int a[MAX];
int main() {
int n, m;
while (scanf_s("%d %d", &n, &m) != EOF) {
memset(a, 0, sizeof(a));//将数组a清0
for (int i = 0; i < n; i++) {
int t; \
scanf_s("%d", &t);
a[500000 + t] = 1;//数字t,登记在500000+t这个位置
}
for (int i = MAX-1; m > 0; i--) {
if (a[i]) {
printf_s("%d ", i-500000);
m--;
}
}
printf_s("\n");
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
运转效果:
工夫复杂度为O(n)
算法的选拔
关于吞并个问题老是有不同的科罚方针,是以咱们在本色缔造中对算法的选拔要从本色情况和空间,工夫复杂度来探究。
二、算法的界说
服气全球齐知谈**“秩序=算法+数据结构”**,算法是科罚问题的逻辑、阵势、经由,数据结构是数据在缠绵机中的存储和拜谒神气,二者细密鸠合。
算法是对特定问题求解步地的一种描写,是教导的有限序列。它有底下5个特征
输入:一个算法有0个或多个输入。秩序不错莫得输入,举例一个定时闹钟秩序,他不需要输入,然而大约每隔一段工夫就输出一个警报。
输出:一个算法有一个或多个输出。秩序不错莫得输入然而一定要有输出。
有穷性:一个算法必须在扩充有穷步之后罢休,且每一步齐在有穷工夫内完成。
笃定性:算法中的每一条教导必须有实在的含义,关于相易的输入只可获取相易的输出。
可行性:算法描写的操作不错通过如故达成的基本操作扩充有限次来达成。
算法的评估
辩论算法性能的主要秩序是工夫复杂度。
为什么不参谋空间复杂度呢?
在一般情况下,一个秩序的空间复杂度是容易分析的,亚博ag百家乐而工夫复杂度往往联系到算法的根柢逻辑,更能评释一个秩序的优劣。
一个秩序或算法的工夫复杂度有以下几种可能
O(1)
缠绵工夫是一个常数,和问题的畛域n无关。举例用公式缠绵时,一次缠绵的复杂度即是O(1);哈希算法,用hash函数在常数工夫内缠绵出存储位置;在矩阵A[M] [N]中查找第i行第j列的元素只需要拜谒A[i][j]就够了。
O(log2n)
缠绵工夫是对数,往往是以2为底的对数,每一步缠绵后,问题的畛域减小一倍。举例在一个长度为n的有序数列中查找某个数,用折半查找的阵势只需要log2n次就能找到。再如分治法,一般情况下,在每一个步地把畛域减小一倍,是以一共有O(log2n)个步地。
O(n)
缠绵工夫随畛域n线性增长。在很厚情况下,这是算法可能达到的最优复杂度,因为对输入n个数,秩序一般需要处理通盘的数,即缠绵n次。举例查找一个无序数列中的某个数,可能需要查验通盘的数。再如图问题,有V个点和E个边,大大宗图的问题齐需要搜索到通盘的点和边,复杂度的上限即是O(V+E)
O(nlog2n)
这时常是算法等达到的最优复杂度。举例分治法,一共O(log2n)个步地,每一个步地对每个数操作一次,是以复杂度是O(nlog2n)。用分治法念念想达成的快速排序和归并列序算法复杂度即是O(nlog2n)
O(n^2)
一个两重轮回的算法,复杂度即是O(n^2)。举例冒泡排序即是典型的两重轮回。通常的复杂度还有O(n ^3),O(n ^4)等
O(2^n)
一般对应集结问题,举例一个集结中有n个数,条件输出它的通盘子集,子集有2 ^n个
O(n!)
在罗列问题中,要是条件输出通盘的全罗列,那么复杂度即是O(n!)。
上头的算法分为两类:
多项式复杂度:前5种
指数复杂度:背面2种
要是一个算法是多项式算法,就称它为“高效算法”;要是一个算法是指数复杂度,则称它为"初级算法"。多项式复杂度的算法跟着畛域的加多不错通过堆叠硬件来达成。然而指数型的莫得方针。
问题畛域和可用算法表(紧记)
❤(itup01)ag百家乐解密