回文子串-力扣

本题要求回文子串,自己想到的解法是记录前一位字符串的回文子串次数,然后判断当前字符串的回文子串次数,时间复杂度高达O(n^3);

class Solution {
public:
    bool isPalindrome(const string& s, int start, int end){
        for (int i = start, j = end; i < j; i++, j--) {
            if (s[i] != s[j]) {
                return false;
            }
        }
        return true;        
    }
    int countSubstrings(string s) {
        vector<int> dp(s.size(), 1);
        for(int i = 0; i < s.size(); i++){
            for(int start = 0; start < i; start++){
                if(isPalindrome(s, start, i)){
                    dp[i]++;
                }
            }
            if(i > 0){
                dp[i] += dp[i - 1];
            }
        }
        return dp[s.size() - 1];
    }
};

学习了代码随想录 动态规划解法,在定义dp数组时,不是定义成字符串前 i 个字符回文子串的个数,而是布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。

  • 布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。
  • 当s[i]与s[j]不相等,那没啥好说的了,dp[i][j]一定是false。
  • 当s[i]与s[j]相等时,这就复杂一些了,有如下三种情况
    情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串
    情况二:下标i 与 j相差为1,例如aa,也是回文子串
    情况三:下标:i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1区间,这个区间是不是回文就看dp[i + 1][j - 1]是否为true。
  • dp[i][j]初始化为false
  • 从递推公式中可以看出,情况三是根据dp[i + 1][j - 1]是否为true,在对dp[i][j]进行赋值true的,dp[i + 1][j - 1] 在 dp[i][j]的左下角,所以一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的
class Solution {
public:
    int countSubstrings(string s) {
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
        int num = 0;
        for(int i = s.size() - 1; i >= 0; i--){
            for(int j = i; j < s.size(); j++){
                if(s[i] == s[j]){
                    if(j - i <= 1){
                        dp[i][j] = true;
                        num++;
                    }else if(dp[i + 1][j - 1]){
                        dp[i][j] = true;
                        num++;
                    }
                }
            }
        }
        return num;
    }
};

注:本题最初使用size_t 类型的 i,j进行遍历,发现同样的代码,此时会超时,经过尝试,发现问题出现在了for(size_t i = s.size() - 1; i >= 0; i–) 这个逆序遍历这里,size_t 是一个无符号数,当为 0 时,size_t-- 将其变为了最大的无符号数,从而变成了一个死循环

  • 31
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值