一、算法的概念
算法(algorithm)是一系列解决问题的清晰指令,也就是能对一定规范的输入,在有限时间内获得要求的输出。
程序=算法+数据结构
算法应该具备的5个基本特性
1.有穷性
算法的有穷性是指算法必须在执行有限个步骤后终止。
2.确切性
算法的每一步骤都必须有确切的定义。
3.输入项
一个算法有0个或多个输入,用于刻画运算对象的初始情况,所谓0个输入是指算法本身顶除了条件。
4.输出项
一个算法有1个或多个输出,用于反映对输入数据加工后的结果。没有输入的算法是毫无意义的。
5.可行性
算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步骤,及每个计算步骤都可以在有限时间内完成。
描述算法的方法有多种,常用的有自然语言、结构化流程图、伪代码和PAD图等,其中最普遍的是流程图。
二、枚举法简介
枚举法是利用计算机运算速度快、精确度高的特点,对要解决问题的所有可能情况,一个不漏的进行检验,从中找出符合要求的答案。
采用美剧算法解体的基本思路:
(1)确定枚举对象、美剧范围和判断条件。
(2)枚举可能的解,验证是否是问题的解。
枚举法例题:
基础: 已知等式□3×6528=3□×8256中的□内是同一个数字,设计算法求出该数字。
分析:枚举□内的数字,确定枚举范围,判断符合条件的等式。
参考程序:
#include <iostream>
using namespace std;
int main(){
for(int i=1;i<=9;i++){
if((i*10+3)*6528==(30+i)*8256)
cout<<i<<endl;
}
return 0;
}
拓展: 将数字1~9分别填入等式“□□□+□□□=□□□”的9个□中,每个数字只能使用一次。
问:如何填数才能使等式成立,你能否找出所有成立的等式?
三、算法复杂度
算法复杂度是指算法在编写成可执行的程序后,运行时所需要的时间资源和内存资源。一个算法的优劣看可以用空间复杂度与时间复杂度来衡量。
时间复杂度: 评估程序运行所需要的时间。
空间复杂度: 评估程序执行所需要的空间。
信息学竞赛中,算法的时间一般限制为1秒(CPU:2GHz左右),空间限制为265MB,时间复杂度相比空间复杂度更重要(可以用空间换时间)。
常见复杂度总结
复杂度 | 标记符号 | 说明 |
---|---|---|
常量 | O(1) | 操作的数量为常数,与输入的数据的规模无关。 |
对数 | O(log2n) | 操作的数量与输入数据的规模n的比例是log2(n)。 |
线性 | O(n) | 操作的数量与输入数据的规模n成正比 |
平方 | O(n^2) | 操作的数量与输入数据的规模n的比例为二次方 |
立方 | O(n^3) | 操作的数量与输入数据的规模n的比例为三次方 |
指数 | O(2^n) O(k^n) O(n!) | 指数级的操作,快速的增长 |
算法复杂度可以从最坏、平均和最好的角度估算。实际应用中,一般仅考虑算法在最坏情况下的运算情况,也就是对于规模为n的任何输入,算法的最长运行时间。
例如,在n个数中,顺序搜索指定值的算法效率最坏、平均、最好的情况为:
最坏的情况:n次比较。
平均情况:n/2次比较。
最佳情况:1次比较。
O(1)常量级代码
//计算梯形的面积
s=(a+b)*h;
cout<<s<<endl;
O(n)线性级代码
//计算n!
for(int i=1;i<=n;i++){
j*=i;
}
cout<<j<<endl;
O(log2(n))对数级代码
//二分查找
int binsearch(int a[],int n,int key){
int low,high mid;
low=0;
high=n-1;
while(low<=high){
mid=(low+high)>>1;
if(a[mid]==key)
return mid;
else if(a[mid]<key)
low=mid+1;
else
high=mid-1;
}
return -1;
}
O(n*log2(n))级代码
//STL快速排序
sort(a,a+n);
O(n^2)平方级代码
//比较排序
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(a[i]>a[j])
swap(a[i].a[j]);
}
}