Leetcode 132. Palindrome Partitioning II (python+cpp)

博客详细介绍了LeetCode 132题的解决方案,包括暴力回溯法(TLE)、O(N^3)动态规划和优化后的O(N^2)动态规划解法。重点讲解了动态规划递归方程的逻辑,并阐述了如何通过从字符串中点向外扩张来提高判断回文子串的效率,从而降低时间复杂度。

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

题目

在这里插入图片描述

解法1:backtracking暴力解法(TLE)

class Solution:
    def minCut(self, s: str) -> int:
        def helper(i,count):
            nonlocal ans
            if i==len(s):
                ans = min(ans,count-1)
            
            for j in range(i,len(s)):
                if s[i:j+1]==s[i:j+1][::-1]:
                    helper(j+1,count+1)
        
        if s == s[::-1]:
            return 0
        ans = float('inf')
        helper(0,0)
        return ans

解法2:O(N^3)动态规划

递归方程是:dp[i] = min(dp[j-1]+1 for j in range(1,i+1) if s[j-1:i]==s[j-1:i][::-1])。
这个可以这么理解,dp[i]代表某个位置之前的字符串切分为回文子串需要的最小切分次数。我们遍历i之前所有位置,当s[j:i]否成一个回文串的时候,那么dp[i]和dp[i-j]的关系就定了,也就得到了subproblem。

class Solution:
    def minCut(self, s: str) -> int:
        
        dp = [float('inf')]*(len(s)+1)
        dp[0] = -1
        
        for i in range(1,len(s)+1):
            for j in range(1,i+1):
                if s[j-1:i] == s[j-1:i][::-1]:
                    dp[i] = min(dp[i],dp[j-1]+1)
        return dp[-1]

解法3:O(N^2)动态规划

前面解法可以优化的地方在于,对于最后一段是不是回文,我们还是每次都对整段进行判断的。但当我们判断一个字符串是不是回文的时候,我们其实可以从字符串的中点出发,然后向外扩张,这样子每个子串是不是回文串就可以O(1)判断。所以这时候两层遍历外层遍历代表最后一个子串的中心,内层遍历代表子串长度的一半。需要格外注意的是,子串可能为奇数或者偶数,所以对于中心的判断需要分类讨论

class Solution {
public:
    int INF = 1e9;
    int minCut(string s) {
        int n = s.length();
        vector<int> dp(n+1,INF);
        dp[0] = -1;
        
        for (int i=0;i<n;++i){
            // index i as the center
            for (int j=0;i-j>=0 && i+j<n;++j){
                if (s[i-j]!=s[i+j]){
                    break;
                }
                dp[i+j+1] = min(dp[i+j+1],dp[i-j]+1);
            }
            // index i, i+1 as a center
            for (int j=0;i-j>=0 && i+1+j<n;++j){
                if (s[i-j]!=s[i+1+j]){
                    break;
                }
                dp[i+j+2] = min(dp[i+j+2],dp[i-j]+1);
            }
        }
        return dp[n];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值