不知道是我太笨还是《算法》的作者脑洞大开,在第一章就看到了好多很妙的函数
1.之前看到的斐波那契数列都是递推给出的
f[n]=f[n-1]+f[n-2];
这次看到了一个代码还是挺有趣的
int f=0;//保存当前数
int g=0;//保存前一个数
for(int i=0;i<=15;i++)
{
printf("%d",f);
f=f+g;
g=f-g;
}
2.递归计算fibonacci数列
public static long Fib(int N)
{
long[]f=new long[N+1];
return fib(f,N);
}
public static long fib(long[]f,int N)
{
if(N==1)f[N]=1;
else if (N==2)f[N]=1;
else if (N>2) {
f[N]=fib(f,N-1)+fib(f,N-2);
}
return f[N];
}
public static long Fib(int N, long[] f)
{
if (f[N] == 0)
{
if (N == 1)
f[N] = 1;
else if (N > 1)
f[N] = Fib(N-1, f) + Fib(N-2, f);
}
return f[N];
}
public static void main(String[]args)
{
for(int N=0;N<100;N++)
StdOut.println(N+" "+Fib(N));
}
两个函数fib/Fib几乎一样,但是第一个效率很低,在N=42之后就很慢很慢,第二个函数效率就很高
编写递归代码时:
要有一个最简单的情况——方法的第一条总是包含return语句;
解决的是规模更小的子问题,这样才能收敛;
父问题和子问题不能有交集;
违反任意一条都可能低效或者出错,例如上面的fib函数,在求f[N]=fib(f,N-1)+fib(f,N-2)实际就说明所求子问题和父问题有交集,导致递归深度越来越大,结果就是越来越慢,但是Fib函数把父问题所求结果放在数组里,子问题求解可以直接使用,不存在交集的情况,因此效率很高。
3.计算a*b和a^b
public static int mystery(int a,int b)
{
if(b==0)return 1;//if 1--->0
if(b%2==0)return mystery(a*a,b/2);//if *---> +
return mystery(a*a,b/2)*a;//if *---> +
}