算法之美
数据结构 + 算法 = 程序
数据结构是程序的骨架,算法是程序的灵魂。
1.1 算法复杂性
算法是指对特定问题求解步骤的一种描述。
算法特性:
(1) 有穷性:算法是若干条指令组成的有穷序列,总是在执行若干次后结束,不可能永不停止。
(2) 确定性:每条语句有特定的含义,无歧义。
(3) 可行性:算法在当前环境条件下可以通过有限次运算实现。
(4) 输入输出:有零个或多个输入,一个或多个输出。
“好”算法的标准:
正确性、易读性、健壮性、高效性、低储存性。
时间复杂度:算法需要运行的时间,一般将算法的执行次数作为时间复杂度的度量标准。
空间复杂度:算法占用的空间大小,一般将算法的辅助空间作为衡量空间复杂度的标准。
1.2 魔鬼序列
- 棋盘麦子故事
64 个格子共放 S = 1+2+2^ 2+……+2^63 ①
把 ① 两边乘 2,
2S=2+2^ 2+……+2^64 ②
② - ①:
S = 2^64-1=18446744073709551615
这样的算法称为爆炸增量函数。
常见的算法复杂度:
(1)常数阶,用 O(1) 表示。
(2)多项式阶,用 O(n),O(n^ 2),O(n^3) 表示。
(3)指数阶,用 O(2^ n),O(n!),O(n^n) 等表示。
(4)对数阶,常见的有 O(logn),O(nlogn)。
关系:O(1)<O(logn)<O(n)<O(nlogn)<O(n^ 2)<O(n^ 3)<O(2^ n)<O(n!)<O(n^n)
- 神奇兔子序列:当月的兔子数 = 上月兔子数 + 当月新生兔子数
斐波拉契数列如下:
1,1,2,3,5,8,13,21,34…
递归表达式:
1 ,n=1
F(n)= 1 ,n=2
F(n-1)+F(n-2) ,n>2
- 算法设计:
Fib1(int n)
{
if(n<1)
return -1;
if(n=1||n=2)
return 1;
return Fib1(n-1)+Fib1(n-2);
}
时间复杂度分析:这是一个指数阶的算法。当 n 趋于无限大时,这是一个爆炸增量函数。
算法改进:
Fib2(int n)
{
int i,s1=1,s2=1;
if(n<1)
return -1;
if(n==1||n==2)
return 1;
for(i=3;i<=n;i++)
{
s2=s1+s2;//辗转相加法
s1=s2-s1;//记录前一项
}
return s2;
}
复杂度分析:时间复杂度为 O(n),空间复杂度为 O(1) ;