LeetCode刷题--- 分割回文串 II

分割回文串 II

题目链接:

题目

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是

回文串

返回符合要求的 最少分割次数 。

示例 1:

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

示例 2:

输入:s = "a"
输出:0

示例 3:

输入:s = "ab"
输出:1

提示:

  • 1 <= s.length <= 2000
  • s 仅由小写英文字母组成

解法

算法原理与解析

我们这题使用动态规划,我们做这类题目可以分为以下五个步骤

  1. 状态显示
  2. 状态转移方程
  3. 初始化(防止填表时不越界)
  4. 填表顺序
  5. 返回值

  • 状态显示
dp[i] 表示 s [0, i] 区间上的字符串,最少分割的次数。
  • 状态转移方程
状态转移⽅程⼀般都是根据「最后⼀个位置」的信息来分析:设 0 <= j <= i ,那么我们可以 根据 j ~ i 位置上的⼦串是否是回⽂串分成下⾯两类:
  1. [j ,i] 位置上的⼦串能够构成⼀个回⽂串,那么 dp[i] 就等于 [0, j - 1] 区间上最少回⽂串的个数 + 1,即 dp[i] = dp[j - 1] + 1 。
  2. [j ,i] 位置上的子串不能构成⼀个回⽂串,此时 j 位置就不⽤考虑。
由于我们要的是最⼩值,因此应该循环遍历⼀遍 j 的取值,拿到⾥⾯的最⼩值即可。
优化:我们在状态转移⽅程里面分析到,要能够快速判读字符串⾥⾯的⼦串是否回⽂。因此,我们可以先处理⼀个 dp 表,⾥⾯保存所有⼦串是否回⽂的信息
  • 初始化(防止填表时不越界)
观察「状态转移⽅程」,我们会用到 j - 1 位置的值。我们可以思考⼀下当 j == 0 的时候,
表示的区间就是 [0, i] 。如果 [0, i] 区间上的字符串已经是回⽂串了,最小的回⽂串就是 1 了, j 往后的值就不⽤遍历了。
因此,我们可以在循环遍历 j 的值之前处理 j == 0 的情况,然后 j 1 开始循环。
但是,为了防⽌求 min 操作时, 0 ⼲扰结果。我们先把表⾥⾯的值初始化为「⽆穷⼤」。
  • 填表顺序
毫⽆疑问是「从左往右」。
  • 返回值

根据「状态表⽰」,应该返回 dp[n - 1]


代码实现 

class Solution {
public:
    int minCut(string s) 
    {
        int n = s.size();
        vector<vector<bool> > check(n, vector<bool>(n));	// 表示下标以i和j为两头的字符串是否为回文串
        vector<int> dp(n, INT_MAX);							// 表示字符串[0,i]中最少的分割次数	
        
        // 填表check,从下向上填
        for (int i = n - 1; i >= 0; i--)
        {
            for (int j = i; j < n; j++)
            {
                if (s[i] == s[j])
                {
                    check[i][j] = i + 1 < j ? check[i + 1][j - 1] : true;
                }
            }
        }
        // 填表dp,从左往右
        for (int i = 0; i < n; i++)
        {
            if (check[0][i])
                dp[i] = 0;
            else
            {
                for (int j = 1; j <= i; j++)
                {
                    if (check[j][i])
                        dp[i] = min(dp[i], dp[j - 1] + 1);
                }
            }
        }
        return dp[n - 1];
    }
};

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-元清-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值