72. Edit Distance

题目

Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.

You have the following 3 operations permitted on a word:

  • Insert a character
  • Delete a character
  • Replace a character

我的想法

如果是自顶向下,每一步操作,都是在之前的最小步数上+1,但是怎样求得第一步该怎么走。如果是自底向上,又该怎样定义子问题?太难了,做不出

解答

其实现在感觉也还是似懂非懂,不知道为什么可以想到用这种方式进行存储

leetcode solution 1: DP-Bottom up
这里只是求需要的步数,因此并不需要考虑这个操作到底是删除还是插入或改变。
cost[i][j]表示的是使word1的前i个字符与word2的前j个字符相同所需要的代价。比如w1 = abcde, w2 = abdefcost[4][2]就等于使abcd变成ab需要的最少操作,即删掉2个字符,因此为2

有三种情况

  1. word1[i] == word2[j]
    两者相等,则无需任何操作,因此cost[i][j] = cost[i - 1][j - 1]
  2. word1[i] != word2[j]
    两者若不等,则进行操作
    1. 插入,则cost[i][j] = cost[i][j - 1] + 1。比如ros, rossi = 2, j = 3时插入,cost[i][j - 1] + 1 -> cost[2][2] + 1。只有在i < j时,插入才有意义
    2. 删除,把i处的字符删掉,此时的cost[i][j] = cost[i - 1][j] + 1。只有在i > j时,删除才有意义
    3. 修改,因为字符数并没有发生改变,则cost[i][j] = cost[i - 1][j - 1] + 1
  3. 边界情况cost[k][0] = cost[0][k] = k,即最少需要k次插入或者删除
public class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();

        int[][] cost = new int[m + 1][n + 1];
        for(int i = 0; i <= m; i++)
            cost[i][0] = i;
        for(int i = 1; i <= n; i++)
            cost[0][i] = i;

        for(int i = 1; i <= m; i++) {
            for(int j = 1; j <= n; j++) {
                if(word1.charAt(i-1) == word2.charAt(j-1))
                    cost[i][j] = cost[i - 1][j - 1];
                else {
                    int a = cost[i - 1][j - 1];
                    int b = cost[i - 1][j];
                    int c = cost[i][j - 1];
                    cost[i][j] = Math.min(a,Math.min(b,c));
                    cost[i][j]++;
                }
            }
        }
        return cost[m][n];
    }
}

leetcode solution 2: DP-Bottom up optimization
改进版,速度快了一倍

public class Solution {
    public int minDistance(String word1, String word2) {
		int[] strg = new int[word2.length() + 1];
		for(int i = word1.length();i >= 0;i--){
			int save = 0;
			for(int j = word2.length();j >= 0;j--){
				if(i == word1.length()){
					strg[j] = word2.length() - j;
					continue;
				}
				if(j == word2.length()){
					save = strg[j];
					strg[j] = word1.length() - i;
					continue;
				}
				if(word1.charAt(i) == word2.charAt(j)){
					int temp = save;
					save = strg[j];
					strg[j] = temp;
				}else{
					int insert = strg[j + 1];
					int delete = strg[j];
					int replace = save;
					save = strg[j];
					strg[j] = Math.min(insert, Math.min(delete, replace)) + 1;
				}
			}
		}
		return strg[0];
    }
}

leetcode solution 3: DP-Top down

public class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();
        int[][] dp  = new int[m+1][n+1];
        return editDist(dp, word1, word2, m, n);
    }
    private int editDist(int[][] dp, String str1 , String str2 , int m ,int n){
        int result;
        if(dp[m][n] !=0) return dp[m][n];

        if(m==0) return n;
        if(n==0) return m;

        if (str1.charAt(m-1) == str2.charAt(n-1)) {
            result= editDist(dp, str1, str2, m-1, n-1); 
        }
        else{
            result =  1 + Math.min(
            Math.min(editDist(dp, str1, str2, m, n-1),    // Insert 
            editDist(dp, str1, str2, m-1, n)),   // Remove 
            editDist(dp, str1, str2, m-1, n-1)); // Replace                       
        }
        dp [m][n] =result;
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值