转自:http://blog.csdn.net/justinavril/archive/2008/08/01/2753596.aspx
所谓递归问题,可以分成两部分来理解:一是基本问题,也可以称之为原始问题,比较好解决;二是后续问题,比较复杂,但是和原始问题比较类似,可以调用自身的一个新的副本去解决它。
最简单的可以归为递归问题的就是阶乘,1的阶乘我们知道是1,2的阶乘为2*1=2*1!,而3的阶乘又是3*2!...这样我们就能够知道如何用递归去实现n的阶乘了。
- public class Factorial {
- public static int factorial (int n){
- int result = 0;
- if (n <= 1){
- result = 1;
- }
- else if (n > 1){
- result = n * factorial (n-1);
- }
- return result;
- }
- public static void main (String args[]){
- for (int i=0; i<10; i++)
- System.out.print(factorial (i) +" ");
- }
- }
输出:
- 1 1 2 6 24 120 720 5040 40320 362880
当然了这是最简单的,也是最好理解的递归例子,但是它揭示了递归的实质:将复杂问题递归为简单问题解决...
我们再来看看稍微复杂点的,也比较有意思,汉诺塔问题:有1,2,3这3个柱子,1号柱子上有n个盘子(盘子由小到大地串在上面,且小盘子永远不能在大盘子下面),以2号柱子为临时存放地,最终将n个盘子移到3号柱子上。将这个问题分析为递归问题,分解出以下三点:
1. 从1号柱子移动n-1个盘子到2号柱子,3号柱子为临时存放点;
2. 从1号柱子将第n个盘子移到3号柱子;
3. 将n-1个柱子从2号柱子移到3号柱子,1号柱子为临时存放点。
请看代码:
- public class Hanoi {
- public static void hanoi (int movingPans, String sourcePillar, String targetPillar, String tempPillar){
- if (movingPans == 1){
- movePans (1, sourcePillar, targetPillar);
- }
- else{
- hanoi(movingPans-1, sourcePillar, tempPillar, targetPillar);
- movePans (movingPans, sourcePillar, targetPillar);
- hanoi(movingPans-1, tempPillar, targetPillar, sourcePillar);
- }
- }
- public static void movePans (int panNum, String sourcePillar, String targetPillar){
- System.out.println("Move "+ panNum +" form "+ sourcePillar +"# to "+ targetPillar +"#");
- }
- public static void main(String args[]){
- System.out.println("3个盘子的汉诺塔问题:");
- hanoi(3, "1", "3", "2");
- System.out.println("5个盘子的汉诺塔问题:");
- hanoi(5, "1", "3", "2");
- }
- }
输出:
- 3个盘子的汉诺塔问题:
- Move 1 form 1# to 3#
- Move 2 form 1# to 2#
- Move 1 form 3# to 2#
- Move 3 form 1# to 3#
- Move 1 form 2# to 1#
- Move 2 form 2# to 3#
- Move 1 form 1# to 3#
- 5个盘子的汉诺塔问题:
- Move 1 form 1# to 3#
- Move 2 form 1# to 2#
- Move 1 form 3# to 2#
- Move 3 form 1# to 3#
- Move 1 form 2# to 1#
- Move 2 form 2# to 3#
- Move 1 form 1# to 3#
- Move 4 form 1# to 2#
- Move 1 form 3# to 2#
- Move 2 form 3# to 1#
- Move 1 form 2# to 1#
- Move 3 form 3# to 2#
- Move 1 form 1# to 3#
- Move 2 form 1# to 2#
- Move 1 form 3# to 2#
- Move 5 form 1# to 3#
- Move 1 form 2# to 1#
- Move 2 form 2# to 3#
- Move 1 form 1# to 3#
- Move 3 form 2# to 1#
- Move 1 form 3# to 2#
- Move 2 form 3# to 1#
- Move 1 form 2# to 1#
- Move 4 form 2# to 3#
- Move 1 form 1# to 3#
- Move 2 form 1# to 2#
- Move 1 form 3# to 2#
- Move 3 form 1# to 3#
- Move 1 form 2# to 1#
- Move 2 form 2# to 3#
- Move 1 form 1# to 3#
在前文《递归问题一》中简单介绍了几个典型的递归问题。前几天看到一个人在论坛里问,如何实现一个字符串数组的全排列问题,底下人都说可以用递归方法实现,我想了会,没想出来,不过有人贴出了他的代码,我这里借用一下:
- public class AllSort{
- public static void main(String[] args) {
- char buf[]={'a','b','c'};
- perm(buf,0,buf.length-1);
- }
- public static void perm(char[] buf,int start,int end){
- if(start==end){//当只要求对数组中一个字母进行全排列时,只要就按该数组输出即可
- for(int i=0;i<=end;i++){
- System.out.print(buf[i]);
- }
- System.out.println();
- }
- else{//多个字母全排列
- for(int i=start;i<=end;i++){
- char temp=buf[start];//交换数组第一个元素与后续的元素
- buf[start]=buf[i];
- buf[i]=temp;
- perm(buf,start+1,end);//后续元素递归全排列
- temp=buf[start];//将交换后的数组还原
- buf[start]=buf[i];
- buf[i]=temp;
- }
- }
- }
- }
输出:
- abc
- acb
- bac
- bca
- cba
- cab
还有一个比较著名的递归问题,就是n皇后问题。就是在一个n*n的国际象棋的方格中,怎么样才能将n个皇后摆在棋盘上共存。我们知道皇后是能横着,竖着和对角线这样三条路子。以8皇后为例讨论这个问题,那么为了和Java中的数组第一个索引0更好的结合起来,我们定义8*8的棋盘中每个方格的坐标为(0, 0),(0, 1)...假定两个皇后(i, j),(k, l),那么这两个皇后的坐标一定得满足:(i != k) && (j != l) && (|i-k| != |j-l|)。我们以一个长度为8的数组表示皇后的坐标,例如(0, 1, 2, ... , 7),这就意味着第一个皇后摆在(0, 0)上,第二个皇后在(1, 1)上,依次类推。这样就能保证每个皇后的纵坐标是不一样的。下面是具体的实现代码:
- class NQueen{
- private int noOfSolutions;
- private int noOfQueens;
- private int[] queensInRow;
- public NQueen (){
- this.noOfQueens = 8;
- this.queensInRow = new int[8];
- this.noOfSolutions = 0;
- }
- public NQueen (int queens){
- this.noOfQueens = queens;
- this.queensInRow = new int[noOfQueens];
- this.noOfSolutions = 0;
- }
- public boolean canPlaceQueen (int k, int i){
- for (int j=0; j<k; j++){
- if ((queensInRow[j]==i) || (Math.abs(queensInRow[j]-i)== Math.abs(j-k))){
- return false;
- }
- }
- return true;
- }
- public void queensConfiguration (int k){
- for (int i=0; i<noOfQueens; i++){
- if (canPlaceQueen(k, i)){
- queensInRow[k] = i;
- if (k == noOfQueens-1){
- printConfiguration();
- }
- else{
- queensConfiguration(k+1);
- }
- }
- }
- }
- public void printConfiguration (){
- noOfSolutions ++;
- System.out.print("(");
- for (int i=0; i<noOfQueens-1; i++){
- System.out.print(queensInRow[i] +", ");
- }
- System.out.println(queensInRow[noOfQueens-1] +")");
- }
- public int solutionsCount(){
- return noOfSolutions;
- }
- }
- public class TestNQueen {
- public static void main (String args[]){
- NQueen queen = new NQueen();
- queen.queensConfiguration(0);
- }
- }
输出:
- (0, 4, 7, 5, 2, 6, 1, 3)
- (0, 5, 7, 2, 6, 3, 1, 4)
- (0, 6, 3, 5, 7, 1, 4, 2)
- (0, 6, 4, 7, 1, 3, 5, 2)
- (1, 3, 5, 7, 2, 0, 6, 4)
- (1, 4, 6, 0, 2, 7, 5, 3)
- (1, 4, 6, 3, 0, 7, 5, 2)
- (1, 5, 0, 6, 3, 7, 2, 4)
- (1, 5, 7, 2, 0, 3, 6, 4)
- (1, 6, 2, 5, 7, 4, 0, 3)
- (1, 6, 4, 7, 0, 3, 5, 2)
- (1, 7, 5, 0, 2, 4, 6, 3)
- (2, 0, 6, 4, 7, 1, 3, 5)
- (2, 4, 1, 7, 0, 6, 3, 5)
- (2, 4, 1, 7, 5, 3, 6, 0)
- (2, 4, 6, 0, 3, 1, 7, 5)
- (2, 4, 7, 3, 0, 6, 1, 5)
- (2, 5, 1, 4, 7, 0, 6, 3)
- (2, 5, 1, 6, 0, 3, 7, 4)
- (2, 5, 1, 6, 4, 0, 7, 3)
- (2, 5, 3, 0, 7, 4, 6, 1)
- (2, 5, 3, 1, 7, 4, 6, 0)
- (2, 5, 7, 0, 3, 6, 4, 1)
- (2, 5, 7, 0, 4, 6, 1, 3)
- (2, 5, 7, 1, 3, 0, 6, 4)
- (2, 6, 1, 7, 4, 0, 3, 5)
- (2, 6, 1, 7, 5, 3, 0, 4)
- (2, 7, 3, 6, 0, 5, 1, 4)
- (3, 0, 4, 7, 1, 6, 2, 5)
- (3, 0, 4, 7, 5, 2, 6, 1)
- (3, 1, 4, 7, 5, 0, 2, 6)
- (3, 1, 6, 2, 5, 7, 0, 4)
- (3, 1, 6, 2, 5, 7, 4, 0)
- (3, 1, 6, 4, 0, 7, 5, 2)
- (3, 1, 7, 4, 6, 0, 2, 5)
- (3, 1, 7, 5, 0, 2, 4, 6)
- (3, 5, 0, 4, 1, 7, 2, 6)
- (3, 5, 7, 1, 6, 0, 2, 4)
- (3, 5, 7, 2, 0, 6, 4, 1)
- (3, 6, 0, 7, 4, 1, 5, 2)
- (3, 6, 2, 7, 1, 4, 0, 5)
- (3, 6, 4, 1, 5, 0, 2, 7)
- (3, 6, 4, 2, 0, 5, 7, 1)
- (3, 7, 0, 2, 5, 1, 6, 4)
- (3, 7, 0, 4, 6, 1, 5, 2)
- (3, 7, 4, 2, 0, 6, 1, 5)
- (4, 0, 3, 5, 7, 1, 6, 2)
- (4, 0, 7, 3, 1, 6, 2, 5)
- (4, 0, 7, 5, 2, 6, 1, 3)
- (4, 1, 3, 5, 7, 2, 0, 6)
- (4, 1, 3, 6, 2, 7, 5, 0)
- (4, 1, 5, 0, 6, 3, 7, 2)
- (4, 1, 7, 0, 3, 6, 2, 5)
- (4, 2, 0, 5, 7, 1, 3, 6)
- (4, 2, 0, 6, 1, 7, 5, 3)
- (4, 2, 7, 3, 6, 0, 5, 1)
- (4, 6, 0, 2, 7, 5, 3, 1)
- (4, 6, 0, 3, 1, 7, 5, 2)
- (4, 6, 1, 3, 7, 0, 2, 5)
- (4, 6, 1, 5, 2, 0, 3, 7)
- (4, 6, 1, 5, 2, 0, 7, 3)
- (4, 6, 3, 0, 2, 7, 5, 1)
- (4, 7, 3, 0, 2, 5, 1, 6)
- (4, 7, 3, 0, 6, 1, 5, 2)
- (5, 0, 4, 1, 7, 2, 6, 3)
- (5, 1, 6, 0, 2, 4, 7, 3)
- (5, 1, 6, 0, 3, 7, 4, 2)
- (5, 2, 0, 6, 4, 7, 1, 3)
- (5, 2, 0, 7, 3, 1, 6, 4)
- (5, 2, 0, 7, 4, 1, 3, 6)
- (5, 2, 4, 6, 0, 3, 1, 7)
- (5, 2, 4, 7, 0, 3, 1, 6)
- (5, 2, 6, 1, 3, 7, 0, 4)
- (5, 2, 6, 1, 7, 4, 0, 3)
- (5, 2, 6, 3, 0, 7, 1, 4)
- (5, 3, 0, 4, 7, 1, 6, 2)
- (5, 3, 1, 7, 4, 6, 0, 2)
- (5, 3, 6, 0, 2, 4, 1, 7)
- (5, 3, 6, 0, 7, 1, 4, 2)
- (5, 7, 1, 3, 0, 6, 4, 2)
- (6, 0, 2, 7, 5, 3, 1, 4)
- (6, 1, 3, 0, 7, 4, 2, 5)
- (6, 1, 5, 2, 0, 3, 7, 4)
- (6, 2, 0, 5, 7, 4, 1, 3)
- (6, 2, 7, 1, 4, 0, 5, 3)
- (6, 3, 1, 4, 7, 0, 2, 5)
- (6, 3, 1, 7, 5, 0, 2, 4)
- (6, 4, 2, 0, 5, 7, 1, 3)
- (7, 1,