LeetCode 20 Palindrome Partitioning II

本文介绍了一种使用动态规划解决字符串最小回文切割数的方法。通过定义子问题和状态转移方程,文章详细阐述了如何确定一个字符串是否为回文,并求得将字符串分割成多个回文子串所需的最少切割次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a string s, partition s such that every substring of the partition is a palindrome.

Return the minimum cuts needed for a palindrome partitioning of s.

For example, given s = "aab",

Return 1 since the palindrome partitioning ["aa", "b"] could be produced using 1 cut.

分析:

动态规划

看到最小切割数,首先想到动态规划,之后像怎么提取子问题以及怎么由子问题推出最终问题答案。

假设字符串长度为len

子问题:从 i 到 n-1 的最小切割数,设为cuts[i], 可知,cuts[n-1]=0,因为只有一个字符,初始,cuts[ i ] = len - i -1, 即初始认为只有每一个字符才是一个回文;

状态转移方程: 假设区间 [ i, j ] 上的子串是回文,则 i 处的切割只要在j+1处的最小切割数加1,cuts[i] = min {  cuts[i], cuts[j+1]+1 },

那么,最后cuts[0]就是最后的结果。 

怎么判断字符串是不是回文?

最原始的想法:如果想判断 [ i, j ] 是不是回文,则如果 [i+1, j-1] 是回文, 并且,i, j 位置的字符相等,则 [ i, j ]是回文。

这样的想法首先会想到递归,中介条件是 j-i < 2, 即 i, j 在同一个位置或者相邻。

在递归中,每次都要求解某个区间是不是回文,产生重复子问题,于是想到用动态规划。

用 mat [ i ][ j ] 来表示,区间 [ i, j ] 是不是回文,记录中间结果。

则,如果 mat [ i+1 ][ j-1 ]为true, 同时 i, j 位置字符相等, 则 mat [ i ][ j ] = true.

几个问题:

为什么cuts的长度是 len+1 ?

因为我们要根据状态转移方程计算cuts[len-1],就需要cuts[len]的值。

为什么cuts[len]的值为 -1 ?

因为要满足 cuts[len-1] = cuts[len]。

我看到很多解法是让 cut[len] = 0, cuts[len-1] = 1, 到最后返回cuts[0]-1 都可以得到正确答案,但是从实际意义上却不好理解。既然cuts[i] 表示从字符 i 到末尾的最小切割术,则我们知道 cuts[len-1], 即最后一个字符的最小切割术一定是0,同时从物理意义上来讲,我们最后应该返回从字符0到最后的最小切割数,即cuts[0].

同时,可以认为 位置 len 到最后是一个空串,空串返回-1也是合理的。

基于以上考虑,我认为应该让 cuts[len-1] = 0, cuts[len] = -1.

public class Solution {
    public int minCut(String s) {
        int len = s.length();
        boolean[][] matrix = new boolean[len][len];
        int cuts[] = new int[len+1];
        //初始化cuts,在每一个字符处都切一下
        for(int i=0; i<=len; i++)
            cuts[i] = len-i-1;
        //更新从i到最后的状态
        for(int i=len-1; i>=0; i--){
            for(int j=i; j<len; j++){
                if( (s.charAt(i) == s.charAt(j)&&(j-i<2)) 
                        || (s.charAt(i) == s.charAt(j)&& matrix[i+1][j-1]) ){
                    matrix[i][j] = true;
                    cuts[i] = Math.min(cuts[i], cuts[j+1]+1);
                }
            }
        }
        return cuts[0];
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值