【LEETCODE】72、分割回文串 III 第1278題

package y2019.Algorithm.dynamicprogramming.hard;

/**
 * @Auther: xiaof
 * @Date: 2019/12/11 08:59
 * @Description:  1278. 分割回文串 III
 *
 * 給你一個由小寫字母組成的字符串 s,和一個整數 k。
 * 請你按下面的要求分割字符串:
 * 首先,你可以將 s 中的部分字符修改爲其他的小寫英文字母。
 * 接着,你需要把 s 分割成 k 個非空且不相交的子串,並且每個子串都是迴文串。
 * 請返回以這種方式分割字符串所需修改的最少字符數。
 *
 * 示例 1:
 * 輸入:s = "abc", k = 2
 * 輸出:1
 * 解釋:你可以把字符串分割成 "ab" 和 "c",並修改 "ab" 中的 1 個字符,將它變成迴文串。
 * 示例 2:
 * 輸入:s = "aabbc", k = 3
 * 輸出:0
 * 解釋:你可以把字符串分割成 "aa"、"bb" 和 "c",它們都是迴文串。
 * 示例 3:
 * 輸入:s = "leetcode", k = 8
 * 輸出:0
 *
 * 來源:力扣(LeetCode)
 * 鏈接:https://leetcode-cn.com/problems/palindrome-partitioning-iii
 * 著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
 *
 * 狀態轉移方程:f[i][j] = min {f[i0][j - 1] + cost(s, i0+1, i)}
 *
 */
public class PalindromePartition {

    /**
     * 執行用時 : 22 ms , 在所有 java 提交中擊敗了 40.30% 的用戶
     * 內存消耗 : 34.3 MB , 在所有 java 提交中擊敗了 100.00% 的用戶
     * @param s
     * @param k
     * @return
     *
     * 狀態轉移:f[i][j] = min {f[i0][j - 1] + cost(s, i0+1, i)} 主要參考這個
     * 參考:https://leetcode-cn.com/problems/palindrome-partitioning-iii/solution/fen-ge-hui-wen-chuan-iii-by-leetcode/
     */
    public int solution(String s, int k) {
        int[][] f = new int[s.length() + 1][k];

        for (int i = 0; i <= s.length(); ++i) {
            //當N個字符,分割成k個區域,也就是整個字符作爲迴文的時候
            for (int j = 0; j < k; ++j) {
                if (i == 0) {
                    f[i][j] = 0;
                } else if (j == 0) {
                    f[i][j] = cost(s, 0, i);
                } else {
                    f[i][j] = Integer.MAX_VALUE;
                }
            }
        }
        //其餘節點初始化爲最大值
        //遍歷獲取所有的吧前i個字符,分割成j塊迴文需要修改的字符數
        for (int i = 1; i < f.length; ++i) {
            for (int j = 1; j < f[i].length; ++j) {
                //如果分割點比字符還多,無法分割
                if (i < j) {
                    continue;
                }
                //最後遍歷所有分割點
                for (int x = 1; x <= i; ++x) {
                    //如果分割點比字符還多,無法分割
                    if (x < j) {
                        continue;
                    }
                    f[i][j] = Math.min(f[i][j], f[x][j - 1] + cost(s, x, i));
                }
            }
        }

        return f[s.length()][k - 1];
    }

    public int cost(String s, int l, int r) {
        //判斷前後遍歷的過程中有多少字符不相同
        int index1 = l, index2 = r - 1, res = 0;
        while (index1 < index2) {
            //當沒有相遇的時候
            if (s.charAt(index1) != s.charAt(index2)) {
                res++;
            }
            ++index1;
            --index2;
        }

        return res;
    }

    public static void main(String[] args) {
        String s1 = "abc";
        int k1 = 2;

        String s2 = "aabbc"; int k2 = 3;

        String s3 = "leetcode"; int k3 = 8;

        PalindromePartition fuc = new PalindromePartition();

        fuc.solution(s3, k3);

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章