Java编程算法基础---- 构造递归思想

 抓住递归的两个要点:

1. 找到相似性。必须寻找到本问题和子问题的相似性,即:仅仅表现为同一过程的不同参数的现象。

2. 递归不要忘记了设计出口。递归必须在某个时候停止,不能无休止调用下去。


任何循环问题都是可以表达为递归的,这是必然的


利用递归解决取球问题

f(m,n)  --> f(m-1,n)

           --> f(m-1,n-1)

例如  从5个球中取得3个球的组合问题,

技巧:

ABCDE五个球,将任意的球如C球涂色,以作为标记

1.f(5,3)将5个球中取得3个球的所有组合分为两类,含有C的  f(4,2),  和不含C的  f(4,3)

则含有C的部分 可以看成是从5个球中取得3个球,且3个球中必须含有C, 该问题等价于  从4个球中取得2个球 f(4,2)

ABC

ACD

ACE

BCD

BCE

CDE

不含有C的部分 可以看成是从5个球中取得3个球,且3个球中不含有C,    该问题等价于  从4个球中取得3个球 f(4,3)

ABD

ABE

BDE

ADE

 

2.f(4,2)

相当于从A,B,D,E中选2个球的组合的个数

        AB  AD, AE  BD  BE  此时将A看成是涂色的可以分为两类  含A和不含A的

 含A         AB AD AE    f(3,1)

不含A       BD BE         f(3,2)

           f(4,2)---->f(3,2)

                   ---->f(3,1)

    f(3,1)

                        相当于从B, D, E中选1个球的组合个数

                       B,D,E  此时将B看成是涂色的,可以分为两类,含B和不含B的

 含B                     B              f(2,0)

不含B                  D,E           f(2,1)

            

                    f(3,1) --->f(2,1)

                              --->f(2,0)

      f(2,1)

                      相当于从D,E中选一个球的组合个数

                      D,E此时可将D看成是涂色的,可以分为两类,含D和不含D的

含D                 D           f(1,0)

不含D             E           f(1,1)

     

 

3.f(4,3)

相当于从A,B,D,E中选3个球的组合的个数

ABD

ABE

BDE

ADE 

     将A看成是标记的

则可以分为两类

含A     ABD ABE ADE  f(3,2)

不含A  BDE         f(3,3)

 

f(3,3)可以看成从BDE中选3个球的组合的个数

f(3,3)---->f(2,3)

        ---->f(2,2)

     f(4,3)--->

             --->f(3,3)

             --->f(3,2)

f(5,3)

          --->f(4,3)

                    --->f(3,3)

                             --->f(2,3) m < n 返回0

                             --->f(2,2)

                                      --->f(1,2) m < n

                                      --->f(1,1)

                                             --->f(0,1)  m < n

                                             --->f(0,0)   n = 0 返回1

          

                    --->f(3,2)

                              --->f(2,2)

                                          --->f(1,2)  m < n

                                          --->f(1,1)

                                                  --->f(0,1)  m < n

                                                  --->f(0,0)   n = 0

                              --->f(2,1)

                                          --->f(1,1)

                                                  --->f(0,1)  m < n

                                                  --->f(0,0)   n = 0

                                          --->f(1,0) 

                                                 --->f(0,0)  n  = 0

                                                 --->f(0,-1) m < n

 

 

         --->f(4,2)

                     --->f(3,2)

                     --->f(3,1)

 

 

编程中很多问题比较抽象啊= =  比如这个取球的问题

递归的出口不太好想啊

一定会递归到 m < n

                  n ==0

这两种情况下么?

我能想到的是 m ==n

                  n  == 1

 

现在你让我把这个问题讲的很清楚,我也做不到,我只能模糊的大概解释下= =\\\\\

 

ex1:

package NO4;

public class Test10 {

	
	private static int f(int m, int n){
		
		if(m == n ) return 1;
		//if(n == 0 )
			//return 1;
		if(n == 1) return m;
		return f(m - 1, n) + f( m - 1 , n - 1);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		
		System.out.println(f(10, 1));
 
                System.out.println(f(3,5));//此种情况下会出现栈溢出,因为该版本的程序应满足 m >= n
	}

}
ex2:

public class Test11 {

	private static int f(int m, int n){
		
		if(m < n ) return 0;
		if(n == 0 )
		 	return 1;
		return f(m - 1, n) + f( m - 1 , n - 1);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		
		System.out.println(f(10, 3));
	}

}

ex3:

此为最终版本

加入  if(m==n) return 1;if(n ==1 ) return m;

作为优化,使得递归层次减少,增加效率

package NO4;

public class Test12 {

	private static int f(int m, int n){
		
		if(m < n)   return 0;
		if(m == n)  return 1;
		if(n == 1)  return m;
		if(n == 0)  return 1;
		return f(m - 1, n) + f( m - 1 , n - 1);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		
		System.out.println(f(10, 3));
	}

}



下面这个是利用递归来解决比较字符串是否相同的问题

package NO4;
/*
 * 串的比较

比较两个串的内容是否相同的规则是:

比较对应位置的每个字母,出现一处不同,则不相同。 一个串为空时,另一个不空,则不同。

请用递归的方法,重现实现比较两个串的内容是否相同。
 * 
 * 
 */
public class Test13 {

	static boolean f(String s1, String s2, int index){
		boolean isEqual = true;
		if(s1.length() != s2.length()) //如果字符串长度不相同则,则s1和s2不相等,直接跳出
			return false;
		if(index == s1.length()) //当比较到子串串的末尾,则说明,s1和s2是相同的,返回true
			return true;
		if(s1.charAt(index) != s2.charAt(index)) //如果本次比较出不相等,则返回false
            return false;
		else                                    //如果本次比较相等,则比较下一次
			isEqual = f(s1, s2, ++index);
		return isEqual;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        
		//System.out.println(f("abcd", "abc", 0));
		System.out.println(f("abc", "a c", 0));
		System.out.println(f("abc", "abc", 0));
		
		
		System.out.println(f("abc", "abc ", 0));
		//System.out.println(f("", "abc ", 0));
	    System.out.println(f("", "", 0));
	    System.out.println(f("abdc", "adcd", 0));
	}

}


1.注意找到当前问题与子问题之间的相似性

即比较当前index标记的元素是否相同,如果不相同则直接返回false,一直回调到起始调用处

如果相同则,继续递归, ++index 进行下一次的比较,  如果递归到字符串的末尾,则两个字符串比较完毕,完全相同

,返回true,一直讲将true回调到起始调用处即可

2.注意当前问题域子问题之间的回调, 因为当子问题解决的时候,需要将相关的结果回调给父问题,此为回溯

递归问题包括 递归过程和回溯过程     两个过程

 

 

递归不太好理解,需要经常把将整个过程完整的用图来示意出来

数据结构中用到了大量的递归,需要好好掌握!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值