判斷兩個字符串的edit distance爲1

from https://leetcode.com/problems/one-edit-distance/ java

正如摘要所說,edit distance是經過變換某些位置的字符使得兩個字符串相同的操做數;而該問題是一個比較有名的動態規劃問題;分別用s和t表示兩個字符串,s(i) 表示s中得第i個字符;用f(i, j)表示s(i)和t(j)的edit distance;那麼有如下的遞推關係:code

f(i, j) = min (leetcode

f(i - 1, j) + 1; //即刪掉s中得第i個字符;字符串

f(i, j - 1) + 1; //即刪掉t中得第j個字符;get

f(i - 1, j - 1); //若是s(i) == t(j)it

f(i - 1, j - 1) + 1; //s(i) != t(j), 因此要作一次替換;class

)static

因此第一種方案是先計算出所給兩個字符串的edit distance,檢查是否等於1;固然,這樣作會超時,由於經過動態規劃計算edit distance的時間複雜度爲O(m * n);word

但這裏仍是給出動態規劃的代碼:di

public static int minDistance(String word1, String word2) {
    if (word1 == null || word1.length() == 0) {
        return word2 == null ? 0 : word2.length();
    }

    if (word2 == null || word2.length() == 0) {
        return word1.length();
    }

    char[] ss = word1.toCharArray();
    char[] ts = word2.toCharArray();

    int[][] m = new int[ss.length + 1][ts.length + 1];

    for (int i = 0; i < m.length; i++) {
        m[i][0] = i;
    }

    for (int j = 0; j < m[0].length; j++) {
        m[0][j] = j;
    }

    for (int i = 1; i < m.length; i++) {
        for (int j = 1; j < m[i].length; j++) {
            int a = m[i - 1][j - 1];
            if (ss[i - 1] != ts[j - 1]) {
                a += 1;
            }

            int b = m[i - 1][j] + 1;
            int c = m[i][j - 1] + 1;
            m[i][j] = Math.min(a, Math.min(b, c));
        }
    }

    return m[ss.length][ts.length];
}

其實仍是要利用題目中要求的edit distance爲1的條件,依次分析如下兩個字符串的狀況:

  1. 若是兩個字符串的長度相差多於1,則確定爲false,由於至少須要刪除兩次字符;

  2. 若是兩個字符串的長度相同,那麼兩個字符串中只能有一個位置的字符不一樣;這種狀況只須要掃描一次就能夠了;

  3. 若是兩個字符串的長度相差1,假設s比t長,那麼除了s中得某個位置,刪掉該字符後,剩餘部分應該徹底相同;

彷佛第三種狀況比較難處理,事實上並不是如此;依次檢查s中得字符,假設處理到了位置i,那麼能夠知道位置i以前的字符s和t中都是相同的,不然的花,s和t中以前若是已經有一個字符不一樣的話,edit distance已經至少爲1了;若是位置s(i) == t(i), 那麼繼續處理下一個字符,若是s(i) != t(i), 須要在t的i位置插入一個字符,而後檢查剩餘的字符是否相同便可;因此,第三種處理也只須要掃描一次;

public boolean isOneEditDistance(String s, String t) {
    int m = s.length();
    int n = t.length();
    if (m == n) {
        return checkSameLength(s.toCharArray(), t.toCharArray());
    } else if (m - n == 1) {
        return checkDiffLength(s.toCharArray(), t.toCharArray());
    } else if (n - m == 1) {
        return checkDiffLength(t.toCharArray(), s.toCharArray());
    } else {
        return false;
    }
}

private boolean checkDiffLength(char[] s, char[] t) {
    for(int i = 0; i < s.length; i++) {
        if(i == t.length) {
            return true;
        }

        if(s[i] == t[i]) {
            continue;
        }

        for(int j = i + 1; j < s.length; j++) {
            if(s[j] != t[j - 1]) {
                return false;
            }
        }
        return true;
    }

    return false;
}

private boolean checkSameLength(char[] s, char[] t) {
    int dist = 0;
    for (int i = 0; i < s.length; i++) {
        if (s[i] != t[i]) {
            dist += 1;
        }
        if (dist > 1) {
            return false;
        }
    }

    return dist == 1;
}
相關文章
相關標籤/搜索