回文子串类问题(慢更新...)

在最近枯燥的刷题生活中,遇到了许多关于回文子串的问题,这里总结一下。

        给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。回文字符串 是正着读和倒过来读一样的字符串。子字符串 是字符串中的由连续字符组成的一个序列。具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串

        刚开始遇到这种问题最容易想到的是暴力解法,也就是用for循环来遍历字符串判断其子字符串是否是回文串,从而统计数量。但是这种方法时间复杂度较高,容易超时。

        对于这样的问题大多可以使用动态规划来分析,其实代码随想录上关于本题也有详细的解答,这里也是参考了其解法。

  • 动态规划
class Solution {
        public int countSubstrings(String s) {
           int len = s.length();
           if(len == 0 || s == null) return 0;
           if(len<2) return 1;
           //设置动规数组
           boolean[][] dp = new boolean[len][len];
           //每单个字符也是回文串,初始化一下
            for(int i = 0;i<len;i++){
                dp[i][i] = true;
            }
           char[] chars = s.toCharArray();
           //得到子串,从左到右子串长度减少
           for(int L = 2;L<=len;L++)
               for(int i = 0;i<len;i++) {
                   int j = L + i - 1;
                   if (j >= len) break;

                   if (chars[i] != chars[j]) {
                       dp[i][j] = false;
                   } else {
                       if (j - i < 3) {
                           dp[i][j] = true;
                       } else {
                           dp[i][j] = dp[i + 1][j - 1];
                       }
                   }
               }
           //统计回文串的数量
           int sum = 0;
           for(int i = 0;i<len;i++)
               for(int j =0;j<len;j++){
                   if(dp[i][j]){
                       sum++;
                   }
               }
           return sum;
        }
    }

        本题也可以使用双指针法来解决

  • 双指针

        其实也可以称作为中心扩展,因为解题思想就是从中心出发,向外扩散,看两端的字符是否相等从而来判断是否为回文串。只不过要考虑中心字符为一个和两个的情况。

class Solution {
         public int countSubstrings(String s) {
             int len  = s.length();
             int sum = 0;
             if(s == null || s.length()<1) return 0;

             for(int i = 0;i<len*2-1;i++){
                 int left = i/2;
                 int right = left + i%2;
                 while(left>=0 && right<len && s.charAt(left) == s.charAt(right)){
                     sum++;
                     left--;
                     right++;
                 }
             }
             return sum;
         }
    }

        给你一个字符串 s,找到 s 中最长的回文子串。如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

        该题和上面的回文子串解题方式大致相同,只不过这里需要求的是最长回文子串,以动态规划方式解题为例,我们只需要在遍历的时候维护一个最长长度maxLen变量,不断更新就可以了。

  • 动态规划
class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
           if(len<2) return s;
           int maxLen = 1;
           int begin = 0;
           boolean[][] dp = new boolean[len][len];

           for(int i =0;i<len;i++){
               dp[i][i] = true;
           }

           char[] arr = s.toCharArray();
           for(int L= 2;L<=len;L++){
               for(int i =0 ;i<len;i++){
                   int j = L+i-1;
                   if(j>=len) break;

                   if(arr[i] != arr[j]){
                       dp[i][j] = false;
                   }else{
                       if(j-i<3){
                           dp[i][j] = true;
                       }else{
                           dp[i][j] = dp[i+1][j-1];
                       }
                   }
                   if(dp[i][j] && j-i+1 > maxLen){
                       maxLen = j-i+1;
                       begin = i;
                   }
               }
           }
           return s.substring(begin,begin+maxLen);
    }
}

本博客只作为笔记使用,如有错误还需海涵,也望多多指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值