递归?首先明白何为递归。
递归有两个要点:1.自己直接或者间接地调用自己。2.必须有递归出口。
优点:容易设计算法,易于思考。
缺点:时间复杂度过高,运用递归时,注意数据规模。
递归特点:
1、问题P的描述涉及规模P(n); 2、规模变小之后,问题的性质不会发生变化; 3、问题有解决出口
样例分析:
一、阶乘问题 二、汉诺塔问题 三、全排列问题
四、最大公约数和最小公倍数 五、整数划分问题
问题一解答,递归完成n!f(n)=n*f(n-1) n!=0 if(n==0) f(n)=1;
int f(int n){//求n!
if(n==0) return 1;
else if(n<0) return n*f(n+1);
else return n*f(n-1);
}
问题二描述:
有X,Y,Z三个塔柱,X上有n个盘子,从小到大盘子一次增大,求出把盘子移动到Z上的最小步数。
要求:1.一次移动一个 2.任何时刻,要求大的盘子都不能在小的盘子上面。Y作为辅助塔柱
问题分析:设置函数Hanoi(X,Y,Z,n);
1,若要吧把第n个盘子移动到Z上,首先把X上的前n-1个盘子移动到Y塔柱上,(此时Z可以作为辅助塔柱)
此时函数为Honoi(X,Z,Y,n-1); Move X—–>Z(1次)
2、把Y上的全部盘子移动到Z上 ,函数为Hanoi(Y,X,Z,n-1);
int sum=0;//每次运行时,置0
void Hanoi(char X,char Y,char Z,int n){
if(n>0){
Hanoi(X,Z,Y,n-1);
++sum;
Hanoi(Y,X,Z,n-1);
}
}
问题三:
求数组的全排列或者求数组a的第k到第n个元素的全排列。
深度搜索,
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
void range(int a[],int k,int n){
if(k==n) {
for(int i=1;i<=n;i++){
printf(“%d”,a[i]);
}
printf(“\n”);
}
for(int i=k;i<=n;i++){
swap(a[k],a[i]);
range(a,k+1,n);
swap(a[k],a[i]);
}
}
int main()
{
int a[10]={0,1,2,3,4,5,6,7,8,9};
range(a,1,4);
return 0;
}
问题四:
题目描述:将一个整数n表示成一系列正整数之和。n=n1+n2+……+nk,其中5=1+4; 5=4+1是一种,
正整数n的不同划分个数为正整数的划分数,记做P(n).
1、题解,在正整数所有不同划分中,将最大加数n1不大于m的划分记做q(n,m);
(1)、q(n,1)=1; n>=1 即 n=1+1+…+1
(2)、q(n,m)=q(n,n) m>=n; 最大加数不能大于n,q(1,m)=1
(3)、q(n,n)=1+q(n,n-1) 最大加数等于n和小于n的所有个数
(4)、q(n,m)=q(n,m-1)+q(n-m,m); 最大加数等于m和小于m-1的划分个数
代码如下:
int q(int n,int m){
if((n<1)||(m<1)) return 0;
if((n==1)||(m==1)) return 1;
if(n<m) return q(n,n);
if(n==m) return q(n,m-1)+1;
return q(n,m-1)+q(n-m,m);
}
int qq(int n){
if(n<1) return 0;
if(n==1) return 1;
else return qq(n-1)+1;
}
进阶问题:求出正整数n的所有划分并打印,
例如:
n=2 :2=1+1
n=3 :3=1+2
=1+1+1
n=4 :4=1+3
=1+1+2
=1+1+1+1
=2+2
n=7 :7=1+6
=1+1+5
=1+1+1+4
=1+1+1+1+3
=1+1+1+1+1+2
=1+1+1+1+1+1+1
=1+1+1+2+2
=1+1+2+3
=1+2+4
=1+3+3
=2+5
=2+2+3
=3+4
题解:可以用数组a存储完成n的一种划分,分析n=7时,可以按a[1]分类(即以1开头,按划分的第一的数分类),可得到a[1]=[1,n/2],共n/2大类,对于每一类划分都有a[1]=i; a[2]=n-i; 然后从k=2,继续拆分a[k],a[k]能否拆分取决于a[k]/2是否大于a[k-1].递归过程中的参数,指向的a[k]的下标k
代码:
#include<iostream>
#include<cstdio>
#define MOD 1000000007
using namespace std;
void split(int t,int n){
printf(“%d=”,n);
for(int i=1;i<=t;i++){
if(i==1) printf(“%d”,a[i]);
else printf(“+%d”,a[i]);
}
printf(“\n”);
int j,l;
j=t; l=a[j];
for(int i=a[j-1];i<=l/2;i++){
a[j]=i; a[j+1]=l-i;
split(j+1,n);
}
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n/2;i++){
//cout<<” “<<endl;
a[1]=i; a[2]=n-i; split(2,n);
}
return 0;
}
备注:笔者水平有限,希望各路大牛不吝指教。于2014年10月7日 22:22