力扣132. 分割回文串 II

题目链接

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回符合要求的最少分割次数。

输入: "aab"
输出: 1
解释: 进行一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

分析:
如果按照上一题的写法,应该是求出来所有方案,然后求一下每个List中的元素个数,取一个min再减一就是答案。但是我估计大概率超时。

思路:通过dp,用 dp[i] 表示前 i 个数分割成每个子串都是回文串至少分出多少个(即答案数 + 1)
状态转移:可以枚举 i 前面的点,假设 j 是 i 前面的某个点,那dp[j]就表示前 j 个字符分割成每个字符串都是回文串最少分出多少个。如果 j ~ i 这一段是回文串,那么只需要多切一次,即 dp[i] = dp[j] + 1,将 j 从头枚举到 i 取最小值即可。
一开始我认为如果从 1 ~ i 这一段本身就是个回文串,那么不属于上述的情况,后面发现也属于,因为初始化合法,dp[0] = 0,前0个字符自然不需要切割,那个数一定为0个。如果 1 ~ i 本身是回文串,那就会走 dp[0] + 1,自然就是1。

class Solution {
    public int minCut(String s) {
        int n = s.length();
        boolean[][] f = new boolean[n + 1][n + 1];
        s = " " + s; // dp从1开始比较舒服,不用处理0的特殊情况
        for (int j = 1; j <= n; j ++ ) // 预处理看是不是回文串
            for (int i = 1; i <= j; i ++ )
                if (i == j) f[i][j] = true;
                else if (s.charAt(i) == s.charAt(j)) {
                    if (i + 1 == j || f[i + 1][j - 1]) f[i][j] = true;
                }
                
        int[] dp = new int[n + 1];
        // 先初始无穷大,只有前0个是0
        for (int i = 0; i < n + 1; i ++ ) dp[i] = 100000000;
        dp[0] = 0;
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= i; j ++ )
                if (f[j][i]) // 如果 j ~ i 是回文串
                    dp[i] = Math.min(dp[i], dp[j - 1] + 1);
        return dp[n] - 1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值