Loading

Java 实现回文子串解法-中心扩展算法

中心扩展算法

中心扩展算法是解决 Leetcode 回文子串题目的一种算法,主要流程是通过遍历字符串以每次遍历的字符中心数来进行左右两边取值(以中心数位置为基准并未进行移动)并进行循环比较是否相等,比较完后对左右两个偏移量进行移动,移动的步长为 1。

中心数位置是对于当前字符位置是固定的,对于整个字符串的位置是不固定的,因为需要遍历整个字符串,所以中心数的位置会随着遍历的次数发生改变,以下情况都是理想情况(当前遍历次数正好处于整个字符串的中心位置也就是 index = 字符串length/2 + 1 ):

  1. 从中心数位置开始每次向左右两边扩展,定义左右两边每次偏移变量,假如为left(左边)、right(右边),受遍历的限制其实每次 left的起始位置 = 当前遍历下标index,情况如下:

    • 长度为偶数的情况下,left的初始位置 = 回文数长度/2 = index (当前遍历次数),也就是中心数的位置;right = 回文数长度/2 + 1,以下图为例子

      image-20231122155932422
    • 长度为奇数的情况下,left的初始位置 = right的起始位置 = 回文数长度/2 = index (当前遍历次数),以下图为例子

      image-20231122160000675
  2. 因为要循环比较左右两端偏移后得到的字符是否相等,循环的次数受3个条件限制:

    • 左右两端偏移量,左右两端的偏移量受整个字符串长度的限制,而且每次偏移的步长为1,所以left的偏移范围应该为index >= left >= 0,right的取值范围为字符串长度length - 1 >= right >= index
    • 左偏移量的值 == 右偏移量的值,如果相等的情况下代表当前左偏移量下标left ~ 右偏移量下标right,这段长度是一个回文串,可以继续进行循环;如果不相等,代表当前中心数左右两端不存在回文串的情况,可以直接跳过进行下次遍历。

    完整的循环条件为 left>=0 && right <= length -1 && 字符串.indexOf(left) == 字符串.indexOf(right)

以上是以Java为基准的中心扩展算法的流程。

代码实现:

class Solution {
    public int countSubstrings(String s) {
        int num = 0;
        int length = s.length();
        int left;
        int right;
        for (int i = 0; i < length; i++) {
            // 针对给定字符长度为偶数的情况
            left = i;
            right = i + 1;
            num = getNum(s, num, length, left, right);
            
            // 针对给定字符长度为奇数的情况
            right = i;
            num = getNum(s, num, length, left, right);
        }
        return num;
    }
    private static int getNum(String s, int num, int length, int left, int right) {
        while (left >= 0 && right <= length - 1 && (s.charAt(left) == (s.charAt(right)))) {
            --left;
            ++right;
            ++num;
        }
        return num;
    }
}
posted @ 2023-11-22 16:38  plum_wink  阅读(98)  评论(0)    收藏  举报