前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Leetcode No.132 分割回文串 II(动态规划)

Leetcode No.132 分割回文串 II(动态规划)

作者头像
week
发布2022-01-06 10:17:50
3330
发布2022-01-06 10:17:50
举报
文章被收录于专栏:用户画像

一、题目描述

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

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

代码语言:javascript
复制
示例 1:
 输入:s = "aab"
 输出:1
 解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
示例 2:
 输入:s = "a"
 输出:0
示例 3:
 输入:s = "ab"
 输出:1
提示:
 1 <= s.length <= 2000
 s 仅由小写英文字母组成

二、解题思路

设 f[i]表示字符串的前缀 s[0..i]的最少分割次数。要想得出 f[i]的值,我们可以考虑枚举 s[0..i] 分割出的最后一个回文串,这样我们就可以写出状态转移方程:

其中 s[j+1..i] 是一个回文串

即我们枚举最后一个回文串的起始位置 j+1,保证 s[j+1..i]是一个回文串,那么 f[i]就可以从 f[j]转移而来,附加 1 次额外的分割次数。

注意到上面的状态转移方程中,我们还少考虑了一种情况,即 s[0..i] 本身就是一个回文串。此时其不需要进行任何分割,即: f[i]=0

那么我们如何知道 s[j+1..i]或者 s[0..i]是否为回文串呢?我们可以使用与

Leetcode No.131 分割回文串(DFS)_公众号:算法攻城狮-CSDN博客

中相同的预处理方法,将字符串 s 的每个子串是否为回文串预先计算出来,即:

设 f(i,j) 表示 s[i..j]是否为回文串,那么有状态转移方程:

其中 ∧ 表示逻辑与运算,即 s[i..j]为回文串,当且仅当其为空串(i>j),其长度为 1(i=j),或者首尾字符相同且 s[i+1..j-1] 为回文串。

这样一来,我们只需要 O(1)的时间就可以判断任意 s[i..j]是否为回文串了。通过动态规划计算出所有的 f 值之后,最终的答案即为 f[n-1],其中 n 是字符串 s 的长度。

三、代码

代码语言:javascript
复制
public class Solution {
    boolean[][] f;
    List<String> ans = new ArrayList<String>();
    int n;
    public int minCut(String s) {
        n = s.length();
        f = new boolean[n][n];
        for (int i = 0; i < n; ++i) {
            Arrays.fill(f[i], true);
        }
        for (int i = n - 1; i >= 0; --i) {
            for (int j = i + 1; j < n; ++j) {
                //判断任意 s[i..j]是否为回文串了
                f[i][j] = (s.charAt(i) == s.charAt(j)) && f[i + 1][j - 1];
            }
        }
        //rs[i] 表示字符串的前缀 s[0..i] 的最少分割次数
        int[] rs=new int[n];
        Arrays.fill(rs, Integer.MAX_VALUE);
        for(int i=0;i<n;i++){
            //假如s[0..i] 本身就是一个回文串,此时不需要进行任何分割
            if(f[0][i]){
                rs[i]=0;
            }else{
                for(int j=0;j<i;j++){
                    //假如以j位置切分, s[j+1..i] 是一个回文串
                    if(f[j+1][i]){
                        //f[i] 就可以从f[j]转移而来,附加1次额外的分割次数
                        rs[i]=Integer.min(rs[i],rs[j]+1);
                    }
                }
            }
        }
        return rs[n-1];
    }

    public static void main(String[] args) {
        Solution solution=new Solution();
        System.out.println(solution.minCut("ab"));
    }
}

四、复杂度分析

时间复杂度:O(n^2),其中 n 是字符串 s 的长度。预处理计算 f 和动态规划计算 rs 的时间复杂度均为 O(n^2)。

空间复杂度:O(n^2),数组 f 需要使用 O(n^2)的空间,数组 rs 需要使用 O(n) 的空间。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/09/25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、题目描述
  • 二、解题思路
  • 三、代码
  • 四、复杂度分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档