【Leetcode】72. Edit Distance

题目:https://leetcode.com/problems/edit-distance/?tab=Description

题目要求最少的变换数目把s1变成s2,有三种操作,insert,change,delete。

f(i,j)返回从s1从i位置以后的string变换到s2从j位置以后的string,最开始从两个sting的开头比较,如果一样,返回f(i+1,j+1)。否则有三种方式,如果修改,那么就返回1+f(i+1,j+1), 如果insert,那么就返回f(i, j+1),如果delete,那么就返回f(i+1,j)。return case是只要有一个到达末尾,就返回。

有一点需要注意,就是会不会出现抖动导致死循环?就是加一个减一个。。。这样。 答案是不会的,因为insert的时候或者delete的时候,总有一个string的位置时向后移动的,因此,每一次都会向return case靠近一步。

下面是代码:

	public int minDistance(String s1, String s2) {
		if(s1.length() == 0) return s2.length();
		if(s2.length() == 0) return s1.length();
		if(s1.charAt(0) == s2.charAt(0)){
			return minDistance(s1.substring(1), s2.substring(1));
		}else{
			int deleteMin = minDistance(s1.substring(1), s2) + 1;
			int changeMin = minDistance(s1.substring(1), s2.substring(1)) + 1;
			int insertMin = minDistance(s1, s2.substring(1)) + 1;
			return Math.min(deleteMin, Math.min(changeMin, insertMin));
		}   
	}

这个实现只是一个子问题的实现,写好以后我就预感到会超时,果然。。。

因为重复计算了好多case。比如说s1=abc,s2=ebc,第一次我做一次change,递归处理了f(bc,bc),当然我也可以在s1里面加入一个e,然后处理abc和bc,这是又可以删除a,接着处理f(bc,bc),重复。

更直接的,每一次我们都有三种选择,那么复杂度基本是3的幂级别。下面一张图可以很好的解释:


如何降低?老问题,带一个memo。

	public int minDistance(String s1, String s2) {
		int[][] memo = new int[s1.length()][s2.length()];
		for(int i = 0; i < s1.length(); i++){
			Arrays.fill(memo[i], -1);
		}
		return subMinDistance(0 ,0, s1, s2, memo);
	}
	
	private int subMinDistance(int i1, int i2, String s1, String s2, int[][] memo){
		if(i1 == s1.length()) return s2.length() - i2;
		if(i2 == s2.length()) return s1.length() - i1;
		if(memo[i1][i2] >= 0) return memo[i1][i2];
		if(s1.charAt(i1) == s2.charAt(i2)){
			return subMinDistance(i1 + 1, i2 + 1, s1, s2, memo);
		}else{
			int deleteMin = subMinDistance(i1 + 1, i2, s1, s2, memo) + 1;
			int changeMin = subMinDistance(i1 + 1, i2 + 1, s1, s2, memo) + 1;
			int insertMin = subMinDistance(i1, i2 + 1, s1, s2, memo) + 1;
			memo[i1][i2] = Math.min(deleteMin, Math.min(changeMin, insertMin));
			return memo[i1][i2];
		}
	}
总结:

(1)为了分析能否通过带memo降低复杂度,可以使用子问题执行图来帮助理解。

(2)我们知道dp有两种形式,一个是自底向上,一个是自顶向下,有些情况是两种写法都可以,但是有些往往其中的一种很难写,这个与分析的过程有关。如果是dp那么应该两种都尝试,因为一种不好实现的情况下另一种没准可以。这里如果自底向上,就是从0,0开始迭代dp,其实比较难入手。

(3)解决两个字符串的问题,同时从一端开始是一个思路。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值