LeetCode: Distinct Subsequence

問題描述:java

<pre> Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not). Here is an example: S = "rabbbit", T = "rabbit" Return 3. </pre>code

問題反覆讀了幾遍感受才理解。首先想到的是用遞歸的方法試試:orm

public class DistinctSubsequences {

    private int numDS = 0;

    public int numDistinct(String S, String T) {
        numDS = 0;
        searchSequence(S, T);
        return numDS;
    }

    private void searchSequence(String S, String T) {
        //System.out.println("searchSequence(" + S + ", " + T + ")");
        if (S.length() < T.length()) {
            return;
        }
        if (T.length() == 0) {
            numDS++;
            return;
        }
        int slen = S.length();
        for (int i = 0; i < slen; i++) {
            if (S.charAt(i) == getHead(T)) {
                searchSequence(cutHead(S, i+1), cutHead(T, 1));
            }
        }
    }

    public String cutHead(String s, int begin) {
        return s.substring(begin, s.length());
    }

    public char getHead(String s) {
        return s.charAt(0);
    }
}

提交後報出超時的錯誤。感受上應該能夠用動態規劃來作,由於畢業找工做時,發現不少用遞歸作的題最終解答都是動態規劃,想了好久,發現能夠這樣:遞歸

public class DistinctSubsequences {

    private int numDS = 0;

    public int numDistinct(String S, String T) {
        return dpSearchSequence(S, T);
    }

    private int dpSearchSequence(String S, String T) {
        int slen = S.length();
        int tlen = T.length();
        if (slen < tlen || slen == 0 || tlen == 0) return 0;
        int dp[][] = new int[tlen][slen];
        for (int i = 0; i < tlen; i++) {
            for (int j = i; j < slen; j++) {
                if (T.charAt(i) == S.charAt(j)) {
                    if (i > 0) {
                        dp[i][j] = dp[i-1][j-1]  // S[0..j-1] 中 T[0..i-1] 出現的次數
                                 + dp[i][j-1];   // S[0..j-1] 中 T[0..i] 出現的次數
                        // 例如:計算 abcc 中子序列 abc 次數,能夠這樣遞歸:
                        // recur(abcc, abc) {
                        //   return recur(abc, ab) + recur(abc, abc)
                        // }
                    } else {
                        if (j > 0) {
                            dp[i][j] = dp[i][j-1] + 1;
                        } else {
                            dp[i][j] = 1;
                        }
                    }
                } else {
                    if (j > 0) {
                        dp[i][j] = dp[i][j-1];
                    } else {
                        dp[i][j] = 0;
                    }
                }
            }
        }
        return dp[tlen-1][slen-1];
    }
}

對動態規劃的題仍是很不熟,仍是得多看看啊。rem

相關文章
相關標籤/搜索