LCS的两种解法比较

动态规划问题一般具有两个要素:最优子结构与子问题重叠。

通常在求解LCS问题时,我们都会用到两种方法:

1. momo-ization(备忘录方法)

利用了该问题的重叠子问题特性,而重叠子问题可以使用递归直接解决

 0ABCBDAB
000000000
B00111111
D00111222
C00122222
A01122232
B01223334
A01223344

所谓自上而下就是从下表最大处开始递归求解,最终结果为LCS(x,y,x.length,y.length);

也就是上表中从最后一格向上回溯直到哨兵的过程,在求解每个子问题之前,我们先检测一下这个子问题之前有没有算过,若果有,那么不用计算直接返回结果,如果没有,那么就计算这个子问题,之后将结果保存起来,方便下次再遇到时使用。。

时间复杂度T(n) = O(mn);

空间复杂度S = O(mn);//二维数组

public class TTBlcs {
	static int[][] c = new int[100][100];
	static int NIF = 9999;
	public static void main(String[] args) {		
		char[] x = {'A','B','C','B','D','A','B'};
		char[] y = {'B','D','C','A','B','A'};
		
		//TTBlcs t = new TTBlcs();
		for(int i = 0;i <= x.length;i++){//周围有一圈哨兵均为0
			for(int j = 0;j <= y.length;j++)
			{
				c[i][j] = NIF;
			}
		}
		System.out.print(LCS(x,y,x.length,y.length));//自上而下
	}
	
	public static int LCS(char[] x,char[] y,int i,int j){
		if(c[i][j] < NIF)//记录如果算出来便直接返回(备忘)
			return c[i][j];
		if((i == 0)||(j == 0)){
			c[i][j] = 0;
		}
		else if(x[i-1] == y[j-1])
				c[i][j] = LCS(x,y,i-1,j-1) + 1;
		else 
				c[i][j] = LCS(x,y,i-1,j) >= LCS(x,y,i,j-1)? LCS(x,y,i-1,j):LCS(x,y,i,j-1);
		return c[i][j];
	}

}

2. 动态规划DP:

所谓自下而上,就是从下标(1,1)处开始求解的过程,不过省去了递归的过程,自下而上的构建原问题的解,首先求解最基本的情况,再从最基本的情况一部一部的向上求解,比如我要求解[2…4],那么我首先需要知道[2…2][3…4]和[2…3][4…4]的最优解,需要知道[3…4],那么首先需要知道[3…3][4…4]的最优解,所以,倒不如我们将原问题需要的解先构建出来,再慢慢向上一层一层的构建,最后组成原问题的解!。

时间复杂度T(n) = O(mn);

空间复杂度S = O(mn);//二维数组

public class BTTlcs {
	static int[][] c = new int[100][100];
	public static void main(String[] args) {
		char[] x = {'A','B','C','B','D','A','B'};
		char[] y = {'B','D','C','A','B','A'};
		for(int k = 0;k <= x.length;k++)
		{
			c[0][k] = 0;
		}
		for(int k = 0;k <= y.length;k++)
		{
			c[k][0] = 0;
		}
		LCS(x,y);
 	}
	
	public static void LCS(char[] x,char[] y){
		for(int i = 1;i <= x.length;i++)
		{
			for(int j = 1;j <= y.length;j++)
			{
				if(x[i-1] == y[j-1])
					c[i][j] = c[i-1][j-1] + 1;
				else 
					c[i][j] = c[i-1][j] >= c[i][j-1]?c[i-1][j]:c[i][j-1];
			}
		}
		for(int i = 0;i <= x.length;i++)
		{
			for(int j = 0;j<y.length;j++)
			{
				System.out.print(c[i][j]);
			}
			System.out.print("\n");
		}
		System.out.print(c[x.length][y.length]);
	}
}

  • 自上而下的优点是并不需要求解每一个子问题的解,而是只求解有需要的子问题的解,缺点就是需要递归调用,函数调用浪费时间。
  • 自下而上的优点是并不需要递归调用,每个子问题求解的速度较快,缺点每个子问题都要计算,就算这个子问题的解对原问题的解并没有任何帮助!

    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值