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

回文子串-力扣

点击查看在力扣的位置

一、题目:

​ 给你一个字符串 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

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

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

    2.从aaba扩展,可得a,aba两个,则sum + 2

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

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

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

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

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

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

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

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

    综上:sum = 7是正确答案

    你会发现,继续增加扩展比如 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++;
         }
     }
    }
    

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

posted @ 2022-05-14 10:53  何泽  阅读(243)  评论(0)    收藏  举报