LeetCode热题(JS版) - 647. 回文子串

107 阅读1分钟

题目描述

给定一个字符串 s,你可以从中选出任意长度大于等于 2 的子串,并将这些子串按任意顺序连接起来。返回所有可能的结果。

注意:你可以以任意顺序返回答案。

示例 1:

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

示例 2:

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

提示:

  • 1 <= s.length <= 1000
  • s仅由小写英文字母组成

解法

根据题目描述,我们需要找出所有可能的回文子串。首先,我们可以通过枚举子串的方式来判断每个子串是否为回文串。具体来说,我们枚举子串的左右边界 l 和 r,满足 0 <= l <= r < len(s),如果子串 s[l, r]s[l,r] 是回文串,那么只要把该子串记录下来即可。

判断回文串可以使用双指针的方法。具体地,两个指针分别指向子串的左右两端,每次判断左右对应的字符是否相同,然后同时向中间移动指针,直到两个指针相遇或者交错。

代码如下:

function countSubstrings(s: string): number {
  let count = 0;
  for (let i = 0; i < s.length; i++) {
    for (let j = i; j < s.length; j++) {
      if (isPalindrome(s, i, j)) {
        count++;
      }
    }
  }
  return count;
}

function isPalindrome(s: string, left: number, right: number): boolean {
  while (left < right) {
    if (s[left] !== s[right]) {
      return false;
    }
    left++;
    right--;
  }
  return true;
}

复杂度分析

时间复杂度:O(n^3),其中 n 是字符串的长度。枚举子串需要 O(n^2) 的时间,判断每个子串是否为回文串需要 O(n) 的时间。

空间复杂度:O(1)。我们只需要常数的空间存放若干变量。

还有一种O(n2)O(n^2)的解法

function countSubstrings(s: string): number {
  let res = 0;
  for (let i = 0; i < s.length; i++) {
    // 奇数长度回文串
    let l = i, r = i;
    while (l >= 0 && r < s.length && s[l] === s[r]) {
      res++;
      l--;
      r++;
    }
    // 偶数长度回文串
    l = i;
    r = i + 1;
    while (l >= 0 && r < s.length && s[l] === s[r]) {
      res++;
      l--;
      r++;
    }
  }
  return res;
}