动态规划

动态规划

问题一:斐波那契数列问题:

斐波那契数列是指存在递推关系为:fib(n)=fib(n-1)+fib(n-2),且fib(0)=0,例如{0,1,1,2,3,5,8,13,…}就是一个斐波那契数列
问题:给定n,求解对应的fib(n)

  1. 迭代法一:
<pre>
public class LinearRecur {
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			System.out.println(fib(i));
		}
	}
	public static int fib(int n) {
		return n > 1 ? fib(n-1)+fib(n-2) : n;
	}
}
</pre>

总结:递归版的fib是十分低效的,原因是大量的递归实例被重复的调用,该迭代算法的时间复杂度为O(2^n),如下图所示。因此需要寻求一种高校的迭代策略
在这里插入图片描述
2. 迭代法二:
将已经计算的结果制表存储,减少了实例的重复计算,计算思路如下图

<pre>
public class LinearRecur {
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			System.out.println(fib(i));
		}
	}
	public static int fib(int n) {
		int f1 = 1 ;
		int f0 = 0;
		while(n > 0) {
			n--;
			f1 = f1 + f0;
			f0 = f1 - f0;
		}
	return f0;
	}
}
</pre>

在这里插入图片描述

问题二:LCS(最长公共子序列)利用递归+分治实现

  1. 子序列:由序列中若干字符,按照原相对次序构成
    在这里插入图片描述
  2. 最长公共子序列:两个序列的公共子序中的最长者,其中第一幅图所示不叫最长公共子序列
    在这里插入图片描述
  3. 对于序列A[0,n]和序列B[0,m],LCS(A,B)存在三种情况:
    a. 若n=-1或者m=-1,则取做空序列
    b. 若A[n] = ‘X’=, 则取做LCS(A[0,n),B[0,M)) + ‘X’
    c. 若A[n] != B[m],则在LCS(A[0,n],B[0,M))与LCS(A[0,n),B[0,M])中取更长者
    整个过程可以用下图表示:
    在这里插入图片描述
<pre>
public class LinearRecur {
	public static void main(String[] args) {
		int[] a = {1,2,5,6,7,9,10};
		int[] b = {0,6,5,1,9,10};
		int aLow = 0; int aHigh = a.length-1;
		int bLow = 0; int bHigh = b.length-1;
		int length = 0;
		length = recurDivided(a,b,aLow,aHigh,bLow,bHigh);
		System.out.println(length);
	}
	public static int recurDivided(int[] a, int[] b, int aLow, int aHigh, int bLow, int bHigh) {
		if (aLow > aHigh || bLow > bHigh) {
			return 0;
		}else if (a[aHigh] == b[bHigh]) {
			int length = 0;
			length = recurDivided(a,b,aLow,aHigh-1,bLow,bHigh-1) + 1;
			return length;
		}else if (a[aHigh] != b[bHigh]){
			int length1 = 0;
			int length2 = 0;
			length1 = recurDivided(a,b,aLow,aHigh,bLow,bHigh-1);
			length2 = recurDivided(a,b,aLow,aHigh-1,bLow,bHigh);
			return length1 > length2 ? length1:length2;
		}
		return -1; //实际不会执行
	}
}
</pre>  

问题二:LCS(最长公共子序列)利用迭代实现

对于该问题和斐波那契数列问题一样,利用递归+分治的思想存在许多的实例重复计算,为了降低实例的重复计算,考虑利用动态规划的思想进行迭代计算。利用递归与分治的算法,算法的时间复杂度为O(2^n),但是考虑到实际中对应于A和B的某个前缀组合O(nm)种。因此递归+分治实现并不是一个较好的算法。因此采用动态规划的算法只需要O(nm)时间即可计算出结果。下图为具体的思路:
在这里插入图片描述

<pre>
public class LinearRecur {
	public static void main(String[] args) {
		int[] b = {0,6,5,1,9,10};
		int[] a = {1,2,5,6,7,9,10};
		int aLength = a.length;
		int bLength = b.length;
		int[][] newMatrix = new int[aLength+1][bLength+1];
		newMatrix = iterLcs(a,b);
		for (int i = 0; i < aLength + 1; i++) {
			for (int j = 0; j < bLength + 1; j++) {
				System.out.printf("%d", newMatrix[i][j]);
			}
			System.out.println();
		}
		int length = 0;
		System.out.printf("最长公共子序列长度为:%d", newMatrix[aLength][bLength]);
	}
	public static int[][] iterLcs(int[] a, int[] b) {
		int[][] newMatrix = new int[a.length+1][b.length+1];
		for (int i = 0; i < a.length; i++) {
			boolean flag = true;
			for (int j = 0; j < b.length; j++) {	
				if (flag && a[i] == b[j]) {
					newMatrix[i+1][j+1] = newMatrix[i+1][j] > newMatrix[i][j+1] ? newMatrix[i+1][j]:  newMatrix[i][j+1];
					newMatrix[i+1][j+1] += 1;
					flag = false;
				}else {
					newMatrix[i+1][j+1] = newMatrix[i+1][j] > newMatrix[i][j+1] ? newMatrix[i+1][j]:  newMatrix[i][j+1];
				}
			}
		}
	return newMatrix;
	}
}
</pre>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值