今天学习了递归调用的经典问题,递归的核心在于:找出相似点,定义出口。平地起风雷,而且,递归的函数参数一定得有变化,且规模越来越小。
先来看在蓝桥杯中出现的经典递归问题
eg1、反转串(例如,将“abc”-->"cba")
public static String f(String s){
if(s.length()<=1) return s;
return f(s.substring(1))+s.charAt(0); //填空
eg2、杨辉三角形,计算第m行第n个系数的值。
public static int f(int m,int n){
if(n==0||m==n) return 1;
return f(m-1,n) + f(m-1,n-1); //填空
}
eg3、计算m个A,n个B可以组成多少种组合。
public static int f(int m,int n){
if(m==0||n==0) return 1;
return f(m-1,n) +f(m,n-1); //分别考虑首位置为A或B的情况。
}
eg4、整数的划分,例如,6可以分解为加法划分
6
5 1
4 2 4 1 1
........
对于给定的正整数n,编写算法打印所有划分。
public static void f(int n,int[]a,int k){
//a为缓冲,k为当前位置。
if(n<=0){
for(int i = 0;i<k;i++){
System.out.print(a[i]+" ");
}
System.out.println();
}
for(int i = n;i>0;i--){
if(k>0 && i>a[k-1]) continue;
a[k] = i;
f(n-i,a,k+1); //精髓所在。
}
}
eg5
具体代码如下:
1、求最大公共子序列的长度
public static int f(String s1,String s2){
if(s1.length()==0||s2.length()==0)
return 0;
if(s1.charAt(0)==s2.charAt(0))
return f(s1.substring(1),s2.substring(2));
else
return Math.max(f(s1.substring(1),s2)),f(s1,s2.substring(1)));
}
2、排列组合
(1)从n个球中取出m个球有多少种组合。
递归的代码非常简短,但是,前提是我们要理解递归的思想。就拿这道题来分析的话,一开始,我们要把这个整体进行划分,怎么划分,我们可以想象在n个球中有一个特殊的球x,取法划分为包含x和不包含x的情况。具体代码如下:
public static int f(int n,int m){
if(n<=m) return 0;
if(n==m) return 1;
if(m==0) return 1;
return f(n-1,m-1) + f(n-1,m);
}
(2)求n个元素的全排列
public static void f(char[]data,int k){
//k为当前的位置,与其后的元素交换位置
if(k==data.length){
for(int i = 0;i<data.length;i++){
System.out.print(data[i]+" ");
System.out.println();
}
for(int i = k;i<data.length;i++){
char t = data[k];
data[k] = data[i];
data[i] = t; //交换位置,试探。
f(data,k+1);
char t = data[k];
data[k] = data[i];
data[i] = t; //回溯 } }