fibonacci数列的两种求解方式:基础递归VS动态规划

11 篇文章 0 订阅

动态规划的核心是要找到“状态”和“状态转移方程”,“状态"用来描述该问题的子问题的解。

/*
 * 基础解法,按照递归方法求解,该算法的运算时间是指数级增长的
 * 这种算法对于相似的子问题进行了重复的计算,因此不是一种高效的算法
 */
public class FibonacciRecursion {
	
	//-----------计算Fibonacci数列值的递归函数--------------
	public static int fib(int n){
		if(n==1||n==2){//序列中第1,2个数为1
			return 1;
		}
		return fib(n-1)+fib(n-2);
	}
	
	public static void main(String[] args) {
		int i=46;
		long begin=System.currentTimeMillis();
		System.out.println("fib("+i+"):"+fib(i));
		long cost=System.currentTimeMillis()-begin;
		System.out.println("耗时:"+cost+"ms");
	}
}

当n=5时,fib(5)的计算过程如下:

  1. fib(5)
  2. fib(4) + fib(3)
  3. (fib(3) + fib(2)) + (fib(2) + fib(1))
  4. ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
  5. (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))

由上面可以看出,这种算法对于相似的子问题进行了重复的计算,因此不是一种高效的算法。

下面采用动态规划的思想来求解

/*
 * 可以通过保存已经算出的子问题的解来避免重复计算
 * 即使用动态规划的技术
 */
public class FibonacciDP {

	// ----------使用动态规划(DP)求fibonacci数列的值------------
	public static int fib(int n) {
		int[] array = new int[n];//用来保存动态规划过程中的状态
		array[0] = 1;
		array[1] = 1;
		for (int i = 2; i < n; i++)
			array[i] = array[i - 1] + array[i - 2];//动态规划的状态转移式
		return array[n-1];
	}

	public static void main(String[] args) {
		long begin=System.currentTimeMillis();
		System.out.println("fib(46):"+fib(46));
		long cost=System.currentTimeMillis()-begin;
		System.out.println("耗时:"+cost+"ms");
	}
}

/*
 * 采用动态规划求解最长非降子序列的长度
 */
public class Lis {
	public static void main(String[] args) {
		int[] src = { 1, 2, 5, 3, 4, 9, 10, 6, 7, 8 };
		System.out.println("本例的最长非降子序列:1 2 3 4 6 7 8");
		System.out.println("<span style="line-height: 22.3999996185303px; font-family: sans-serif;">最长非降子序列长度</span>:" + lis(src));
	}

	public static int lis(int[] src) {
		int n = src.length;
		int[] dis = new int[n];// 保存"状态"的数组
		int len = 1;// 返回最大非降子序列的长度
		for (int i = 0; i < n; i++) {
			dis[i] = 1;
			for (int j = 0; j < i; j++) {
				if (src[j] < src[i] && dis[j] + 1 > dis[i])
					dis[i] = dis[j] + 1;
			}
			if (dis[i] > len) {
				len = dis[i];
			}
		}
		return len;
	}
}
参考文献(关于动态规划)
http://www.hawstein.com/posts/dp-novice-to-advanced.html
http://blog.csdn.net/woshioosm/article/details/7438834

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程猿薇茑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值