1. 程式人生 > >Edit Distance 編輯距離演算法 @LeetCode

Edit Distance 編輯距離演算法 @LeetCode

思路:

又是一道典型DP!

我們將人生劃為詭異的階段
我們把這個世界表為豐富的狀態

package DP;

import java.util.Arrays;

/**
 * Edit Distance 
 * 
 * Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character
 */
public class EditDistance {

	static int[][] dist = null;
	
	public static void main(String[] args) {
		String word1 = "sdfsssjdfhsb";
		String word2 = "cvdsfadfgkdfgj";
		
		dist = new int[word1.length()+1][word2.length()+1];
		for(int[] row : dist){
			Arrays.fill(row, -1);
		}
		
		System.out.println(minDistance(word1, word2));
		System.out.println(minDistance2(word1, word2));
	}
	
	public static int min3(int a, int b, int c){
		return Math.min(Math.min(a, b), c);
	}
	
	// DP bottom-up
	public static int minDistance(String word1, String word2) {
		int[][] distance = new int[word1.length()+1][word2.length()+1];
		
		// 邊界情況:當其中一個string為空時,只要一直新增或刪除就可以
		for(int i=0; i<=word1.length(); i++){
			distance[i][0] = i;
		}
		for(int j=1; j<=word2.length(); j++){
			distance[0][j] = j;
		}
		
		// 遞推,[i][j]處可以由左,上,左上3種情況而來
		for(int i=1; i<=word1.length(); i++){
			for(int j=1; j<=word2.length(); j++){
				distance[i][j] = min3(distance[i-1][j]+1,	// 從上演變
											distance[i][j-1]+1,	// 從左演變
											distance[i-1][j-1]+(word1.charAt(i-1)==word2.charAt(j-1) ? 0 : 1));	// 從左上演變,考慮是否需要替換
			}
		}
		return distance[word1.length()][word2.length()];		// 返回右下角
    }

	// 遞迴,太慢
	public static int minDistance2(String word1, String word2) {
//		return rec(word1, word1.length(), word2, word2.length());
		return rec2(word1, word1.length(), word2, word2.length());
	}
	
	public static int rec(String word1, int len1, String word2, int len2){
		if(len1 == 0){
			return len2;
		}
		if(len2 == 0){
			return len1;
		}
		if(word1.charAt(len1-1) == word2.charAt(len2-1)){
			return rec(word1, len1-1, word2, len2-1);
		}else{
			return min3(rec(word1, len1-1, word2, len2-1) + 1, 
							rec(word1, len1, word2, len2-1) + 1, 
							rec(word1, len1-1, word2, len2) + 1);
		}
	}
	
	// 新增全域性陣列,儲存狀態,用空間換時間 DP top-down
	public static int rec2(String word1, int len1, String word2, int len2){
		if(len1 == 0){
			return len2;
		}
		if(len2 == 0){
			return len1;
		}
		
		if(word1.charAt(len1-1) == word2.charAt(len2-1)){
			if(dist[len1-1][len2-1] == -1){
				dist[len1-1][len2-1] = rec2(word1, len1-1, word2, len2-1);
			}
			return dist[len1-1][len2-1];
		}else{
			if(dist[len1-1][len2-1] == -1){
				dist[len1-1][len2-1] = rec2(word1, len1-1, word2, len2-1);
			}
			if(dist[len1][len2-1] == -1){
				dist[len1][len2-1] = rec2(word1, len1, word2, len2-1);
			}
			if(dist[len1-1][len2] == -1){
				dist[len1-1][len2] = rec2(word1, len1-1, word2, len2);
			}
			dist[len1][len2] = min3(dist[len1-1][len2-1]+1, dist[len1][len2-1]+1, dist[len1-1][len2]+1);
			return dist[len1][len2];
		}
	}
}


Ref:

這個視訊講的特別好!

public class Solution {
    public int minDistance(String word1, String word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        
        if(len1 == 0) {
            return len2;
        }
        if(len2 == 0) {
            return len1;
        }
        
        int[][] ed = new int[len1+1][len2+1];
        for(int i=0; i<=len1; i++) {
            ed[i][0] = i;
        }
        for(int j=0; j<=len2; j++) {
            ed[0][j] = j;
        }
        
        for(int i=1; i<=len1; i++) {
            for(int j=1; j<=len2; j++) {
                if(word1.charAt(i-1) == word2.charAt(j-1)) {
                    ed[i][j] = ed[i-1][j-1];
                } else {
                    ed[i][j] = Math.min(ed[i-1][j-1], Math.min(ed[i-1][j], ed[i][j-1])) + 1;
                }
            }
        }
        
        return ed[len1][len2];
    }
}