Java编程算法基础----组合数学实践

《组合数学》中的许多问题都可以通过计算机给出模拟(而不是通过数学公式推出),一般是利用了计算机速度优势进行大量的枚举。
许多解法中都引入“递归”算法,使得表述更加简捷。

 

示例:上台阶问题

 

n阶台阶,如果第一次上一阶台阶,则有f(n-1)种情况,第一次上二阶台阶,则有f(n-2)种情况

每个父问题都有子问题确定,递归的出口是n == 1, n == 2,此为最简单情况
代码如下:
package NO4;

public class Test25 {

	
	static int  f(int n){
		
		if(n == 1) return 1;
		if(n == 2) return 2;
		return  f(n - 1) + f(n - 2);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
          System.out.println(f(10));
	}

}



当n的数目较小时候,程序运行耗时还可以

当n的数目较大的时候,递归会递的比较深入,耗时比较严重

f(5)

   ---> f(4)

              --->f(3)

                        --->f(2)

                        --->f(1)

             ---->f(2)

   ---->f(3)

             --->f(2)

             --->f(1)

如上所示:递归中存在重复计算的过程,所以当n的数目较大的时候,耗时严重,此时应考虑优化

 

package NO4;

import java.util.*;
public class Test26 {

	static Map map = new HashMap();
	static int f(int n){
		if(map.get(n)!=null) return(Integer)map.get(n);
		int x = f(n-1) + f(n-2);
		map.put(n, x);
		return x;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        map.put(1, 1);
        map.put(2, 2);
		System.out.println(f(45));
	}

}

以上优化做的工作是,把一个值计算完成后,即保存下来,避免重复计算

利用了java中的HashMap

HashMap是一种键值对的集合,表现形式为key=value,其中key是唯一的,value可以重复,如果在开发中用到需要这种表现形式的话可以用HashMap

程序一直往下递,一直递到n == 1 , n == 2的情况,然后开始归,比如f(3) = f(2) + f(1),然后把f(3)的值保存起来,

求f(4)  = f(3) + f(2)时候,则直接调用Map存的值即可,避免重复计算


f(n)  f(n-1)    f(n-2)  f(n-3)   f(n-4)   f(4)    f(3)     f(2) 

                                              f(n-5)             f(2)     f(1)

                                  f(n-4)

                      f(n-3)


        f(n-2)   f(n-3)

                     f(n-4)


f(n)   f(n-1)    f(n-2)   f(n-3)   f(4)   f(3)   f(2)  f(1)

如上所示:f(45)会一直计算f(n-1) 即 f(44) f(43) f(42)--->f(3)->f(2)  f(1),然后再回调给父问题

如f(3) = f(2) + f(1)

f(4) = f(3) + f(2)

f(5) =(f4)+f(3)



示例:利用交互递归来判断一个数的奇偶性

package NO4;
//利用交互递归来实现判断一个数是否是偶数
public class Test28 {

	static boolean isEven(int n){ //判断是否是偶数
		if(n == 0)         //此为递归的出口
			return true;   
		else 
			return isOdd(n-1);   //输入一个数n,不确定它是否为偶数,则交由isOdd(n-1)判断
	}
	static boolean isOdd(int n){ //判断是否是奇数,如果他不是偶数,则返回true,若他是偶数,则返回false
		
		return !isEven(n);   //调用isEven(n)来判断,返回!isEven(n)
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//System.out.println(isEven(11));
		System.out.println(isOdd(11));
	}
}

此处空出解释的位置:








交通问题

如图的城市交通网,每个路口都有红绿灯。

交通问题.PNG

某车辆,从A点开始,打算去往B点。

如果只允许车辆向上和向右行驶,那么从A到B有多少种可能的路径?

代码:

设A点坐标为(0,0) B点坐标为(m,n)

则到达B点分两种情况,则需要首先到达点(m-1,n) 或点(m,n-1),后面一直可以继续递归

边界条件为当m  ==  0 或者 n  ==  0时候,返回1

package NO4;

public class Test30 {

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

		//System.out.println(f(1, 2));
		System.out.println(f(4, 4));
		//f(m, n);
	}

}

f(4,4)的结果为70

f(2,2)的结果为6

f(8,8)的结果为12870               好大呀 = =








 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值