【精】leetcode - 647. Palindromic Substrings【动态规划 + 回文 + 对称性】

该博客讨论了LeetCode第647题——计算字符串中回文子串的数量。通过分析回文串的性质,特别是其对称性,提出了利用动态规划的方法来解决此问题。文章详细解释了回文串的概念,以及如何从单个字符或成对相同字符开始构造回文串,并给出了简洁的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题目

Given a string, your task is to count how many palindromic substrings in this string.

The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.

Example 1:

Input: "abc"
Output: 3
Explanation: Three palindromic strings: "a", "b", "c".

Example 2:

Input: "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".

Note:

  1. The input string length won't exceed 1000.

题意

给定一个字符串,你的任务是计算在该字符串中有多少个回文子串。

子串如果有不同的起始索引或者结束索引,那么便可以认为是不同的,即使他们包含着相同的字符。

(例子:见以上英文)

分析及解答

(1)什么叫做回文串?(见百度百科:回文串

(2)回文串具有什么性质?

  • 【特性】正读、反读都是一样的字符串。
  • 【另一种说法】左右对称的串。(后面将会用到这个性质进行算法设计)


(3)利用性质寻找算法


前面提到了回文串具有对称的性质,那么我们应该如何利用这个性质呢?让我们观察一下字符串实例(观察图1,图2),我们能够发现:

  • 对称轴】回文串都有某个对称轴(奇数个字符的串对称轴为最中间的字符。偶数不同,偶数的对称轴可以看做两个(如图2)).
  • 回文串的规律当在回文串两端各加入两个相同的字符的时候,形成的新字符仍旧是回文串。(关键
  • 构造回文的初始】我们可以从一个字符,或者两个相同字符开始,运用以上两个规律开始构造回文(不断同时往两边加相同的字符)。

图1:(回文串,奇数个字符)

图2:(回文串,偶数个字符)

解法1:(简洁 + 代码技巧)

public class Solution {
    int count  = 0;
    public int countSubstrings(String s) {
        for(int i = 0;i<s.length();i++){
            helper(s,i,i);
            helper(s,i,i+1);
        }
        return count;
    }
    public void helper(String s, int left, int right){
        while(left >=0 && right < s.length() && s.charAt(left) == s.charAt(right)){
            count++;
            left--;
            right++;
        }

解法2:(我的做法,有些冗余,下标处不太让人用于理解)

  • 【循环语句的使用】像解法1一样,如果将for循环变成while循环,能够节省不少代码量,同时也容易让人读懂。

public class Solution {
    public int countSubstrings(String s) {
       
    	int length = s.length();
        int[][] paliSign = new int[length][length];
        int sum = 0;
        
        sum += length;
        for(int i =0;i < length;i++){
        	paliSign[i][i] = 1;
        	if(i != length -1 && s.charAt(i) == s.charAt(i+1)){
        		paliSign[i][i+1] = 1;
        		sum += 1;
        	}
        }
                
        for(int gap =0; gap <= length-2;gap++){
        	for(int i = 1; i <= length-gap-2; i++){
        		if(paliSign[i][i+gap] == 1 && s.charAt(i-1)== s.charAt(i+gap+1)){
        			paliSign[i-1][i+gap+1]=1;
        			sum += 1;
        		}
        	}
        }

        return sum;
    
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值