回文子串及最长回文子串-简单易懂解法-力扣

回文子串-力扣

点击查看在力扣的位置

一、题目:

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

示例1:

输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"

示例2:

输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

二、解法:

  1. 暴力:列举每一个子串,判断是否是回文子串,是的话count+1

  2. 中心扩展:从里往外扩展至整个字符串,期间是回文子串count+1

  3. 读懂例子你就明白具体是怎么实现中心扩展了

    例如:aaba 从左到右(扩展即左右两边都需要+1

    1.从aaba扩展,由于a处于第1位,得a,则只能够执行一次,使sum + 1

    2.从aaba扩展,可得a,aab两个,但是只有a是,则sum + 1

    3.从aaba扩展,可得b,aba,则sum + 2

    4.从aaba扩展,可得a,则sum + 1

    注意:每一位都算一个回文子串,没有去重的意思,请看上面的示例2

    综上:sum = 5 ,但是,你会发现**这里面有个aaba是回文子串但是没有找出来

    所以这里提出1位扩展是不行的,那么就2位扩展

    根据上面的操作接下来续写2位扩展

    5.从aaba扩展,可得aa,则sum + 1

    6.后面aaba,aaba扩展就没有回文子串了

    综上:sum = 6是正确答案

    你会发现,继续增加扩展比如 aaba 3位扩展则与前面1位重复,4位扩展则与2位重复,所以,就只有1和2扩展两种情况

    *到现在基本上就知道 回文子串的总数 = sum1 + sum2

    暴力算法:

    class Solution {
     public static int countSubstrings(String s) {
         int count = 0; //总计数
         int size = s.length(); //字符串长度
         for (int i = 0; i < size; i++){
             for (int j = i + 1; j <= size; j++){ //这里j=i+1和j<=size是因为下面substring方法i取得到,j取不到
                 String s1 = s.substring(i, j);
                 if (s1.equals(new StringBuffer(s1).reverse().toString())){ //判断是否是回文
                     count++;   //计数+1
                 }
             }
         }
         return count;
     }

    中心扩展算法:

    class Solution {
     public static int countSubstrings(String s) {
          int sum = 0;
          for (int i = 0; i < s.length(); i++){ //遍历字符串
              sum = sum + check(s, i, i) + check(s, i, i + 1);  //1位和2位总和
          }
          return sum;
     }
     public static int check(String s, int left, int right){    //传递参数作为左右指针,指的即所对应的字母
          int count = 0;
          while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
            //由于是从中心扩展,所以从里到外,存在一个回文子串+1
              left--;
              right++;
              count++;
          }
          return count;
      }
    }

    点击去力扣做这道题

    3.进阶题—最长回文子串

    说明:由于前面讲的是暴力算法和中心扩展算法,没有用动态规划来求解,故这里只讲前面两种方法求解,更容易理解接受

    class Solution {
        int max = 0;
        String str = "";
        public String longestPalindrome(String s) {
            //暴力  --  超出时间限制
            //求解方法就是 多设一个长度最大值max进行找出最大子串长度,相应的子串str则是最大的回文子串
            // int max = 0;
            // String str = "";  //这里java需要初始化
            // for (int i = 0; i < s.length(); i++){
            //     for (int j = i + 1; j <= s.length(); j++){
            //         String s1 = s.substring(i, j);
            //         if (s1.equals(new StringBuffer(s1).reverse().toString()) && s1.length() > max){
                            //这里就是更改部分start
            //             max = s1.length();  
            //             str = s1;
                            //end
            //         }
            //     }
            // }
            // return str;
    ​
            //中心扩展
            for (int i = 0; i < s.length(); i++){
                //更改部分start1
                check(s, i, i);
                check(s, i, i+1);
                //end1
            }
            return str;
            
        }
        public void check(String s, int left, int right){
            while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
                String s1 = s.substring(left, right + 1);
                //更改部分start2
                if (max < s1.length()){
                    max = s1.length();
                    str = s1;
                }
                //end2
                left--;
                right++;
            }
        }
    }

    点击此处去做—最长回文子串

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值