LeetCode131/132 分割回文串I/II

代码分析
题目一
暴力法递归

递归分割所有情况,判断分割部分是否是回文串,如果分割部分是回文串,继续分割后面的字符串,直到能全部分割为止,为一种分割情况

class Solution {
public:
    vector<vector<string>>res;
    bool isIsPalindrome(string &s, int left, int right){//判断是否是回文
        while(left<right&&s[left]==s[right])
        {
            left++;
            right--;
        }
        return left>=right;
    }
    void dfs(string &s, int index, vector<string>&vec){//递归查找
        if(index == s.size()){//分割至最后,则能分割完
            res.push_back(vec);
            return;
        }
        for(int i = index; i < s.size(); i++){
            if(isIsPalindrome(s, index, i)){//如果从此处分割是回文串,查找下一分割点
                vec.push_back(s.substr(index, i-index+1));
                dfs(s, i+1, vec);
                vec.pop_back();
            }
        }
    }
    vector<vector<string>> partition(string s) {
        vector<string>vec;//存储每种分割情况数组
        dfs(s,0,vec);
        return res;
    }
};
递归优化

不用对每个分割的字符串判断一次是否是回文串
用中心扩展法或动态规划法,找出所有的回文子串,并记录,当判断分割字符串是回文串时,直接用记录判断

class Solution {
public:
    vector<vector<string>>res;
    void isIsPalindrome(string &s, vector<vector<bool>>&checkPartition){//生成回文子串记录
        for(int i = 0; i < s.size(); i++){
            int left = i,right = i;
            while(left>=0&&right<s.size()&&s[left]==s[right]){
                checkPartition[left--][right++] = 1;
            }
            left = i,right = i+1;
            while(left>=0&&right<s.size()&&s[left]==s[right]){
                checkPartition[left--][right++] = 1;
            }
        }
    }
    void dfs(string &s, int index, vector<string>&vec,vector<vector<bool>>&checkPartition){//递归查找
        if(index == s.size()){
            res.push_back(vec);
            return;
        }
        for(int i = index; i < s.size(); i++){
            if(checkPartition[index][i]){
                vec.push_back(s.substr(index, i-index+1));
                dfs(s, i+1, vec,checkPartition);
                vec.pop_back();
            }
        }
    }
    vector<vector<string>> partition(string s) {
        vector<vector<bool>>checkPartition(s.size(),vector<bool>(s.size(),0));//记录数组
        isIsPalindrome(s,checkPartition);
        vector<string>vec;
        dfs(s,0,vec,checkPartition);
        return res;
    }
};
题目二
记忆化搜索

回溯,从后往前找当前位置所需形成回文的最小分割次数,并保存在记忆数组中

class Solution {
public:
    
    bool isPalindrome(string &s,int left,int right){//判断是否是回文串
        while(left<right){
            if(s[left]!=s[right]){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

    int dfs(string &s, int index, vector<int>&memo){//递归
        if(index==s.size()){//如果遍历到最后,由于分割次数比回文串个数少1,遍历到最后要-1
            return -1;
        }
        if(memo[index]!=-1){//记忆化数组
            return memo[index];
        }
        int k = INT_MAX;
        for(int i = index; i < s.size(); i++){
            if(isPalindrome(s,index,i)){//如果是回文,继续分割,返回最短分割次数+1
                k = min(k, dfs(s,i+1,memo)+1);
            }
        }
        memo[index] = k;
        return k;
    }
    int minCut(string s) {
        vector<int>memo(s.size()+1,-1);
        return dfs(s,0,memo);
    }
};
记忆化搜索优化

不用对每个分割的字符串判断一次是否是回文串
用中心扩展法或动态规划法,找出所有的回文子串,并记录,当判断分割字符串是回文串时,直接用记录判断

class Solution {
public:
    void isPalindrome(string &s,vector<vector<bool>>&palindrome){
        for(int  i = 0; i < s.size(); i++){
            int left = i,right=i;
            while(left>=0&&right<s.size()&&s[left]==s[right]){
                palindrome[left--][right++]=1;
            }
            left = i; right=i+1;
            while(left>=0&&right<s.size()&&s[left]==s[right]){
                palindrome[left--][right++]=1;
            }
        }
    }

    int dfs(string &s, int index, vector<int>&memo,vector<vector<bool>>&palindrome){
        if(index==s.size()){
            return -1;
        }
        if(memo[index]!=-1){
            return memo[index];
        }
        int k = INT_MAX;
        for(int i = index; i < s.size(); i++){
            if(palindrome[index][i]){
                k = min(k, dfs(s,i+1,memo,palindrome)+1);
            }
        }
        memo[index] = k;
        return k;
    }
    int minCut(string s) {
        vector<vector<bool> >palindrome(s.size(),vector<bool>(s.size(),0));
        isPalindrome(s,palindrome);
        vector<int>memo(s.size()+1,-1);
        return dfs(s,0,memo,palindrome);
    }
};
class Solution {
public:
    
    void isPalindrome(string &s,vector<vector<bool>>&palindrome){
        for(int  right = 0; right < s.size(); right++){
            for(int left = 0; left <= right; left++){
                if((right-left<=2||palindrome[left+1][right-1])&&s[left]==s[right]){
                    palindrome[left][right]=1;
                }
            }
        }
    }

    int dfs(string &s, int index, vector<int>&memo,vector<vector<bool>>&palindrome){
        if(index==s.size()){
            return -1;
        }
        if(memo[index]!=-1){
            return memo[index];
        }
        int k = INT_MAX;
        for(int i = index; i < s.size(); i++){
            if(palindrome[index][i]){
                k = min(k, dfs(s,i+1,memo,palindrome)+1);
            }
        }
        memo[index] = k;
        return k;
    }
    int minCut(string s) {
        vector<vector<bool> >palindrome(s.size(),vector<bool>(s.size(),0));
        isPalindrome(s,palindrome);
        vector<int>memo(s.size()+1,-1);
        return dfs(s,0,memo,palindrome);
    }
};
动态规划优化

dp[i]代表当前位置最少分割次数
状态转移方程如下:
dp[i] = min(s[j ~ i]是回文?dp[j])(for j in range(i) )

用中心扩展法或动态规划法,找出所有的回文子串,并记录,当判断分割字符串是回文串时,直接用记录判断

class Solution {
public:
    
    void isPalindrome(string &s,vector<vector<bool>>&palindrome){//中心扩展
        for(int  i = 0; i < s.size(); i++){
            int left = i-1,right=i+1;
            palindrome[i][i]=1;
            while(left>=0&&right<s.size()&&s[left]==s[right]){
                palindrome[left--][right++]=1;
            }
            left = i; right=i+1;
            while(left>=0&&right<s.size()&&s[left]==s[right]){
                palindrome[left--][right++]=1;
            }
        }
    }

    int minCut(string s) {
        vector<vector<bool> >palindrome(s.size(),vector<bool>(s.size(),0));
        isPalindrome(s,palindrome);
        vector<int>dp(s.size()+1,0);
        for(int i = 0; i < s.size(); i++){
            if(palindrome[0][i]){
                dp[i] = 0;
                continue;
            }
            dp[i] = i;
            for(int j = 1; j <= i; j++){
                if(palindrome[j][i]){
                    dp[i] = min(dp[i],dp[j-1]+1);
                }
            }
        }
        return dp[s.size()-1];
    }
};
class Solution {
public:
    
    void isPalindrome(string &s,vector<vector<bool>>&palindrome){//动态规划
        for(int  right = 0; right < s.size(); right++){
            for(int left = 0; left <= right; left++){
                if((right-left<=2||palindrome[left+1][right-1])&&s[left]==s[right]){
                    palindrome[left][right]=1;
                }
            }
        }
    }

    int minCut(string s) {
        vector<vector<bool> >palindrome(s.size(),vector<bool>(s.size(),0));
        isPalindrome(s,palindrome);
        vector<int>dp(s.size()+1,0);
        for(int i = 0; i < s.size(); i++){
            if(palindrome[0][i]){//如果本身是回文串不需要分割,可以节省时间
                dp[i] = 0;
                continue;
            }
            dp[i] = i;//最坏情况每个字符为一个回文串
            for(int j = 1; j <= i; j++){
                if(palindrome[j][i]){//j~i是回文
                    dp[i] = min(dp[i],dp[j-1]+1);//j的上一个位置最少分割次数+1作为i位置的一种分割次数
                }
            }
        }
        return dp[s.size()-1];
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Baal Austin

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

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

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

打赏作者

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

抵扣说明:

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

余额充值